[llvm] r213678 - This patch implements optimization as mentioned in PR19753: Optimize comparisons with "ashr/lshr exact" of a constanst.

Sanjay Patel spatel at rotateright.com
Sun Oct 19 11:46:54 PDT 2014


> Sorry for the necro-post, but did this get verified with an SMT solver?

Apparently not - at least 2 more miscompiles have been blamed on this patch
after PR19958 was marked fixed:
http://llvm.org/bugs/show_bug.cgi?id=20945
http://llvm.org/bugs/show_bug.cgi?id=21222

On Fri, Oct 17, 2014 at 5:26 PM, Sean Silva <chisophugis at gmail.com> wrote:

> Sorry for the necro-post, but did this get verified with an SMT solver?
>
> Sanjay (CC'd) even provided links to example code for using an SMT solver
> to verify it in http://llvm.org/bugs/show_bug.cgi?id=19958#c9
>
> -- Sean Silva
>
> On Tue, Jul 22, 2014 at 12:19 PM, Suyog Sarda <suyog.sarda at samsung.com>
> wrote:
>
>> Author: suyog
>> Date: Tue Jul 22 14:19:36 2014
>> New Revision: 213678
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=213678&view=rev
>> Log:
>> This patch implements optimization as mentioned in PR19753: Optimize
>> comparisons with "ashr/lshr exact" of a constanst.
>> It handles the errors which were seen in PR19958 where wrong code was
>> being emitted due to earlier patch.
>> Added code for lshr as well as non-exact right shifts.
>>
>> It implements :
>> (icmp eq/ne (ashr/lshr const2, A), const1)" ->
>> (icmp eq/ne A, Log2(const2/const1)) ->
>> (icmp eq/ne A, Log2(const2) - Log2(const1))
>>
>> Differential Revision: http://reviews.llvm.org/D4068
>>
>>
>> Added:
>>     llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll
>> Modified:
>>     llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
>>     llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>>
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=213678&r1=213677&r2=213678&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Tue Jul 22
>> 14:19:36 2014
>> @@ -172,6 +172,8 @@ public:
>>                                ConstantInt *DivRHS);
>>    Instruction *FoldICmpShrCst(ICmpInst &ICI, BinaryOperator *DivI,
>>                                ConstantInt *DivRHS);
>> +  Instruction *FoldICmpCstShrCst(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,
>>
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=213678&r1=213677&r2=213678&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Tue Jul
>> 22 14:19:36 2014
>> @@ -1044,6 +1044,90 @@ Instruction *InstCombiner::FoldICmpShrCs
>>    return nullptr;
>>  }
>>
>> +/// FoldICmpCstShrCst - Handle "(icmp eq/ne (ashr/lshr const2, A),
>> const1)" ->
>> +/// (icmp eq/ne A, Log2(const2/const1)) ->
>> +/// (icmp eq/ne A, Log2(const2) - Log2(const1)).
>> +Instruction *InstCombiner::FoldICmpCstShrCst(ICmpInst &I, Value *Op,
>> Value *A,
>> +                                             ConstantInt *CI1,
>> +                                             ConstantInt *CI2) {
>> +  assert(I.isEquality() && "Cannot fold icmp gt/lt");
>> +
>> +  auto getConstant = [&I, this](bool IsTrue) {
>> +    if (I.getPredicate() == I.ICMP_NE)
>> +      IsTrue = !IsTrue;
>> +    return ReplaceInstUsesWith(I, ConstantInt::get(I.getType(), IsTrue));
>> +  };
>> +
>> +  auto getICmp = [&I](CmpInst::Predicate Pred, Value *LHS, Value *RHS) {
>> +    if (I.getPredicate() == I.ICMP_NE)
>> +      Pred = CmpInst::getInversePredicate(Pred);
>> +    return new ICmpInst(Pred, LHS, RHS);
>> +  };
>> +
>> +  APInt AP1 = CI1->getValue();
>> +  APInt AP2 = CI2->getValue();
>> +
>> +  if (!AP1) {
>> +    if (!AP2) {
>> +      // Both Constants are 0.
>> +      return getConstant(true);
>> +    }
>> +
>> +    if (cast<BinaryOperator>(Op)->isExact())
>> +      return getConstant(false);
>> +
>> +    if (AP2.isNegative()) {
>> +      // MSB is set, so a lshr with a large enough 'A' would be
>> undefined.
>> +      return getConstant(false);
>> +    }
>> +
>> +    // 'A' must be large enough to shift out the highest set bit.
>> +    return getICmp(I.ICMP_UGT, A,
>> +                   ConstantInt::get(A->getType(), AP2.logBase2()));
>> +  }
>> +
>> +  if (!AP2) {
>> +    // Shifting 0 by any value gives 0.
>> +    return getConstant(false);
>> +  }
>> +
>> +  bool IsAShr = isa<AShrOperator>(Op);
>> +  if (AP1 == AP2) {
>> +    if (AP1.isAllOnesValue() && IsAShr) {
>> +      // Arithmatic shift of -1 is always -1.
>> +      return getConstant(true);
>> +    }
>> +    return getICmp(I.ICMP_EQ, A,
>> ConstantInt::getNullValue(A->getType()));
>> +  }
>> +
>> +  if (IsAShr) {
>> +    if (AP1.isNegative() != AP2.isNegative()) {
>> +      // Arithmetic shift will never change the sign.
>> +      return getConstant(false);
>> +    }
>> +    // Both the constants are negative, take their positive to calculate
>> +    // log.
>> +    if (AP1.isNegative()) {
>> +      AP1 = -AP1;
>> +      AP2 = -AP2;
>> +    }
>> +  }
>> +
>> +  if (AP1.ugt(AP2)) {
>> +    // Right-shifting will not increase the value.
>> +    return getConstant(false);
>> +  }
>> +
>> +  // Get the distance between the highest bit that's set.
>> +  int Shift = AP2.logBase2() - AP1.logBase2();
>> +
>> +  // Use lshr here, since we've canonicalized to +ve numbers.
>> +  if (AP1 == AP2.lshr(Shift))
>> +    return getICmp(I.ICMP_EQ, A, ConstantInt::get(A->getType(), Shift));
>> +
>> +  // Shifting const2 will never be equal to const1.
>> +  return getConstant(false);
>> +}
>>
>>  /// visitICmpInstWithInstAndIntCst - Handle "icmp (instr, intcst)".
>>  ///
>> @@ -2469,6 +2553,15 @@ Instruction *InstCombiner::visitICmpInst
>>                            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)))) {
>> +        return FoldICmpCstShrCst(I, Op0, A, CI, CI2);
>> +      }
>> +    }
>> +
>>      // If this comparison is a normal comparison, it demands all
>>      // bits, if it is a sign bit comparison, it only demands the sign
>> bit.
>>      bool UnusedBit;
>>
>> Added: llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll?rev=213678&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll (added)
>> +++ llvm/trunk/test/Transforms/InstCombine/icmp-shr.ll Tue Jul 22
>> 14:19:36 2014
>> @@ -0,0 +1,677 @@
>> +; RUN: opt < %s -instcombine -S | FileCheck %s
>> +
>> +target datalayout =
>> "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_eq_both_zero(i8 %a) {
>> + %shr = lshr exact i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_eq_both_zero(i8 %a) {
>> + %shr = ashr exact i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_eq_both_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_both_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_eq_both_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_ne_both_zero(i8 %a) {
>> + %shr = lshr exact i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_ne_both_zero(i8 %a) {
>> + %shr = ashr exact i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_ne_both_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_both_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_ne_both_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_last_zero(i8 %a) {
>> + %shr = lshr exact i8 128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_last_zero(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_last_zero(i8 %a) {
>> + %shr = lshr exact i8 128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_last_zero(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_eq_last_zero(i8 %a) {
>> + %shr = lshr i8 128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_last_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_eq_last_zero(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_ne_last_zero(i8 %a) {
>> + %shr = lshr i8 128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_last_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_ne_last_zero(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_msb_low_last_zero
>> +; CHECK-NEXT: icmp ugt i8 %a, 6
>> +define i1 @lshr_eq_msb_low_last_zero(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_msb_low_second_zero
>> +; CHECK-NEXT: icmp ugt i8 %a, 6
>> +define i1 @ashr_eq_msb_low_second_zero(i8 %a) {
>> + %shr = ashr i8 127, %a
>> + %cmp = icmp eq i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_msb_low_last_zero
>> +; CHECK-NEXT: icmp ult i8 %a, 7
>> +define i1 @lshr_ne_msb_low_last_zero(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_msb_low_second_zero
>> +; CHECK-NEXT: icmp ult i8 %a, 7
>> +define i1 @ashr_ne_msb_low_second_zero(i8 %a) {
>> + %shr = ashr i8 127, %a
>> + %cmp = icmp ne i8 %shr, 0
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_first_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @lshr_eq_first_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_first_zero
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @ashr_eq_first_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp eq i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_first_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @lshr_ne_first_zero(i8 %a) {
>> + %shr = lshr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_first_zero
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @ashr_ne_first_zero(i8 %a) {
>> + %shr = ashr i8 0, %a
>> + %cmp = icmp ne i8 %shr, 2
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_both_minus1
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @ashr_eq_both_minus1(i8 %a) {
>> + %shr = ashr i8 -1, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_both_minus1
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @ashr_ne_both_minus1(i8 %a) {
>> + %shr = ashr i8 -1, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_both_minus1
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_eq_both_minus1(i8 %a) {
>> + %shr = ashr exact i8 -1, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_both_minus1
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_ne_both_minus1(i8 %a) {
>> + %shr = ashr exact i8 -1, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @ashr_eq_both_equal(i8 %a) {
>> + %shr = ashr i8 128, %a
>> + %cmp = icmp eq i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @ashr_ne_both_equal(i8 %a) {
>> + %shr = ashr i8 128, %a
>> + %cmp = icmp ne i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @lshr_eq_both_equal(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp eq i8 %shr, 127
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @lshr_ne_both_equal(i8 %a) {
>> + %shr = lshr i8 127, %a
>> + %cmp = icmp ne i8 %shr, 127
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @exact_ashr_eq_both_equal(i8 %a) {
>> + %shr = ashr exact i8 128, %a
>> + %cmp = icmp eq i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @exact_ashr_ne_both_equal(i8 %a) {
>> + %shr = ashr exact i8 128, %a
>> + %cmp = icmp ne i8 %shr, 128
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_both_equal
>> +; CHECK-NEXT: icmp eq i8 %a, 0
>> +define i1 @exact_lshr_eq_both_equal(i8 %a) {
>> + %shr = lshr exact i8 126, %a
>> + %cmp = icmp eq i8 %shr, 126
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_both_equal
>> +; CHECK-NEXT: icmp ne i8 %a, 0
>> +define i1 @exact_lshr_ne_both_equal(i8 %a) {
>> + %shr = lshr exact i8 126, %a
>> + %cmp = icmp ne i8 %shr, 126
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_opposite_msb
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_opposite_msb(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_eq_opposite_msb
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @ashr_eq_opposite_msb(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_opposite_msb
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @exact_lshr_eq_opposite_msb(i8 %a) {
>> + %shr = lshr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_eq_opposite_msb
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @lshr_eq_opposite_msb(i8 %a) {
>> + %shr = lshr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_opposite_msb
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_opposite_msb(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @ashr_ne_opposite_msb
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @ashr_ne_opposite_msb(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_opposite_msb
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @exact_lshr_ne_opposite_msb(i8 %a) {
>> + %shr = lshr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @lshr_ne_opposite_msb
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @lshr_ne_opposite_msb(i8 %a) {
>> + %shr = lshr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_shift_gt
>> +; CHECK-NEXT : ret i1 false
>> +define i1 @exact_ashr_eq_shift_gt(i8 %a) {
>> + %shr = ashr exact i8 -2, %a
>> + %cmp = icmp eq i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_shift_gt
>> +; CHECK-NEXT : ret i1 true
>> +define i1 @exact_ashr_ne_shift_gt(i8 %a) {
>> + %shr = ashr exact i8 -2, %a
>> + %cmp = icmp ne i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_shift_gt
>> +; CHECK-NEXT : ret i1 false
>> +define i1 @nonexact_ashr_eq_shift_gt(i8 %a) {
>> + %shr = ashr i8 -2, %a
>> + %cmp = icmp eq i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_shift_gt
>> +; CHECK-NEXT : ret i1 true
>> +define i1 @nonexact_ashr_ne_shift_gt(i8 %a) {
>> + %shr = ashr i8 -2, %a
>> + %cmp = icmp ne i8 %shr, -8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_shift_gt
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_shift_gt(i8 %a) {
>> + %shr = lshr exact i8 2, %a
>> + %cmp = icmp eq i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_shift_gt
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_shift_gt(i8 %a) {
>> + %shr = lshr exact i8 2, %a
>> + %cmp = icmp ne i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_shift_gt
>> +; CHECK-NEXT : ret i1 false
>> +define i1 @nonexact_lshr_eq_shift_gt(i8 %a) {
>> + %shr = lshr i8 2, %a
>> + %cmp = icmp eq i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_shift_gt
>> +; CHECK-NEXT : ret i1 true
>> +define i1 @nonexact_lshr_ne_shift_gt(i8 %a) {
>> + %shr = ashr i8 2, %a
>> + %cmp = icmp ne i8 %shr, 8
>> + ret i1 %cmp
>> +}
>> +
>> +
>> +
>> +; CHECK-LABEL: @exact_ashr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @exact_ashr_eq(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @exact_ashr_ne(i8 %a) {
>> + %shr = ashr exact i8 -128, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 2
>> +define i1 @exact_lshr_eq(i8 %a) {
>> + %shr = lshr exact i8 4, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 2
>> +define i1 @exact_lshr_ne(i8 %a) {
>> + %shr = lshr exact i8 4, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 7
>> +define i1 @nonexact_ashr_eq(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp eq i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 7
>> +define i1 @nonexact_ashr_ne(i8 %a) {
>> + %shr = ashr i8 -128, %a
>> + %cmp = icmp ne i8 %shr, -1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq
>> +; CHECK-NEXT: icmp eq i8 %a, 2
>> +define i1 @nonexact_lshr_eq(i8 %a) {
>> + %shr = lshr i8 4, %a
>> + %cmp = icmp eq i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne
>> +; CHECK-NEXT: icmp ne i8 %a, 2
>> +define i1 @nonexact_lshr_ne(i8 %a) {
>> + %shr = lshr i8 4, %a
>> + %cmp = icmp ne i8 %shr, 1
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @exact_lshr_eq_exactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp eq i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @exact_lshr_ne_exactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp ne i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @nonexact_lshr_eq_exactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp eq i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @nonexact_lshr_ne_exactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp ne i8 %shr, 5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @exact_ashr_eq_exactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @exact_ashr_ne_exactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_exactdiv
>> +; CHECK-NEXT: icmp eq i8 %a, 4
>> +define i1 @nonexact_ashr_eq_exactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_exactdiv
>> +; CHECK-NEXT: icmp ne i8 %a, 4
>> +define i1 @nonexact_ashr_ne_exactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -5
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_noexactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp eq i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_noexactdiv(i8 %a) {
>> + %shr = lshr exact i8 80, %a
>> + %cmp = icmp ne i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_eq_noexactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp eq i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_ne_noexactdiv(i8 %a) {
>> + %shr = lshr i8 80, %a
>> + %cmp = icmp ne i8 %shr, 31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_noexactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_noexactdiv(i8 %a) {
>> + %shr = ashr exact i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_noexactdiv
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_eq_noexactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp eq i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_noexactdiv
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_ne_noexactdiv(i8 %a) {
>> + %shr = ashr i8 -80, %a
>> + %cmp = icmp ne i8 %shr, -31
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_lshr_eq_noexactlog(i8 %a) {
>> + %shr = lshr exact i8 90, %a
>> + %cmp = icmp eq i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_lshr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_lshr_ne_noexactlog(i8 %a) {
>> + %shr = lshr exact i8 90, %a
>> + %cmp = icmp ne i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_lshr_eq_noexactlog(i8 %a) {
>> + %shr = lshr i8 90, %a
>> + %cmp = icmp eq i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_lshr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_lshr_ne_noexactlog(i8 %a) {
>> + %shr = lshr i8 90, %a
>> + %cmp = icmp ne i8 %shr, 30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @exact_ashr_eq_noexactlog(i8 %a) {
>> + %shr = ashr exact i8 -90, %a
>> + %cmp = icmp eq i8 %shr, -30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @exact_ashr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @exact_ashr_ne_noexactlog(i8 %a) {
>> + %shr = ashr exact i8 -90, %a
>> + %cmp = icmp ne i8 %shr, -30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_eq_noexactlog
>> +; CHECK-NEXT: ret i1 false
>> +define i1 @nonexact_ashr_eq_noexactlog(i8 %a) {
>> + %shr = ashr i8 -90, %a
>> + %cmp = icmp eq i8 %shr, -30
>> + ret i1 %cmp
>> +}
>> +
>> +; CHECK-LABEL: @nonexact_ashr_ne_noexactlog
>> +; CHECK-NEXT: ret i1 true
>> +define i1 @nonexact_ashr_ne_noexactlog(i8 %a) {
>> + %shr = ashr i8 -90, %a
>> + %cmp = icmp ne i8 %shr, -30
>> + ret i1 %cmp
>> +}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141019/6273d895/attachment.html>


More information about the llvm-commits mailing list