Index: lib/Transforms/InstCombine/InstCombine.h =================================================================== --- lib/Transforms/InstCombine/InstCombine.h +++ lib/Transforms/InstCombine/InstCombine.h @@ -128,7 +128,7 @@ AssumptionTracker *getAssumptionTracker() const { return AT; } const DataLayout *getDataLayout() const { return DL; } - + DominatorTree *getDominatorTree() const { return DT; } TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; } @@ -191,6 +191,8 @@ ConstantInt *DivRHS); Instruction *FoldICmpCstShrCst(ICmpInst &I, Value *Op, Value *A, ConstantInt *CI1, ConstantInt *CI2); + Instruction *FoldICmpLgGtCstShrCst(ICmpInst &I, Value *Op, Value *A, + ConstantInt *CI1, ConstantInt *CI2); Instruction *FoldICmpAddOpCst(Instruction &ICI, Value *X, ConstantInt *CI, ICmpInst::Predicate Pred); Instruction *FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS, Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1118,6 +1118,367 @@ return getConstant(false); } +Instruction *InstCombiner::FoldICmpLgGtCstShrCst(ICmpInst &I, Value *Op, + Value *A, ConstantInt *CI1, + ConstantInt *CI2) { + + auto getConstantIfEquality = [&I, this](bool IsTrue) { + if ((I.getPredicate() == I.ICMP_SLT || I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SGT || I.getPredicate() == I.ICMP_UGT)) + IsTrue = !IsTrue; + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), IsTrue)); + }; + + auto getConstantIfGreater = [&I, this](bool IsTrue) { + if (I.getPredicate() == I.ICMP_SLT || I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLE || I.getPredicate() == I.ICMP_ULE) + IsTrue = !IsTrue; + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), IsTrue)); + }; + + APInt AP1 = CI1->getValue(); + APInt AP2 = CI2->getValue(); + + bool IsAShr = isa(Op); + + if (!AP1) { + if (!AP2) { + // Both Constants are Zero + return getConstantIfEquality(true); + } else if (AP2.isNegative()) { + // AP1 is zero and MSB of AP2 is set + if (I.isUnsigned()) { + // AP2 will always be greater than AP1 (unsigned) + if (IsAShr) { + // AP2 will remain negative + // AP2 will always be greater than AP1 (unsigned) + return getConstantIfGreater(true); + } else { + if (I.getPredicate() == I.ICMP_UGE) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else if (I.getPredicate() == I.ICMP_UGT) { + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), 32)); + } else if (I.getPredicate() == I.ICMP_ULT) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } else { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), 32)); + } + } + } else { + if (IsAShr) { + // AP2 will always remain negative + // AP2 will always be less than AP1 (signed) + return getConstantIfGreater(false); + } else { + if (I.getPredicate() == I.ICMP_SGT || + I.getPredicate() == I.ICMP_SGE) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), 0)); + } else if (I.getPredicate() == I.ICMP_SLT) { + return new ICmpInst(I.ICMP_EQ, A, + ConstantInt::get(A->getType(), 0)); + } else { + // A == 0 || A >= 32 + return NULL; + } + } + } + } else { + // AP1 is zero and MSB of AP2 is unset + // Doesn't matter if signed or unsigned comparison + int logAP2 = AP2.logBase2(); + + if (I.getPredicate() == I.ICMP_ULT || I.getPredicate() == I.ICMP_SLT) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } else if (I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), AP2.logBase2())); + } else if (I.getPredicate() == I.ICMP_SGE || + I.getPredicate() == I.ICMP_UGE) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else { + if (AP2 == AP2.ashr(logAP2)) + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), AP2.logBase2())); + else + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), AP2.logBase2())); + } + } + } + + if (!AP2) { + // AP1 is non-zero, AP2 is zero, 0 after shift remains 0 + if (I.isUnsigned()) { + return getConstantIfGreater(false); + } else { + if (AP1.isNegative()) { + return getConstantIfGreater(true); + } else { + return getConstantIfGreater(false); + } + } + } + + // Both AP1, AP2 are non-zero + if (AP1 == AP2) { + if (AP1.isAllOnesValue() && IsAShr) { + return getConstantIfEquality(true); + } + + if (I.isUnsigned()) { + if (I.getPredicate() == I.ICMP_ULT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::getNullValue(A->getType())); + } else if (I.getPredicate() == I.ICMP_ULE) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else if (I.getPredicate() == I.ICMP_UGT) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } else { + return new ICmpInst(I.ICMP_EQ, A, + ConstantInt::getNullValue(A->getType())); + } + } else { + if (AP1.isNegative()) { + if (I.getPredicate() == I.ICMP_SGE) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else if (I.getPredicate() == I.ICMP_SGT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::getNullValue(A->getType())); + } else if (I.getPredicate() == I.ICMP_SLT) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } else { + return new ICmpInst(I.ICMP_EQ, A, + ConstantInt::getNullValue(A->getType())); + } + } else { + if (I.getPredicate() == I.ICMP_SLT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::getNullValue(A->getType())); + } else if (I.getPredicate() == I.ICMP_SLE) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else if (I.getPredicate() == I.ICMP_SGT) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } else { + return new ICmpInst(I.ICMP_EQ, A, + ConstantInt::getNullValue(A->getType())); + } + } + } + } + + if (IsAShr) { + if (AP1.isNegative() != AP2.isNegative()) { + if (AP1.isNegative()) { + if (I.isUnsigned()) { + return getConstantIfGreater(false); + } else { + return getConstantIfGreater(true); + } + } else { + if (I.isUnsigned()) { + return getConstantIfGreater(true); + } else { + return getConstantIfGreater(false); + } + } + } + if (AP1.isNegative()) { + AP1 = -AP1; + AP2 = -AP2; + + if (AP1.ugt(AP2)) { + return getConstantIfGreater(true); + } else { + int Shift = AP2.logBase2() - AP1.logBase2(); + if (AP1 == AP2.lshr(Shift)) { + if (I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLT) { + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), Shift)); + } else if (I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), Shift)); + } else if (I.getPredicate() == I.ICMP_UGT || + I.getPredicate() == I.ICMP_SGT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), Shift)); + } else { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), Shift)); + } + } else { + if (AP1.ugt(AP2.lshr(Shift))) { + Shift--; + } + if (I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLT || + I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), Shift + 1)); + } else { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), Shift)); + } + } + } + return NULL; + } else { + if (AP1.ugt(AP2)) { + return getConstantIfGreater(false); + } else { + int Shift = AP2.logBase2() - AP1.logBase2(); + if (AP1 == AP2.lshr(Shift)) { + if (I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), Shift)); + } else if (I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), Shift)); + } else if (I.getPredicate() == I.ICMP_UGT || + I.getPredicate() == I.ICMP_SGT) { + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), Shift)); + } else { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), Shift)); + } + } else { + if (AP1.ugt(AP2.lshr(Shift))) { + Shift--; + } + if (I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLT || + I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), Shift + 1)); + } else { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), Shift)); + } + } + } + } + } else { + if (AP1.isNegative() != AP2.isNegative()) { + if (AP1.isNegative()) { + if (I.isUnsigned()) { + return getConstantIfGreater(false); + } else { + return getConstantIfGreater(true); + } + } else { + if (I.isUnsigned()) { + int x = 32 - AP1.logBase2() - 1; + if (AP1 == AP2.lshr(x)) { + if (I.getPredicate() == I.ICMP_UGT) { + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), x)); + } else if (I.getPredicate() == I.ICMP_UGE) { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), x)); + } else if (I.getPredicate() == I.ICMP_ULT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), x)); + } else { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), x)); + } + } else { + if (AP2.lshr(x).ult(AP1)) { + x--; + } + if (I.getPredicate() == I.ICMP_UGT || + I.getPredicate() == I.ICMP_UGE) { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), x)); + } else { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), x + 1)); + } + } + } else { + return NULL; + } + } + } else if (AP1.isNegative()) { + if (I.getPredicate() == I.ICMP_ULT || I.getPredicate() == I.ICMP_ULE) { + if (AP1.ugt(AP2)) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else { + return new ICmpInst(I.ICMP_UGT, A, ConstantInt::get(A->getType(), 0)); + } + } else if (I.getPredicate() == I.ICMP_UGT || + I.getPredicate() == I.ICMP_UGE) { + if (AP2.ugt(AP1)) { + return new ICmpInst(I.ICMP_EQ, A, ConstantInt::get(A->getType(), 0)); + } else { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } + } else if (I.getPredicate() == I.ICMP_SLT || + I.getPredicate() == I.ICMP_SLE) { + if (AP2.slt(AP1)) { + return new ICmpInst(I.ICMP_EQ, A, ConstantInt::get(A->getType(), 0)); + } else { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), false)); + } + } else { + if (AP2.sgt(AP1)) { + return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), true)); + } else { + return new ICmpInst(I.ICMP_UGT, A, ConstantInt::get(A->getType(), 0)); + } + } + } else { + if (AP1.ugt(AP2)) { + return getConstantIfGreater(false); + } else { + int Shift = AP2.logBase2() - AP1.logBase2(); + if (AP1 == AP2.lshr(Shift)) { + if (I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLT) { + return new ICmpInst(I.ICMP_UGT, A, + ConstantInt::get(A->getType(), Shift)); + } else if (I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), Shift)); + } else if (I.getPredicate() == I.ICMP_UGT || + I.getPredicate() == I.ICMP_SGT) { + return new ICmpInst(I.ICMP_ULT, A, + ConstantInt::get(A->getType(), Shift)); + } else { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), Shift)); + } + } else { + if (AP1.ugt(AP2.lshr(Shift))) { + Shift--; + } + if (I.getPredicate() == I.ICMP_ULT || + I.getPredicate() == I.ICMP_SLT || + I.getPredicate() == I.ICMP_ULE || + I.getPredicate() == I.ICMP_SLE) { + return new ICmpInst(I.ICMP_UGE, A, + ConstantInt::get(A->getType(), Shift + 1)); + } else { + return new ICmpInst(I.ICMP_ULE, A, + ConstantInt::get(A->getType(), Shift)); + } + } + } + } + } +} + /// visitICmpInstWithInstAndIntCst - Handle "icmp (instr, intcst)". /// Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, @@ -1294,7 +1655,7 @@ cast(ConstantExpr::getShl(AndCst, ShAmt)); ConstantInt *ShiftedRHSCst = cast(ConstantExpr::getShl(RHS, ShAmt)); - + if (!ShiftedAndCst->isNegative() && !ShiftedRHSCst->isNegative()) CanFold = true; } @@ -2574,12 +2935,16 @@ Builder->getInt(CI->getValue()-1)); } - // (icmp eq/ne (ashr/lshr const2, A), const1) - if (I.isEquality()) { - ConstantInt *CI2; - if (match(Op0, m_AShr(m_ConstantInt(CI2), m_Value(A))) || - match(Op0, m_LShr(m_ConstantInt(CI2), m_Value(A)))) { + ConstantInt *CI2; + if (match(Op0, m_AShr(m_ConstantInt(CI2), m_Value(A))) || + match(Op0, m_LShr(m_ConstantInt(CI2), m_Value(A)))) { + // (icmp eq/ne (ashr/lshr const2, A), const1) + if (I.isEquality()) { return FoldICmpCstShrCst(I, Op0, A, CI, CI2); + } else { + Instruction *I2 = FoldICmpLgGtCstShrCst(I, Op0, A, CI, CI2); + if (I2 != NULL) + return I2; } } Index: test/Transforms/InstCombine/icmp-shr.ll =================================================================== --- test/Transforms/InstCombine/icmp-shr.ll +++ test/Transforms/InstCombine/icmp-shr.ll @@ -690,3 +690,364 @@ %cmp = icmp ne i32 %shr, -5 ret i1 %cmp } + +; Test cases for icmp shr ugt/sgt/uge/sge/ult/slt/ule/sle +define i1 @lshr_sgt_both_zero(i8 %a) { +; CHECK-LABEL: @lshr_sgt_both_zero( +; CHECK-NEXT: ret i1 false + %shr = lshr i8 0, %a + %cmp = icmp sgt i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_sge_both_zero(i8 %a) { +; CHECK-LABEL: @lshr_sge_both_zero( +; CHECK-NEXT: ret i1 true + %shr = lshr i8 0, %a + %cmp = icmp sge i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_sge_ap1_zero_ap2_negative(i8 %a) { +; CHECK-LABEL: @lshr_sge_ap1_zero_ap2_negative( +; CHECK-NEXT: %cmp = icmp ne i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i8 -4, %a + %cmp = icmp sge i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_sgt_ap1_zero_ap2_negative(i8 %a) { +; CHECK-LABEL: @lshr_sgt_ap1_zero_ap2_negative( +; CHECK-NEXT: %cmp = icmp ne i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i8 -5, %a + %cmp = icmp sgt i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_slt_ap1_zero_ap2_negative(i8 %a) { +; CHECK-LABEL: @lshr_slt_ap1_zero_ap2_negative( +; CHECK-NEXT: %cmp = icmp eq i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i8 -6, %a + %cmp = icmp slt i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_sle_ap1_zero_ap2_negative(i8 %a) { +; CHECK-LABEL: @lshr_sle_ap1_zero_ap2_negative( +; CHECK-NEXT: %shr = lshr i8 -5, %a +; CHECK-NEXT: %cmp = icmp slt i8 %shr, 1 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i8 -5, %a + %cmp = icmp sle i8 %shr, 0 + ret i1 %cmp +} + +define i1 @ashr_sgt_ap1_zero_ap2_positive(i8 %a) { +; CHECK-LABEL: @ashr_sgt_ap1_zero_ap2_positive( +; CHECK-NEXT: %cmp = icmp ult i8 %a, 3 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 5, %a + %cmp = icmp sgt i8 %shr, 0 + ret i1 %cmp +} + +define i1 @ashr_sle_ap1_zero_ap2_positive(i8 %a) { +; CHECK-LABEL: @ashr_sle_ap1_zero_ap2_positive( +; CHECK-NEXT: %cmp = icmp ugt i8 %a, 2 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 7, %a + %cmp = icmp sle i8 %shr, 0 + ret i1 %cmp +} + +define i1 @ashr_ugt_ap1_zero_ap2_positive(i8 %a) { +; CHECK-LABEL: @ashr_ugt_ap1_zero_ap2_positive( +; CHECK-NEXT: %cmp = icmp ult i8 %a, 3 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 5, %a + %cmp = icmp ugt i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_sgt_ap1_zero_ap2_positive(i8 %a) { +; CHECK-LABEL: @lshr_sgt_ap1_zero_ap2_positive( +; CHECK-NEXT: %cmp = icmp ult i8 %a, 3 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i8 5, %a + %cmp = icmp sgt i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_sle_ap1_zero_ap2_positive(i8 %a) { +; CHECK-LABEL: @lshr_sle_ap1_zero_ap2_positive( +; CHECK-NEXT: %cmp = icmp ugt i8 %a, 2 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i8 7, %a + %cmp = icmp sle i8 %shr, 0 + ret i1 %cmp +} + +define i1 @lshr_ugt_ap1_negative_ap2_zero(i8 %a) { +; CHECK-LABEL: @lshr_ugt_ap1_negative_ap2_zero( +; CHECK-NEXT: ret i1 false + %shr = lshr i8 0, %a + %cmp = icmp ugt i8 %shr, -7 + ret i1 %cmp +} + +define i1 @lshr_sge_ap1_negative_ap2_zero(i8 %a) { +; CHECK-LABEL: @lshr_sge_ap1_negative_ap2_zero( +; CHECK-NEXT: ret i1 true + %shr = lshr i8 0, %a + %cmp = icmp sge i8 %shr, -6 + ret i1 %cmp +} + +define i1 @ashr_sgt_ap1_positive_ap2_zero(i8 %a) { +; CHECK-LABEL: @ashr_sgt_ap1_positive_ap2_zero( +; CHECK-NEXT: ret i1 false + %shr = ashr i8 0, %a + %cmp = icmp sgt i8 %shr, 7 + ret i1 %cmp +} + +define i1 @ashr_slt_ap1_positive_ap2_zero(i8 %a) { +; CHECK-LABEL: @ashr_slt_ap1_positive_ap2_zero( +; CHECK-NEXT: ret i1 true + %shr = ashr i8 0, %a + %cmp = icmp slt i8 %shr, 5 + ret i1 %cmp +} + +define i1 @ashr_ult_ap1_equal_ap2(i8 %a) { +; CHECK-LABEL: @ashr_ult_ap1_equal_ap2( +; CHECK-NEXT: %cmp = icmp ne i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 13, %a + %cmp = icmp ult i8 %shr, 13 + ret i1 %cmp +} + +define i1 @ashr_uge_ap1_equal_ap2(i8 %a) { +; CHECK-LABEL: @ashr_uge_ap1_equal_ap2( +; CHECK-NEXT: %cmp = icmp eq i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 13, %a + %cmp = icmp uge i8 %shr, 13 + ret i1 %cmp +} + +define i1 @ashr_sgt_ap1_equal_ap2_negative(i8 %a) { +; CHECK-LABEL: @ashr_sgt_ap1_equal_ap2_negative( +; CHECK-NEXT: %cmp = icmp ne i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 -13, %a + %cmp = icmp sgt i8 %shr, -13 + ret i1 %cmp +} + +define i1 @ashr_sle_ap1_equal_ap2_negative(i8 %a) { +; CHECK-LABEL: @ashr_sle_ap1_equal_ap2_negative( +; CHECK-NEXT: %cmp = icmp eq i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 -13, %a + %cmp = icmp sle i8 %shr, -13 + ret i1 %cmp +} + +define i1 @ashr_sge_ap1_equal_ap2_positive(i8 %a) { +; CHECK-LABEL: @ashr_sge_ap1_equal_ap2_positive( +; CHECK-NEXT: %cmp = icmp eq i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 13, %a + %cmp = icmp sge i8 %shr, 13 + ret i1 %cmp +} + +define i1 @ashr_slt_ap1_equal_ap2_positive(i8 %a) { +; CHECK-LABEL: @ashr_slt_ap1_equal_ap2_positive( +; CHECK-NEXT: %cmp = icmp ne i8 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i8 13, %a + %cmp = icmp slt i8 %shr, 13 + ret i1 %cmp +} + +define i1 @ashr_sgt_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @ashr_sgt_ap1_negative_ap2_negative( +; CHECK-NEXT: %cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i32 -22, %a + %cmp = icmp sgt i32 %shr, -14 + ret i1 %cmp +} + +define i1 @ashr_slt_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @ashr_slt_ap1_negative_ap2_negative( +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i32 -22, %a + %cmp = icmp slt i32 %shr, -14 + ret i1 %cmp +} + +define i1 @ashr_sge_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @ashr_sge_ap1_negative_ap2_negative( +; CHECK-NEXT: %cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i32 -22, %a + %cmp = icmp sge i32 %shr, -14 + ret i1 %cmp +} + +define i1 @ashr_sle_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @ashr_sle_ap1_negative_ap2_negative( +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = ashr i32 -22, %a + %cmp = icmp sle i32 %shr, -14 + ret i1 %cmp +} + +define i1 @lshr_ule_ap1_positive_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_ule_ap1_positive_ap2_negative( +; CHECK-NEXT: %cmp = icmp ugt i32 %a, 28 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -22, %a + %cmp = icmp ule i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_ult_ap1_positive_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_ult_ap1_positive_ap2_negative( +; CHECK-NEXT: %cmp = icmp ugt i32 %a, 28 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -22, %a + %cmp = icmp ult i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_ugt_ap1_positive_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_ugt_ap1_positive_ap2_negative( +; CHECK-NEXT: %cmp = icmp ult i32 %a, 29 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -22, %a + %cmp = icmp ugt i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_uge_ap1_positive_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_uge_ap1_positive_ap2_negative( +; CHECK-NEXT: %cmp = icmp ult i32 %a, 29 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -22, %a + %cmp = icmp uge i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_ult_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_ult_ap1_negative_ap2_negative( +; CHECK-NEXT: ret i1 true + %shr = lshr i32 -22, %a + %cmp = icmp ult i32 %shr, -14 + ret i1 %cmp +} + +define i1 @lshr_ugt_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_ugt_ap1_negative_ap2_negative( +; CHECK-NEXT: ret i1 false + %shr = lshr i32 -22, %a + %cmp = icmp ugt i32 %shr, -14 + ret i1 %cmp +} + +define i1 @lshr_slt_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_slt_ap1_negative_ap2_negative( +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -22, %a + %cmp = icmp slt i32 %shr, -14 + ret i1 %cmp +} + +define i1 @lshr_sgt_ap1_negative_ap2_negative(i32 %a) { +; CHECK-LABEL: @lshr_sgt_ap1_negative_ap2_negative( +; CHECK-NEXT: %cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -22, %a + %cmp = icmp sgt i32 %shr, -14 + ret i1 %cmp +} + +define i1 @lshr_ult_ap1_negative_ap2_negative_ap1_greater(i32 %a) { +; CHECK-LABEL: @lshr_ult_ap1_negative_ap2_negative_ap1_greater( +; CHECK-NEXT: %cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -14, %a + %cmp = icmp ult i32 %shr, -22 + ret i1 %cmp +} + +define i1 @lshr_ugt_ap1_negative_ap2_negative_ap1_greater(i32 %a) { +; CHECK-LABEL: @lshr_ugt_ap1_negative_ap2_negative_ap1_greater( +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 -14, %a + %cmp = icmp ugt i32 %shr, -22 + ret i1 %cmp +} + +define i1 @lshr_slt_ap1_negative_ap2_negative_ap1_greater(i32 %a) { +; CHECK-LABEL: @lshr_slt_ap1_negative_ap2_negative_ap1_greater( +; CHECK-NEXT: ret i1 false + %shr = lshr i32 -14, %a + %cmp = icmp slt i32 %shr, -22 + ret i1 %cmp +} + +define i1 @lshr_sgt_ap1_negative_ap2_negative_ap1_greater(i32 %a) { +; CHECK-LABEL: @lshr_sgt_ap1_negative_ap2_negative_ap1_greater( +; CHECK-NEXT: ret i1 true + %shr = lshr i32 -14, %a + %cmp = icmp sgt i32 %shr, -22 + ret i1 %cmp +} + +define i1 @lshr_ult_ap1_positive_ap2_positive(i32 %a) { +; CHECK-LABEL: @lshr_ult_ap1_positive_ap2_positive( +; CHECK-NEXT: %cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 22, %a + %cmp = icmp ult i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_ugt_ap1_positive_ap2_positive(i32 %a) { +; CHECK-LABEL: @lshr_ugt_ap1_positive_ap2_positive( +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 22, %a + %cmp = icmp ugt i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_slt_ap1_positive_ap2_positive(i32 %a) { +; CHECK-LABEL: @lshr_slt_ap1_positive_ap2_positive( +; CHECK-NEXT: %cmp = icmp ne i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 22, %a + %cmp = icmp slt i32 %shr, 14 + ret i1 %cmp +} + +define i1 @lshr_sgt_ap1_positive_ap2_positive(i32 %a) { +; CHECK-LABEL: @lshr_sgt_ap1_positive_ap2_positive( +; CHECK-NEXT: %cmp = icmp eq i32 %a, 0 +; CHECK-NEXT: ret i1 %cmp + %shr = lshr i32 22, %a + %cmp = icmp sgt i32 %shr, 14 + ret i1 %cmp +}