| ; 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: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], 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: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], 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 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)), i1 false |
| ; CHECK-NEXT: ret i1 [[C15]] |
| ; |
| %not.L = xor i1 %L, true |
| %C15 = select i1 %not.L, i1 xor (i1 add (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp ne (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @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 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) |
| ; CHECK-NEXT: ret i1 [[C15]] |
| ; |
| %not.L = xor i1 %L, true |
| %C15 = select i1 %not.L, i1 true, i1 xor (i1 add (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp ne (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)), i1 true) |
| ret i1 %C15 |
| } |
| |
| define i1 @and_or1(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @and_or1( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[B:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 [[TMP1]], i1 false |
| ; 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:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false |
| ; 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_commuted(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @and_or1_commuted( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[B:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 [[TMP1]], i1 false |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %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_commuted(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @and_or2_commuted( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notc = xor i1 %c, true |
| %cond = and i1 %b, %notc |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @and_or1_multiuse(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @and_or1_multiuse( |
| ; 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 @and_or2_multiuse(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @and_or2_multiuse( |
| ; 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 <2 x i1> @and_or1_vec(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @and_or1_vec( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[B:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer |
| ; 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> %nota, %c |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @and_or2_vec(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @and_or2_vec( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = call <2 x i1> @gen_v2i1() |
| %notc = xor <2 x i1> %c, <i1 true, i1 true> |
| %cond = and <2 x i1> %notc, %b |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @and_or1_vec_commuted(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @and_or1_vec_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[B:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer |
| ; 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 |
| } |
| |
| define <2 x i1> @and_or2_vec_commuted(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @and_or2_vec_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = call <2 x i1> @gen_v2i1() |
| %notc = xor <2 x i1> %c, <i1 true, i1 true> |
| %cond = and <2 x i1> %b, %notc |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define i1 @and_or1_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) { |
| ; CHECK-LABEL: @and_or1_wrong_operand( |
| ; 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 @and_or2_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) { |
| ; CHECK-LABEL: @and_or2_wrong_operand( |
| ; 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 i1 @and_or3(i1 %a, i1 %b, i32 %x, i32 %y) { |
| ; CHECK-LABEL: @and_or3( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 true, i1 [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = and i1 %b, %c |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @and_or3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) { |
| ; CHECK-LABEL: @and_or3_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 true, i1 [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = and i1 %c, %b |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @and_or3_not_free_to_invert(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @and_or3_not_free_to_invert( |
| ; CHECK-NEXT: [[COND:%.*]] = and i1 [[B:%.*]], [[C:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %cond = and i1 %b, %c |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @and_or3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) { |
| ; CHECK-LABEL: @and_or3_multiuse( |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[COND:%.*]] = and i1 [[C]], [[B:%.*]] |
| ; CHECK-NEXT: call void @use(i1 [[COND]]) |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = and i1 %b, %c |
| call void @use(i1 %cond) |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define <2 x i1> @and_or3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) { |
| ; CHECK-LABEL: @and_or3_vec( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = icmp eq <2 x i32> %x, %y |
| %cond = and <2 x i1> %b, %c |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @and_or3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) { |
| ; CHECK-LABEL: @and_or3_vec_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = icmp eq <2 x i32> %x, %y |
| %cond = and <2 x i1> %c, %b |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define i1 @and_or3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) { |
| ; CHECK-LABEL: @and_or3_wrong_operand( |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[COND:%.*]] = and i1 [[C]], [[B:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[D:%.*]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = and i1 %b, %c |
| %r = select i1 %cond, i1 %a, i1 %d |
| ret i1 %r |
| } |
| |
| define i1 @or_and1(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and1( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[TMP1]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notb = xor i1 %b, true |
| %cond = and i1 %notb, %c |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and2(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and2( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 false |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notc = xor i1 %c, true |
| %cond = or i1 %notc, %a |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and1_commuted(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and1_commuted( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[TMP1]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notb = xor i1 %b, true |
| %cond = and i1 %c, %notb |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and2_commuted(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and2_commuted( |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 false |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notc = xor i1 %c, true |
| %cond = or i1 %a, %notc |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and1_multiuse(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and1_multiuse( |
| ; CHECK-NEXT: [[NOTB:%.*]] = xor i1 [[B:%.*]], true |
| ; CHECK-NEXT: [[COND:%.*]] = and i1 [[NOTB]], [[C:%.*]] |
| ; CHECK-NEXT: call void @use(i1 [[COND]]) |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notb = xor i1 %b, true |
| %cond = and i1 %notb, %c |
| call void @use(i1 %cond) |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and2_multiuse(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and2_multiuse( |
| ; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true |
| ; CHECK-NEXT: [[COND:%.*]] = or i1 [[NOTC]], [[A:%.*]] |
| ; 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 = or i1 %notc, %a |
| call void @use(i1 %cond) |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define <2 x i1> @or_and1_vec(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @or_and1_vec( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = call <2 x i1> @gen_v2i1() |
| %notb = xor <2 x i1> %b, <i1 true, i1 true> |
| %cond = and <2 x i1> %c, %notb |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @or_and2_vec(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @or_and2_vec( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = call <2 x i1> @gen_v2i1() |
| %notc = xor <2 x i1> %c, <i1 true, i1 true> |
| %cond = or <2 x i1> %a, %notc |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @or_and1_vec_commuted(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @or_and1_vec_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = call <2 x i1> @gen_v2i1() |
| %notb = xor <2 x i1> %b, <i1 true, i1 true> |
| %cond = and <2 x i1> %notb, %c |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @or_and2_vec_commuted(<2 x i1> %a, <2 x i1> %b) { |
| ; CHECK-LABEL: @or_and2_vec_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = call <2 x i1> @gen_v2i1() |
| %notc = xor <2 x i1> %c, <i1 true, i1 true> |
| %cond = or <2 x i1> %notc, %a |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define i1 @or_and1_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) { |
| ; CHECK-LABEL: @or_and1_wrong_operand( |
| ; CHECK-NEXT: [[NOTB:%.*]] = xor i1 [[B:%.*]], true |
| ; CHECK-NEXT: [[COND:%.*]] = and i1 [[NOTB]], [[C:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[D:%.*]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notb = xor i1 %b, true |
| %cond = and i1 %c, %notb |
| %r = select i1 %cond, i1 %a, i1 %d |
| ret i1 %r |
| } |
| |
| define i1 @or_and2_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) { |
| ; CHECK-LABEL: @or_and2_wrong_operand( |
| ; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true |
| ; CHECK-NEXT: [[COND:%.*]] = or i1 [[NOTC]], [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[D:%.*]], i1 [[B:%.*]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %notc = xor i1 %c, true |
| %cond = or i1 %a, %notc |
| %r = select i1 %cond, i1 %d, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @pr64558(i1 noundef %a, i1 noundef %b) { |
| ; CHECK-LABEL: @pr64558( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND_V:%.*]] = or i1 [[B:%.*]], [[A:%.*]] |
| ; CHECK-NEXT: ret i1 [[COND_V]] |
| ; |
| entry: |
| %lnot = xor i1 %b, true |
| %and11 = and i1 %lnot, %a |
| %cond.v = select i1 %and11, i1 %a, i1 %b |
| ret i1 %cond.v |
| } |
| |
| define i1 @or_and3(i1 %a, i1 %b, i32 %x, i32 %y) { |
| ; CHECK-LABEL: @or_and3( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = or i1 %a, %c |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) { |
| ; CHECK-LABEL: @or_and3_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = or i1 %c, %a |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and3_not_free_to_invert(i1 %a, i1 %b, i1 %c) { |
| ; CHECK-LABEL: @or_and3_not_free_to_invert( |
| ; CHECK-NEXT: [[COND:%.*]] = or i1 [[A:%.*]], [[C:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %cond = or i1 %a, %c |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define i1 @or_and3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) { |
| ; CHECK-LABEL: @or_and3_multiuse( |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[COND:%.*]] = or i1 [[C]], [[A:%.*]] |
| ; CHECK-NEXT: call void @use(i1 [[COND]]) |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = or i1 %a, %c |
| call void @use(i1 %cond) |
| %r = select i1 %cond, i1 %a, i1 %b |
| ret i1 %r |
| } |
| |
| define <2 x i1> @or_and3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) { |
| ; CHECK-LABEL: @or_and3_vec( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = icmp eq <2 x i32> %x, %y |
| %cond = or <2 x i1> %a, %c |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define <2 x i1> @or_and3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) { |
| ; CHECK-LABEL: @or_and3_vec_commuted( |
| ; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer |
| ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[TMP1]] |
| ; CHECK-NEXT: ret <2 x i1> [[R]] |
| ; |
| %c = icmp eq <2 x i32> %x, %y |
| %cond = or <2 x i1> %c, %a |
| %r = select <2 x i1> %cond, <2 x i1> %a, <2 x i1> %b |
| ret <2 x i1> %r |
| } |
| |
| define i1 @or_and3_wrong_operand(i1 %a, i1 %b, i32 %x, i32 %y, i1 %d) { |
| ; CHECK-LABEL: @or_and3_wrong_operand( |
| ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[COND:%.*]] = or i1 [[C]], [[A:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[D:%.*]], i1 [[B:%.*]] |
| ; CHECK-NEXT: ret i1 [[R]] |
| ; |
| %c = icmp eq i32 %x, %y |
| %cond = or i1 %a, %c |
| %r = select i1 %cond, i1 %d, i1 %b |
| ret i1 %r |
| } |