[llvm-commits] [llvm] r153419 - in /llvm/trunk: lib/Analysis/InstructionSimplify.cpp test/Transforms/InstSimplify/compare.ll

Duncan Sands baldrick at free.fr
Mon Mar 26 03:26:15 PDT 2012


Hi Chandler,

> Teach instsimplify how to simplify comparisons of pointers which are
> constant-offsets of a common base using the generic GEP-walking logic
> I added for computing pointer differences in the same situation.

> --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
> +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Sun Mar 25 16:28:14 2012
> @@ -1591,6 +1591,45 @@
>     return 0;
>   }
>
> +static Constant *computePointerICmp(const TargetData&TD,
> +                                    CmpInst::Predicate Pred,
> +                                    Value *LHS, Value *RHS) {
> +  // We can only fold certain predicates on pointer comparisons.
> +  switch (Pred) {
> +  default:
> +    return 0;
> +
> +    // Equality comaprisons are easy to fold.

comaprisons -> comparisons

> +  case CmpInst::ICMP_EQ:
> +  case CmpInst::ICMP_NE:
> +    break;
> +
> +    // We can only handle unsigned relational comparisons because 'inbounds' on
> +    // a GEP only protects against unsigned wrapping.
> +  case CmpInst::ICMP_UGT:
> +  case CmpInst::ICMP_UGE:
> +  case CmpInst::ICMP_ULT:
> +  case CmpInst::ICMP_ULE:
> +    // However, we have to switch them to their signed variants to handle
> +    // negative indices from the base pointer.
> +    Pred = ICmpInst::getSignedPredicate(Pred);

Is this correct?  For example, suppose the base pointer is null (otherwise
known as 0), LHSOffset is 2^31-1, RHSOffset is 2^31, and you are doing a
unsigned < comparison.  The result should be true, but you will return false.

Ciao, Duncan.

> +    break;
> +  }
> +
> +  Constant *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
> +  if (!LHSOffset)
> +    return 0;
> +  Constant *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
> +  if (!RHSOffset)
> +    return 0;
> +
> +  // If LHS and RHS are not related via constant offsets to the same base
> +  // value, there is nothing we can do here.
> +  if (LHS != RHS)
> +    return 0;
> +
> +  return ConstantExpr::getICmp(Pred, LHSOffset, RHSOffset);
> +}
>
>   /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
>   /// fold the result.  If not, this returns null.
> @@ -2311,7 +2350,12 @@
>         return getFalse(ITy);
>     }
>
> -  // Simplify comparisons of GEPs.
> +  // Simplify comparisons of related pointers using a powerful, recursive
> +  // GEP-walk when we have target data available..
> +  if (Q.TD&&  LHS->getType()->isPointerTy()&&  RHS->getType()->isPointerTy())
> +    if (Constant *C = computePointerICmp(*Q.TD, Pred, LHS, RHS))
> +      return C;
> +
>     if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) {
>       if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) {
>         if (GLHS->getPointerOperand() == GRHS->getPointerOperand()&&
>
> Modified: llvm/trunk/test/Transforms/InstSimplify/compare.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/compare.ll?rev=153419&r1=153418&r2=153419&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstSimplify/compare.ll (original)
> +++ llvm/trunk/test/Transforms/InstSimplify/compare.ll Sun Mar 25 16:28:14 2012
> @@ -103,6 +103,68 @@
>   ; CHECK: ret i1 %equal
>   }
>
> +define i1 @gep9(i8* %ptr) {
> +; CHECK: @gep9
> +; CHECK-NOT: ret
> +; CHECK: ret i1 true
> +
> +entry:
> +  %first1 = getelementptr inbounds i8* %ptr, i32 0
> +  %first2 = getelementptr inbounds i8* %first1, i32 1
> +  %first3 = getelementptr inbounds i8* %first2, i32 2
> +  %first4 = getelementptr inbounds i8* %first3, i32 4
> +  %last1 = getelementptr inbounds i8* %first2, i32 48
> +  %last2 = getelementptr inbounds i8* %last1, i32 8
> +  %last3 = getelementptr inbounds i8* %last2, i32 -4
> +  %last4 = getelementptr inbounds i8* %last3, i32 -4
> +  %first.int = ptrtoint i8* %first4 to i32
> +  %last.int = ptrtoint i8* %last4 to i32
> +  %cmp = icmp ne i32 %last.int, %first.int
> +  ret i1 %cmp
> +}
> +
> +define i1 @gep10(i8* %ptr) {
> +; CHECK: @gep10
> +; CHECK-NOT: ret
> +; CHECK: ret i1 true
> +
> +entry:
> +  %first1 = getelementptr inbounds i8* %ptr, i32 -2
> +  %first2 = getelementptr inbounds i8* %first1, i32 44
> +  %last1 = getelementptr inbounds i8* %ptr, i32 48
> +  %last2 = getelementptr inbounds i8* %last1, i32 -6
> +  %first.int = ptrtoint i8* %first2 to i32
> +  %last.int = ptrtoint i8* %last2 to i32
> +  %cmp = icmp eq i32 %last.int, %first.int
> +  ret i1 %cmp
> +}
> +
> +define i1 @gep11(i8* %ptr) {
> +; CHECK: @gep11
> +; CHECK-NOT: ret
> +; CHECK: ret i1 true
> +
> +entry:
> +  %first1 = getelementptr inbounds i8* %ptr, i32 -2
> +  %last1 = getelementptr inbounds i8* %ptr, i32 48
> +  %last2 = getelementptr inbounds i8* %last1, i32 -6
> +  %cmp = icmp ult i8* %first1, %last2
> +  ret i1 %cmp
> +}
> +
> +define i1 @gep12(i8* %ptr) {
> +; CHECK: @gep12
> +; CHECK-NOT: ret
> +; CHECK: ret i1 %cmp
> +
> +entry:
> +  %first1 = getelementptr inbounds i8* %ptr, i32 -2
> +  %last1 = getelementptr inbounds i8* %ptr, i32 48
> +  %last2 = getelementptr inbounds i8* %last1, i32 -6
> +  %cmp = icmp slt i8* %first1, %last2
> +  ret i1 %cmp
> +}
> +
>   define i1 @zext(i32 %x) {
>   ; CHECK: @zext
>     %e1 = zext i32 %x to i64
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list