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(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 +}