Files
clang-p2996/llvm/test/Transforms/InstCombine/select-and-or.ll
Nikita Popov a105877646 [InstCombine] Remove some of the complexity-based canonicalization (#91185)
The idea behind this canonicalization is that it allows us to handle less
patterns, because we know that some will be canonicalized away. This is
indeed very useful to e.g. know that constants are always on the right.

However, this is only useful if the canonicalization is actually
reliable. This is the case for constants, but not for arguments: Moving
these to the right makes it look like the "more complex" expression is
guaranteed to be on the left, but this is not actually the case in
practice. It fails as soon as you replace the argument with another
instruction.

The end result is that it looks like things correctly work in tests,
while they actually don't. We use the "thwart complexity-based
canonicalization" trick to handle this in tests, but it's often a
challenge for new contributors to get this right, and based on the
regressions this PR originally exposed, we clearly don't get this right
in many cases.

For this reason, I think that it's better to remove this complexity
canonicalization. It will make it much easier to write tests for
commuted cases and make sure that they are handled.
2024-08-21 12:02:54 +02:00

1323 lines
43 KiB
LLVM

; 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: ret i1 [[NOT_L]]
;
%not.L = xor i1 %L, true
%cmp = icmp eq ptr getelementptr inbounds (i16, ptr @g2, i64 1), @g1
%add = add i1 %cmp, %cmp
%xor = xor i1 %add, true
%C15 = select i1 %not.L, i1 %xor, 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: [[CMP2:%.*]] = icmp ne ptr getelementptr inbounds (i8, ptr @g2, i64 2), @g1
; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 [[CMP2]], i1 false
; CHECK-NEXT: ret i1 [[C15]]
;
%not.L = xor i1 %L, true
%cmp1 = icmp eq ptr getelementptr inbounds (i16, ptr @g1, i64 1), @g1
%cmp2 = icmp eq ptr getelementptr inbounds (i16, ptr @g2, i64 1), @g1
%add = add i1 %cmp1, %cmp2
%xor = xor i1 %add, true
%C15 = select i1 %not.L, i1 %xor, i1 false
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 [[C:%.*]], [[NOTA]]
; 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 [[B:%.*]], [[NOTC]]
; 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 [[C:%.*]], [[NOTA]]
; 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 [[B:%.*]], [[NOTC]]
; 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: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[A:%.*]]
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP2]], 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: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[A:%.*]]
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP2]], 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 [[B:%.*]], [[C]]
; 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: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP2]], <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: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP2]], <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 [[B:%.*]], [[C]]
; 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 [[C:%.*]], [[NOTB]]
; 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 [[A:%.*]], [[NOTC]]
; 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 [[C:%.*]], [[NOTB]]
; 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 [[A:%.*]], [[NOTC]]
; 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: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 false
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP2]]
; 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: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 false
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP2]]
; 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 [[A:%.*]], [[C]]
; 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: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <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> [[TMP2]]
; 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: [[TMP1:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <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> [[TMP2]]
; 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 [[A:%.*]], [[C]]
; 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
}
define i8 @test_or_umax(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_or_umax(
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[X]], i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%or = select i1 %cond, i1 true, i1 %cmp
%ret = select i1 %or, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_or_umin(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_or_umin(
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[Y]], i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%or = select i1 %cond, i1 true, i1 %cmp
%ret = select i1 %or, i8 %y, i8 %x
ret i8 %ret
}
define i8 @test_and_umax(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_and_umax(
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[TMP1]], i8 [[Y]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%and = select i1 %cond, i1 %cmp, i1 false
%ret = select i1 %and, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_and_umin(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_and_umin(
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[TMP1]], i8 [[X]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%and = select i1 %cond, i1 %cmp, i1 false
%ret = select i1 %and, i8 %y, i8 %x
ret i8 %ret
}
define i8 @test_or_umax_bitwise1(i8 %x, i8 %y, i8 %val) {
; CHECK-LABEL: @test_or_umax_bitwise1(
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
%cmp = icmp ugt i8 %x, %y
%or = or i1 %cond, %cmp
%ret = select i1 %or, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_or_umax_bitwise2(i8 %x, i8 %y, i8 %val) {
; CHECK-LABEL: @test_or_umax_bitwise2(
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
%cmp = icmp ugt i8 %x, %y
%or = or i1 %cmp, %cond
%ret = select i1 %or, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_and_umax_bitwise1(i8 %x, i8 %y, i8 %val) {
; CHECK-LABEL: @test_and_umax_bitwise1(
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[TMP1]], i8 [[Y]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
%cmp = icmp ugt i8 %x, %y
%and = and i1 %cond, %cmp
%ret = select i1 %and, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_and_umax_bitwise2(i8 %x, i8 %y, i8 %val) {
; CHECK-LABEL: @test_and_umax_bitwise2(
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[VAL:%.*]], 0
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND]], i8 [[TMP1]], i8 [[Y]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cond = icmp eq i8 %val, 0 ; thwart complexity-based ordering
%cmp = icmp ugt i8 %x, %y
%and = and i1 %cmp, %cond
%ret = select i1 %and, i8 %x, i8 %y
ret i8 %ret
}
; Other SPFs
define i8 @test_or_smax(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_or_smax(
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[X]], i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp sgt i8 %x, %y
%or = select i1 %cond, i1 true, i1 %cmp
%ret = select i1 %or, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_or_abs(i8 %x, i1 %cond) {
; CHECK-LABEL: @test_or_abs(
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 [[X]], i8 [[TMP1]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp sgt i8 %x, -1
%neg = sub nsw i8 0, %x
%or = select i1 %cond, i1 true, i1 %cmp
%ret = select i1 %or, i8 %x, i8 %neg
ret i8 %ret
}
; TODO: fold SPF_FMAXNUM
define float @test_or_fmaxnum(float %x, float %y, i1 %cond) {
; CHECK-LABEL: @test_or_fmaxnum(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[OR:%.*]] = select i1 [[COND:%.*]], i1 true, i1 [[CMP]]
; CHECK-NEXT: [[RET:%.*]] = select i1 [[OR]], float [[X]], float [[Y]]
; CHECK-NEXT: ret float [[RET]]
;
%cmp = fcmp nnan ogt float %x, %y
%or = select i1 %cond, i1 true, i1 %cmp
%ret = select i1 %or, float %x, float %y
ret float %ret
}
; Negative tests
define i8 @test_or_umax_invalid_logical(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_or_umax_invalid_logical(
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP]], i1 true, i1 [[COND:%.*]]
; CHECK-NEXT: [[RET:%.*]] = select i1 [[OR]], i8 [[X]], i8 [[Y]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%or = select i1 %cmp, i1 true, i1 %cond
%ret = select i1 %or, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_and_umax_invalid_logical(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_and_umax_invalid_logical(
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP]], i1 [[COND:%.*]], i1 false
; CHECK-NEXT: [[RET:%.*]] = select i1 [[AND]], i8 [[X]], i8 [[Y]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%and = select i1 %cmp, i1 %cond, i1 false
%ret = select i1 %and, i8 %x, i8 %y
ret i8 %ret
}
define i8 @test_or_umax_multiuse_cond(i8 %x, i8 %y, i1 %cond) {
; CHECK-LABEL: @test_or_umax_multiuse_cond(
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[OR:%.*]] = select i1 [[COND:%.*]], i1 true, i1 [[CMP]]
; CHECK-NEXT: call void @use(i1 [[OR]])
; CHECK-NEXT: [[RET:%.*]] = select i1 [[OR]], i8 [[X]], i8 [[Y]]
; CHECK-NEXT: ret i8 [[RET]]
;
%cmp = icmp ugt i8 %x, %y
%or = select i1 %cond, i1 true, i1 %cmp
call void @use(i1 %or)
%ret = select i1 %or, i8 %x, i8 %y
ret i8 %ret
}
; Tests from PR76203
define i8 @test_or_eq_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_or_eq_a_b(
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp eq i8 %a, %b
%cond = or i1 %other_cond, %cmp
%select = select i1 %cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_and_ne_a_b(
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp ne i8 %a, %b
%cond = and i1 %other_cond, %cmp
%select = select i1 %cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_or_eq_a_b_commuted(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_or_eq_a_b_commuted(
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[B:%.*]], i8 [[A:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp eq i8 %a, %b
%cond = or i1 %other_cond, %cmp
%select = select i1 %cond, i8 %b, i8 %a
ret i8 %select
}
define i8 @test_and_ne_a_b_commuted(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_and_ne_a_b_commuted(
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[B:%.*]], i8 [[A:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp ne i8 %a, %b
%cond = and i1 %other_cond, %cmp
%select = select i1 %cond, i8 %b, i8 %a
ret i8 %select
}
define i8 @test_or_eq_different_operands(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: @test_or_eq_different_operands(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], [[C:%.*]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i8 [[A]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp eq i8 %a, %c
%cmp1 = icmp eq i8 %b, %a
%cond = or i1 %cmp, %cmp1
%select = select i1 %cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_or_eq_a_b_multi_use(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_or_eq_a_b_multi_use(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[COND:%.*]] = or i1 [[OTHER_COND:%.*]], [[CMP]]
; CHECK-NEXT: call void @use(i1 [[CMP]])
; CHECK-NEXT: call void @use(i1 [[COND]])
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND]], i8 [[A]], i8 [[B]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp eq i8 %a, %b
%cond = or i1 %other_cond, %cmp
call void @use(i1 %cmp)
call void @use(i1 %cond)
%select = select i1 %cond, i8 %a, i8 %b
ret i8 %select
}
define <2 x i8> @test_or_eq_a_b_vec(<2 x i1> %other_cond, <2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: @test_or_eq_a_b_vec(
; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[OTHER_COND:%.*]], <2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]
; CHECK-NEXT: ret <2 x i8> [[SELECT]]
;
%cmp = icmp eq <2 x i8> %a, %b
%cond = or <2 x i1> %other_cond, %cmp
%select = select <2 x i1> %cond, <2 x i8> %a, <2 x i8> %b
ret <2 x i8> %select
}
define i8 @test_or_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_or_ne_a_b(
; CHECK-NEXT: ret i8 [[A:%.*]]
;
%cmp = icmp ne i8 %a, %b
%cond = or i1 %other_cond, %cmp
%select = select i1 %cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_and_ne_different_operands_fail(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: @test_and_ne_different_operands_fail(
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[A:%.*]], [[C:%.*]]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[B:%.*]], [[C]]
; CHECK-NEXT: [[COND:%.*]] = and i1 [[CMP]], [[CMP1]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i8 [[B]], i8 [[A]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp ne i8 %a, %c
%cmp1 = icmp ne i8 %b, %c
%cond = and i1 %cmp, %cmp1
%select = select i1 %cond, i8 %b, i8 %a
ret i8 %select
}
define i8 @test_logical_or_eq_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_logical_or_eq_a_b(
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp eq i8 %a, %b
%or.cond = select i1 %other_cond, i1 true, i1 %cmp
%select = select i1 %or.cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_logical_commuted_or_eq_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_logical_commuted_or_eq_a_b(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[OTHER_COND:%.*]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i8 [[A]], i8 [[B]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp eq i8 %a, %b
%or.cond = select i1 %cmp, i1 true, i1 %other_cond
%select = select i1 %or.cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_logical_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_logical_and_ne_a_b(
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OTHER_COND:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp ne i8 %a, %b
%or.cond = select i1 %other_cond, i1 %cmp, i1 false
%select = select i1 %or.cond, i8 %a, i8 %b
ret i8 %select
}
define i8 @test_logical_commuted_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
; CHECK-LABEL: @test_logical_commuted_and_ne_a_b(
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[OTHER_COND:%.*]], i1 false
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[OR_COND]], i8 [[A]], i8 [[B]]
; CHECK-NEXT: ret i8 [[SELECT]]
;
%cmp = icmp ne i8 %a, %b
%or.cond = select i1 %cmp, i1 %other_cond, i1 false
%select = select i1 %or.cond, i8 %a, i8 %b
ret i8 %select
}