; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=instcombine < %s | FileCheck %s declare void @use(i1) declare i1 @gen_i1() declare <2 x i1> @gen_v2i1() ; Should not be converted to "and", which has different poison semantics. define i1 @logical_and(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_and( ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %b, i1 false ret i1 %res } ; Should not be converted to "or", which has different poison semantics. define i1 @logical_or(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_or( ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 true, i1 %b ret i1 %res } ; Canonicalize to logical and form, even if that requires adding a "not". define i1 @logical_and_not(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_and_not( ; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 false, i1 %b ret i1 %res } ; Canonicalize to logical or form, even if that requires adding a "not". define i1 @logical_or_not(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_or_not( ; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %b, i1 true ret i1 %res } ; These are variants where condition or !condition is used to represent true ; or false in one of the select arms. It should be canonicalized to the ; constants. define i1 @logical_and_cond_reuse(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_and_cond_reuse( ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %b, i1 %a ret i1 %res } define i1 @logical_or_cond_reuse(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_or_cond_reuse( ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %a, i1 %b ret i1 %res } define i1 @logical_and_not_cond_reuse(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_and_not_cond_reuse( ; CHECK-NEXT: [[A_NOT:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A_NOT]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %a.not = xor i1 %a, true %res = select i1 %a, i1 %b, i1 %a.not ret i1 %res } define i1 @logical_or_not_cond_reuse(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_or_not_cond_reuse( ; CHECK-NEXT: [[A_NOT:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A_NOT]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[RES]] ; %a.not = xor i1 %a, true %res = select i1 %a, i1 %a.not, i1 %b ret i1 %res } ; Safe to convert to or due to poison implication. define i1 @logical_or_implies(i32 %x) { ; CHECK-LABEL: @logical_or_implies( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[X:%.*]], 0 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X]], 42 ; CHECK-NEXT: [[RES:%.*]] = or i1 [[C1]], [[C2]] ; CHECK-NEXT: ret i1 [[RES]] ; %c1 = icmp eq i32 %x, 0 %c2 = icmp eq i32 %x, 42 %res = select i1 %c1, i1 true, i1 %c2 ret i1 %res } ; Will fold after conversion to or. define i1 @logical_or_implies_folds(i32 %x) { ; CHECK-LABEL: @logical_or_implies_folds( ; CHECK-NEXT: ret i1 true ; %c1 = icmp slt i32 %x, 0 %c2 = icmp sge i32 %x, 0 %res = select i1 %c1, i1 true, i1 %c2 ret i1 %res } ; Safe to convert to and due to poison implication. define i1 @logical_and_implies(i32 %x) { ; CHECK-LABEL: @logical_and_implies( ; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[X]], 42 ; CHECK-NEXT: [[RES:%.*]] = and i1 [[C1]], [[C2]] ; CHECK-NEXT: ret i1 [[RES]] ; %c1 = icmp ne i32 %x, 0 %c2 = icmp ne i32 %x, 42 %res = select i1 %c1, i1 %c2, i1 false ret i1 %res } ; Will fold after conversion to and. define i1 @logical_and_implies_folds(i32 %x) { ; CHECK-LABEL: @logical_and_implies_folds( ; CHECK-NEXT: [[C1:%.*]] = icmp ugt i32 [[X:%.*]], 42 ; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp ugt i32 %x, 42 %c2 = icmp ne i32 %x, 0 %res = select i1 %c1, i1 %c2, i1 false ret i1 %res } ; Noundef on condition has no effect. define i1 @logical_or_noundef_a(i1 noundef %a, i1 %b) { ; CHECK-LABEL: @logical_or_noundef_a( ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 true, i1 %b ret i1 %res } ; Noundef on false value allows conversion to or. define i1 @logical_or_noundef_b(i1 %a, i1 noundef %b) { ; CHECK-LABEL: @logical_or_noundef_b( ; CHECK-NEXT: [[RES:%.*]] = or i1 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 true, i1 %b ret i1 %res } ; Noundef on condition has no effect. define i1 @logical_and_noundef_a(i1 noundef %a, i1 %b) { ; CHECK-LABEL: @logical_and_noundef_a( ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %b, i1 false ret i1 %res } ; Noundef on false value allows conversion to and. define i1 @logical_and_noundef_b(i1 %a, i1 noundef %b) { ; CHECK-LABEL: @logical_and_noundef_b( ; CHECK-NEXT: [[RES:%.*]] = and i1 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %b, i1 false ret i1 %res } ; (!x && !y) || x --> x || !y define i1 @not_not_true(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_true( ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[NOTY]] ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true %r = select i1 %notx, i1 %noty, i1 true ret i1 %r } ; (!x && !y) --> !(x || y) define i1 @not_not_false(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_false( ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true %r = select i1 %notx, i1 %noty, i1 false ret i1 %r } ; (!x || !y) --> !(x && y) define i1 @not_true_not(i1 %x, i1 %y) { ; CHECK-LABEL: @not_true_not( ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true %r = select i1 %notx, i1 true, i1 %noty ret i1 %r } ; (!!x && !y) --> x && !y define i1 @not_false_not(i1 %x, i1 %y) { ; CHECK-LABEL: @not_false_not( ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true %r = select i1 %notx, i1 false, i1 %noty ret i1 %r } define i1 @not_not_true_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_true_use1( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 true, i1 [[NOTY]] ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true %r = select i1 %notx, i1 %noty, i1 true ret i1 %r } define i1 @not_not_false_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_false_use1( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X]], i1 true, i1 [[Y:%.*]] ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true %r = select i1 %notx, i1 %noty, i1 false ret i1 %r } define i1 @not_true_not_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_true_not_use1( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X]], i1 [[Y:%.*]], i1 false ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true %r = select i1 %notx, i1 true, i1 %noty ret i1 %r } define i1 @not_false_not_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_false_not_use1( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 [[NOTY]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true %r = select i1 %notx, i1 false, i1 %noty ret i1 %r } define i1 @not_not_true_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_true_use2( ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[NOTY]] ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 %noty, i1 true ret i1 %r } define i1 @not_not_false_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_false_use2( ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y]] ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 %noty, i1 false ret i1 %r } define i1 @not_true_not_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @not_true_not_use2( ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 true, i1 %noty ret i1 %r } define i1 @not_false_not_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @not_false_not_use2( ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 false, i1 %noty ret i1 %r } define i1 @not_not_true_use3(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_true_use3( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 true, i1 [[NOTY]] ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 %noty, i1 true ret i1 %r } define i1 @not_not_false_use3(i1 %x, i1 %y) { ; CHECK-LABEL: @not_not_false_use3( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTX]], i1 [[NOTY]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 %noty, i1 false ret i1 %r } define i1 @not_true_not_use3(i1 %x, i1 %y) { ; CHECK-LABEL: @not_true_not_use3( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTX]], i1 true, i1 [[NOTY]] ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 true, i1 %noty ret i1 %r } define i1 @not_false_not_use3(i1 %x, i1 %y) { ; CHECK-LABEL: @not_false_not_use3( ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTX]]) ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true ; CHECK-NEXT: call void @use(i1 [[NOTY]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 [[NOTY]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %notx = xor i1 %x, true call void @use(i1 %notx) %noty = xor i1 %y, true call void @use(i1 %noty) %r = select i1 %notx, i1 false, i1 %noty ret i1 %r } ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399 @g1 = external global i16 @g2 = external global i16 define i1 @demorgan_select_infloop1(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop1( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true ; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true %C15 = select i1 %not.L, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false ret i1 %C15 } define i1 @demorgan_select_infloop2(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop2( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true ; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true) ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true %C15 = select i1 %not.L, i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true) ret i1 %C15 } define i1 @and_or1(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @and_or1( ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %nota = xor i1 %a, true %cond = or i1 %nota, %c %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @and_or2(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @and_or2( ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[A:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %notc = xor i1 %c, true %cond = and i1 %notc, %b %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @and_or1_bundef(i1 %a, i1 noundef %b, i1 %c) { ; CHECK-LABEL: @and_or1_bundef( ; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[C:%.*]], [[B:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %nota = xor i1 %a, true %cond = or i1 %nota, %c %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @and_or2_aundef(i1 noundef %a, i1 %b, i1 %c) { ; CHECK-LABEL: @and_or2_aundef( ; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[C:%.*]], [[A:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %notc = xor i1 %c, true %cond = and i1 %notc, %b %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @no_and_or1_bundef(i1 %a, i1 noundef %b, i1 %c) { ; CHECK-LABEL: @no_and_or1_bundef( ; CHECK-NEXT: [[NOTA:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[COND:%.*]] = or i1 [[NOTA]], [[C:%.*]] ; CHECK-NEXT: call void @use(i1 [[COND]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %nota = xor i1 %a, true %cond = or i1 %nota, %c call void @use(i1 %cond) %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @no_and_or2_aundef(i1 noundef %a, i1 %b, i1 %c) { ; CHECK-LABEL: @no_and_or2_aundef( ; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true ; CHECK-NEXT: [[COND:%.*]] = and i1 [[NOTC]], [[B:%.*]] ; CHECK-NEXT: call void @use(i1 [[COND]]) ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]] ; CHECK-NEXT: ret i1 [[R]] ; %notc = xor i1 %c, true %cond = and i1 %notc, %b call void @use(i1 %cond) %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @and_or1_op1not(i1 %a, i1 %b) { ; CHECK-LABEL: @and_or1_op1not( ; CHECK-NEXT: [[C:%.*]] = call i1 @gen_i1() ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[C]], [[TMP1]] ; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %c = call i1 @gen_i1() %nota = xor i1 %a, true %cond = or i1 %c, %nota %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @and_or2_op1not(i1 %a, i1 %c) { ; CHECK-LABEL: @and_or2_op1not( ; CHECK-NEXT: [[B:%.*]] = call i1 @gen_i1() ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[A:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: [[R:%.*]] = and i1 [[B]], [[TMP2]] ; CHECK-NEXT: ret i1 [[R]] ; %b = call i1 @gen_i1() %notc = xor i1 %c, true %cond = and i1 %b, %notc %r = select i1 %cond, i1 %a, i1 %b ret i1 %r } define i1 @neg_and_or1(i1 %a, i1 %b, i1 %c, i1 %d) { ; CHECK-LABEL: @neg_and_or1( ; CHECK-NEXT: [[NOTA:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[COND:%.*]] = or i1 [[NOTA]], [[C:%.*]] ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[D:%.*]], i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %nota = xor i1 %a, true %cond = or i1 %nota, %c %r = select i1 %cond, i1 %d, i1 %b ret i1 %r } define i1 @neg_and_or2(i1 %a, i1 %b, i1 %c, i1 %d) { ; CHECK-LABEL: @neg_and_or2( ; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true ; CHECK-NEXT: [[COND:%.*]] = and i1 [[NOTC]], [[B:%.*]] ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[D:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %notc = xor i1 %c, true %cond = and i1 %notc, %b %r = select i1 %cond, i1 %a, i1 %d ret i1 %r } define <2 x i1> @and_or1_op1not_vec(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @and_or1_op1not_vec( ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() ; CHECK-NEXT: [[TMP1:%.*]] = freeze <2 x i1> [[B:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i1> [[C]], [[TMP1]] ; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP2]], [[A:%.*]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %c = call <2 x i1> @gen_v2i1() %nota = xor <2 x i1> %a, <i1 true, i1 true> %cond = or <2 x i1> %c, %nota %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b ret <2 x i1> %r }