Index: lib/Transforms/InstCombine/InstCombine.h =================================================================== --- lib/Transforms/InstCombine/InstCombine.h +++ lib/Transforms/InstCombine/InstCombine.h @@ -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,303 @@ return getConstant(false); } +Instruction *InstCombiner::FoldICmpLgGtCstShrCst(ICmpInst &I, Value *Op, + Value *A, ConstantInt *CI1, + ConstantInt *CI2) { + + 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.isNegative()) { + // AP1 is zero and MSB of AP2 is set + assert(!IsAShr); + 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 if (I.getPredicate() == I.ICMP_SLE){ + // A == 0 || A >= 32 + return NULL; + } + else { + //Shouldn't reach here + 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())); + } + } + } + // Cases where AP2 = 0 and AP1 is nonzero, handled in InstSimplify + // Both AP1, AP2 are non-zero + if (AP1 == AP2) { + 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()) { + 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, @@ -2574,12 +2871,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 +}