[llvm] da92e86 - [InstCombine] Fold IntToPtr/PtrToInt to bitcast

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 18 14:14:45 PDT 2021


Author: Krishna Kariya
Date: 2021-07-18T23:13:25+02:00
New Revision: da92e86263c3dcbe0d19fe68d1be2373b74eedf5

URL: https://github.com/llvm/llvm-project/commit/da92e86263c3dcbe0d19fe68d1be2373b74eedf5
DIFF: https://github.com/llvm/llvm-project/commit/da92e86263c3dcbe0d19fe68d1be2373b74eedf5.diff

LOG: [InstCombine] Fold IntToPtr/PtrToInt to bitcast

The inttoptr/ptrtoint roundtrip optimization is not always correct.
We are working towards removing this optimization and adding support
to specific cases where this optimization works. This patch is the
first one on this line.

Consider the example:

    %i = ptrtoint i8* %X to i64
    %p = inttoptr i64 %i to i16*
    %cmp = icmp eq i8* %load, %p

In this specific case, the inttoptr/ptrtoint optimization is correct
as it only compares the pointer values. In this patch, we fold
inttoptr/ptrtoint to a bitcast (if src and dest types are different).

Differential Revision: https://reviews.llvm.org/D105088

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/test/Transforms/InstCombine/ptr-int-ptr-icmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 6de4c4d4aa34e..2b0ef0c5f2cce 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4571,6 +4571,16 @@ static Instruction *foldICmpWithZextOrSext(ICmpInst &ICmp,
 
 /// Handle icmp (cast x), (cast or constant).
 Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
+  // If any operand of ICmp is a inttoptr roundtrip cast then remove it as
+  // icmp compares only pointer's value.
+  // icmp (inttoptr (ptrtoint p1)), p2 --> icmp p1, p2.
+  Value *SimplifiedOp0 = simplifyIntToPtrRoundTripCast(ICmp.getOperand(0));
+  Value *SimplifiedOp1 = simplifyIntToPtrRoundTripCast(ICmp.getOperand(1));
+  if (SimplifiedOp0 || SimplifiedOp1)
+    return new ICmpInst(ICmp.getPredicate(),
+                        SimplifiedOp0 ? SimplifiedOp0 : ICmp.getOperand(0),
+                        SimplifiedOp1 ? SimplifiedOp1 : ICmp.getOperand(1));
+
   auto *CastOp0 = dyn_cast<CastInst>(ICmp.getOperand(0));
   if (!CastOp0)
     return nullptr;

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 76552801a7f95..6d0690dde9e02 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -340,6 +340,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   /// \see CastInst::isEliminableCastPair
   Instruction::CastOps isEliminableCastPair(const CastInst *CI1,
                                             const CastInst *CI2);
+  Value *simplifyIntToPtrRoundTripCast(Value *Val);
 
   Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, BinaryOperator &And);
   Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, BinaryOperator &Or);

diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 9646a8c7d02d1..07b354f596a11 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -346,6 +346,25 @@ static bool simplifyAssocCastAssoc(BinaryOperator *BinOp1,
   return true;
 }
 
+// Simplifies IntToPtr/PtrToInt RoundTrip Cast To BitCast.
+// inttoptr ( ptrtoint (x) ) --> x
+Value *InstCombinerImpl::simplifyIntToPtrRoundTripCast(Value *Val) {
+  auto *IntToPtr = dyn_cast<IntToPtrInst>(Val);
+  if (IntToPtr && DL.getPointerTypeSizeInBits(IntToPtr->getDestTy()) ==
+                      DL.getTypeSizeInBits(IntToPtr->getSrcTy())) {
+    auto *PtrToInt = dyn_cast<PtrToIntInst>(IntToPtr->getOperand(0));
+    Type *CastTy = IntToPtr->getDestTy();
+    if (PtrToInt &&
+        CastTy->getPointerAddressSpace() ==
+            PtrToInt->getSrcTy()->getPointerAddressSpace() &&
+        DL.getPointerTypeSizeInBits(PtrToInt->getSrcTy()) ==
+            DL.getTypeSizeInBits(PtrToInt->getDestTy())) {
+      return Builder.CreateBitCast(PtrToInt->getOperand(0), CastTy);
+    }
+  }
+  return nullptr;
+}
+
 /// This performs a few simplifications for operators that are associative or
 /// commutative:
 ///

diff  --git a/llvm/test/Transforms/InstCombine/ptr-int-ptr-icmp.ll b/llvm/test/Transforms/InstCombine/ptr-int-ptr-icmp.ll
index 9784f18730849..f99685c779080 100644
--- a/llvm/test/Transforms/InstCombine/ptr-int-ptr-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/ptr-int-ptr-icmp.ll
@@ -8,9 +8,7 @@ target triple = "x86_64-unknown-linux-gnu"
 
 define i1 @func(i8* %X, i8* %Y) {
 ; CHECK-LABEL: @func(
-; CHECK-NEXT:    [[I:%.*]] = ptrtoint i8* [[X:%.*]] to i64
-; CHECK-NEXT:    [[P:%.*]] = inttoptr i64 [[I]] to i8*
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[P]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %i = ptrtoint i8* %X to i64
@@ -21,9 +19,8 @@ define i1 @func(i8* %X, i8* %Y) {
 
 define i1 @func_pointer_
diff erent_types(i16* %X, i8* %Y) {
 ; CHECK-LABEL: @func_pointer_
diff erent_types(
-; CHECK-NEXT:    [[I:%.*]] = ptrtoint i16* [[X:%.*]] to i64
-; CHECK-NEXT:    [[P:%.*]] = inttoptr i64 [[I]] to i8*
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[P]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i16* [[X:%.*]] to i8*
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[TMP1]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %i = ptrtoint i16* %X to i64
@@ -37,9 +34,8 @@ declare i8* @gen8ptr()
 define i1 @func_commutative(i16* %X) {
 ; CHECK-LABEL: @func_commutative(
 ; CHECK-NEXT:    [[Y:%.*]] = call i8* @gen8ptr()
-; CHECK-NEXT:    [[I:%.*]] = ptrtoint i16* [[X:%.*]] to i64
-; CHECK-NEXT:    [[P:%.*]] = inttoptr i64 [[I]] to i8*
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[Y]], [[P]]
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i16* [[X:%.*]] to i8*
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[Y]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %Y = call i8* @gen8ptr() ; thwart complexity-based canonicalization


        


More information about the llvm-commits mailing list