[llvm] 6f8afaf - [InstCombine] Fold `A == MIN_INT ? B != MIN_INT : A < B` to `A < B` (#120177)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 19 06:52:58 PST 2024
Author: Veera
Date: 2024-12-19T22:52:55+08:00
New Revision: 6f8afafd308d37d9abc4af0801dd5a4451c13718
URL: https://github.com/llvm/llvm-project/commit/6f8afafd308d37d9abc4af0801dd5a4451c13718
DIFF: https://github.com/llvm/llvm-project/commit/6f8afafd308d37d9abc4af0801dd5a4451c13718.diff
LOG: [InstCombine] Fold `A == MIN_INT ? B != MIN_INT : A < B` to `A < B` (#120177)
This PR folds:
`A == MIN_INT ? B != MIN_INT : A < B` to `A < B`
`A == MAX_INT ? B != MAX_INT : A > B` to `A > B`
Proof: https://alive2.llvm.org/ce/z/bR6E2s
This helps in optimizing comparison of optional unsigned non-zero types
in https://github.com/rust-lang/rust/issues/49892.
Rust compiler's current output: https://rust.godbolt.org/z/9fxfq3Gn8
Added:
llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
Modified:
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 726c0f29e39928..8567a0504f54e1 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -7144,7 +7144,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
NewOps[1], I->getFastMathFlags(), Q, MaxRecurse);
case Instruction::Select:
return simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q, MaxRecurse);
- break;
case Instruction::GetElementPtr: {
auto *GEPI = cast<GetElementPtrInst>(I);
return simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0],
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 5eebfdb774d2e2..3d251d662bd53d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1781,6 +1781,46 @@ static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
return nullptr;
}
+/// `A == MIN_INT ? B != MIN_INT : A < B` --> `A < B`
+/// `A == MAX_INT ? B != MAX_INT : A > B` --> `A > B`
+static Instruction *foldSelectWithExtremeEqCond(Value *CmpLHS, Value *CmpRHS,
+ Value *TrueVal,
+ Value *FalseVal) {
+ Type *Ty = CmpLHS->getType();
+
+ if (Ty->isPtrOrPtrVectorTy())
+ return nullptr;
+
+ CmpPredicate Pred;
+ Value *B;
+
+ if (!match(FalseVal, m_c_ICmp(Pred, m_Specific(CmpLHS), m_Value(B))))
+ return nullptr;
+
+ Value *TValRHS;
+ if (!match(TrueVal, m_SpecificICmp(ICmpInst::ICMP_NE, m_Specific(B),
+ m_Value(TValRHS))))
+ return nullptr;
+
+ APInt C;
+ unsigned BitWidth = Ty->getScalarSizeInBits();
+
+ if (ICmpInst::isLT(Pred)) {
+ C = CmpInst::isSigned(Pred) ? APInt::getSignedMinValue(BitWidth)
+ : APInt::getMinValue(BitWidth);
+ } else if (ICmpInst::isGT(Pred)) {
+ C = CmpInst::isSigned(Pred) ? APInt::getSignedMaxValue(BitWidth)
+ : APInt::getMaxValue(BitWidth);
+ } else {
+ return nullptr;
+ }
+
+ if (!match(CmpRHS, m_SpecificInt(C)) || !match(TValRHS, m_SpecificInt(C)))
+ return nullptr;
+
+ return new ICmpInst(Pred, CmpLHS, B);
+}
+
static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
InstCombinerImpl &IC) {
ICmpInst::Predicate Pred = ICI->getPredicate();
@@ -1795,6 +1835,10 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
if (Pred == ICmpInst::ICMP_NE)
std::swap(TrueVal, FalseVal);
+ if (Instruction *Res =
+ foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))
+ return Res;
+
// Transform (X == C) ? X : Y -> (X == C) ? C : Y
// specific handling for Bitwise operation.
// x&y -> (x|y) ^ (x^y) or (x|y) & ~(x^y)
diff --git a/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll b/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
new file mode 100644
index 00000000000000..7f2cca44eab3b7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
@@ -0,0 +1,457 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @compare_unsigned_min(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_unsigned_min(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP2]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_signed_min(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_signed_min(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, -128
+ %cmp2 = icmp ne i8 %y, -128
+ %cmp3 = icmp slt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_unsigned_max(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_unsigned_max(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 255
+ %cmp2 = icmp ne i8 %y, 255
+ %cmp3 = icmp ugt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_signed_max(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_signed_max(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 127
+ %cmp2 = icmp ne i8 %y, 127
+ %cmp3 = icmp sgt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @relational_cmp_unsigned_min(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @relational_cmp_unsigned_min(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp ule i8 %x, 0
+ %cmp2 = icmp ugt i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @relational_cmp_signed_min(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @relational_cmp_signed_min(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp sle i8 %x, -128
+ %cmp2 = icmp sgt i8 %y, -128
+ %cmp3 = icmp slt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @relational_cmp_unsigned_max(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @relational_cmp_unsigned_max(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp uge i8 %x, 255
+ %cmp2 = icmp ult i8 %y, 255
+ %cmp3 = icmp ugt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @relational_cmp_signed_max(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @relational_cmp_signed_max(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP4]]
+;
+start:
+ %cmp1 = icmp sge i8 %x, 127
+ %cmp2 = icmp slt i8 %y, 127
+ %cmp3 = icmp sgt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+declare void @use(i1)
+
+define i1 @compare_signed_max_multiuse(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_signed_max_multiuse(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[X]], [[Y]]
+; CHECK-NEXT: call void @use(i1 [[TMP4]])
+; CHECK-NEXT: [[RESULT:%.*]] = icmp sgt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 127
+ %cmp2 = icmp ne i8 %y, 127
+ %cmp3 = icmp sgt i8 %x, %y
+ call void @use(i1 %cmp3)
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_signed_min_samesign(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_signed_min_samesign(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[RESULT:%.*]] = icmp slt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, -128
+ %cmp2 = icmp ne i8 %y, -128
+ %cmp3 = icmp samesign slt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_flipped(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_flipped(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[RESULT:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ugt i8 %y, %x
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_swapped(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_swapped(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[RESULT:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp ne i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp3, i1 %cmp2
+ ret i1 %result
+}
+
+define i1 @compare_swapped_flipped_unsigned_max(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_swapped_flipped_unsigned_max(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[RESULT:%.*]] = icmp ugt i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp ne i8 %x, 255
+ %cmp2 = icmp ne i8 %y, 255
+ %cmp3 = icmp ult i8 %y, %x
+ %result = select i1 %cmp1, i1 %cmp3, i1 %cmp2
+ ret i1 %result
+}
+
+define i1 @compare_unsigned_min_illegal_type(i9 %x, i9 %y) {
+; CHECK-LABEL: define i1 @compare_unsigned_min_illegal_type(
+; CHECK-SAME: i9 [[X:%.*]], i9 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i9 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[TMP2]]
+;
+start:
+ %cmp1 = icmp eq i9 %x, 0
+ %cmp2 = icmp ne i9 %y, 0
+ %cmp3 = icmp ult i9 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_true_poison(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_true_poison(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[CMP3]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 poison, i1 %cmp3
+ ret i1 %result
+}
+
+define <2 x i1> @compare_vector(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: define <2 x i1> @compare_vector(
+; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]]
+; CHECK-NEXT: ret <2 x i1> [[TMP1]]
+;
+ %cmp1 = icmp eq <2 x i8> %x, zeroinitializer
+ %cmp2 = icmp ne <2 x i8> %y, zeroinitializer
+ %cmp3 = icmp ult <2 x i8> %x, %y
+ %result = select <2 x i1> %cmp1, <2 x i1> %cmp2, <2 x i1> %cmp3
+ ret <2 x i1> %result
+}
+
+define i1 @compare_pointer_negative(ptr %x, ptr %y) {
+; CHECK-LABEL: define i1 @compare_pointer_negative(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[X]], inttoptr (i8 127 to ptr)
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[Y]], inttoptr (i8 127 to ptr)
+; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt ptr [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %X = inttoptr i8 127 to ptr
+ %cmp1 = icmp eq ptr %x, %X
+ %cmp2 = icmp ne ptr %y, %X
+ %cmp3 = icmp sgt ptr %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_float_negative(half %x, half %y) {
+; CHECK-LABEL: define i1 @compare_float_negative(
+; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = fcmp oeq half [[X]], 0xH0000
+; CHECK-NEXT: [[TMP3:%.*]] = fcmp one half [[Y]], 0xH0000
+; CHECK-NEXT: [[TMP4:%.*]] = fcmp ult half [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = fcmp oeq half %x, 0.0
+ %cmp2 = fcmp one half %y, 0.0
+ %cmp3 = fcmp ult half %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_unsigned_max_swapped_lhs_rhs_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_unsigned_max_swapped_lhs_rhs_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[X]], -1
+; CHECK-NEXT: [[DOTNOT:%.*]] = icmp ne i8 [[Y]], -1
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[DOTNOT]], i1 [[TMP2]], i1 false
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 255
+ %cmp2 = icmp ne i8 %y, 255
+ %cmp3 = icmp ugt i8 %x, %y
+ %result = select i1 %cmp2, i1 %cmp1, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_signed_min_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_signed_min_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[X]], -127
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[Y]], -127
+; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, -127
+ %cmp2 = icmp ne i8 %y, -127
+ %cmp3 = icmp slt i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_unsigned_max_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_unsigned_max_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[X]], -1
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[Y]], -1
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 255
+ %cmp2 = icmp ne i8 %y, 255
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @non_strict_op_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @non_strict_op_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[Y]], 0
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ule i8 [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ule i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_poison_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_poison_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
+; CHECK-NEXT: ret i1 [[CMP2]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %result = select i1 %cmp1, i1 %cmp2, i1 poison
+ ret i1 %result
+}
+
+define i1 @mismatched_cond_lhs_negative(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: define i1 @mismatched_cond_lhs_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[Z]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ult i8 %z, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @mismatched_trueval_lhs_negative(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: define i1 @mismatched_trueval_lhs_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[X]], [[Z]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %z
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @mismatched_constant_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @mismatched_constant_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 2
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp ne i8 %y, 2
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @mismatched_constant_two_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @mismatched_constant_two_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 2
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 2
+ %cmp2 = icmp ne i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
+
+define i1 @compare_eq_eq_negative(i8 %x, i8 %y) {
+; CHECK-LABEL: define i1 @compare_eq_eq_negative(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[Y]], 0
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[X]], [[Y]]
+; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+start:
+ %cmp1 = icmp eq i8 %x, 0
+ %cmp2 = icmp eq i8 %y, 0
+ %cmp3 = icmp ult i8 %x, %y
+ %result = select i1 %cmp1, i1 %cmp2, i1 %cmp3
+ ret i1 %result
+}
More information about the llvm-commits
mailing list