[llvm] d992606 - [InstCombine] Fold phi ( inttoptr/ptrtoint x ) to phi (x)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 3 05:23:21 PDT 2021


Author: Krishna
Date: 2021-08-03T17:52:59+05:30
New Revision: d99260641b30b0638c6a1e60bcb971ec09fa5368

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

LOG: [InstCombine] Fold phi ( inttoptr/ptrtoint x ) to phi (x)

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.

In this patch, we focus on phi-node operands with inttoptr casts.
We know that ptrtoint( inttoptr( ptrtoint x) ) is same as ptrtoint (x).
So, we want to remove this roundtrip cast which goes through phi-node.

Reviewed By: aqjune

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

Added: 
    llvm/test/Transforms/InstCombine/phi-int2ptr-fold.ll

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index dda35ca44dd0..cefb947567e9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -22,6 +22,7 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstVisitor.h"
 #include "llvm/IR/PatternMatch.h"
+#include "llvm/IR/Value.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Transforms/InstCombine/InstCombineWorklist.h"
@@ -623,6 +624,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *foldPHIArgGEPIntoPHI(PHINode &PN);
   Instruction *foldPHIArgLoadIntoPHI(PHINode &PN);
   Instruction *foldPHIArgZextsIntoPHI(PHINode &PN);
+  Instruction *foldPHIArgIntToPtrToPHI(PHINode &PN);
 
   /// If an integer typed PHI has only one use which is an IntToPtr operation,
   /// replace the PHI with an existing pointer typed PHI if it exists. Otherwise

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
index 6c6351c70e3a..35739c3b9a21 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -299,6 +299,29 @@ Instruction *InstCombinerImpl::foldIntegerTypedPHI(PHINode &PN) {
                                           IntToPtr->getOperand(0)->getType());
 }
 
+// Remove RoundTrip IntToPtr/PtrToInt Cast on PHI-Operand and
+// fold Phi-operand to bitcast.
+Instruction *InstCombinerImpl::foldPHIArgIntToPtrToPHI(PHINode &PN) {
+  // convert ptr2int ( phi[ int2ptr(ptr2int(x))] ) --> ptr2int ( phi [ x ] )
+  // Make sure all uses of phi are ptr2int.
+  if (!all_of(PN.users(), [](User *U) { return isa<PtrToIntInst>(U); }))
+    return nullptr;
+
+  // Iterating over all operands to check presence of target pointers for
+  // optimization.
+  bool OperandWithRoundTripCast = false;
+  for (unsigned OpNum = 0; OpNum != PN.getNumIncomingValues(); ++OpNum) {
+    if (auto *NewOp =
+            simplifyIntToPtrRoundTripCast(PN.getIncomingValue(OpNum))) {
+      PN.setIncomingValue(OpNum, NewOp);
+      OperandWithRoundTripCast = true;
+    }
+  }
+  if (!OperandWithRoundTripCast)
+    return nullptr;
+  return &PN;
+}
+
 /// If we have something like phi [insertvalue(a,b,0), insertvalue(c,d,0)],
 /// turn this into a phi[a,c] and phi[b,d] and a single insertvalue.
 Instruction *
@@ -1306,6 +1329,9 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
   if (Instruction *Result = foldPHIArgZextsIntoPHI(PN))
     return Result;
 
+  if (Instruction *Result = foldPHIArgIntToPtrToPHI(PN))
+    return Result;
+
   // If all PHI operands are the same operation, pull them through the PHI,
   // reducing code size.
   if (isa<Instruction>(PN.getIncomingValue(0)) &&

diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 4e3b18e805ee..434659cf4b2c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -359,7 +359,8 @@ Value *InstCombinerImpl::simplifyIntToPtrRoundTripCast(Value *Val) {
             PtrToInt->getSrcTy()->getPointerAddressSpace() &&
         DL.getPointerTypeSizeInBits(PtrToInt->getSrcTy()) ==
             DL.getTypeSizeInBits(PtrToInt->getDestTy())) {
-      return Builder.CreateBitCast(PtrToInt->getOperand(0), CastTy);
+      return CastInst::CreateBitOrPointerCast(PtrToInt->getOperand(0), CastTy,
+                                              "", PtrToInt);
     }
   }
   return nullptr;

diff  --git a/llvm/test/Transforms/InstCombine/phi-int2ptr-fold.ll b/llvm/test/Transforms/InstCombine/phi-int2ptr-fold.ll
new file mode 100644
index 000000000000..015aa9df5a30
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/phi-int2ptr-fold.ll
@@ -0,0 +1,175 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -instcombine -S -disable-i2p-p2i-opt < %s | FileCheck %s
+
+target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; convert ptrtoint [ phi[ inttoptr (ptrtoint (x) ) ] ---> ptrtoint (phi[x])
+
+define i64 @func(i32** %X, i32** %Y, i1 %cond) {
+; CHECK-LABEL: @func(
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PHI_IN_IN:%.*]] = phi i32** [ [[X:%.*]], [[BB1]] ], [ [[Y:%.*]], [[BB2]] ]
+; CHECK-NEXT:    [[PHI_IN:%.*]] = ptrtoint i32** [[PHI_IN_IN]] to i64
+; CHECK-NEXT:    ret i64 [[PHI_IN]]
+;
+  br i1 %cond, label %bb1, label %bb2
+
+bb1:
+  %X.i = ptrtoint i32** %X to i64
+  %X.p = inttoptr i64 %X.i to i32*
+  br label %exit
+
+bb2:
+  %Y.i = ptrtoint i32** %Y to i64
+  %Y.p = inttoptr i64 %Y.i to i32*
+  br label %exit
+
+exit:
+  %phi = phi i32* [%X.p, %bb1], [%Y.p, %bb2]
+  %X.p.i = ptrtoint i32* %phi to i64
+  ret i64 %X.p.i
+}
+
+define i64 @func_single_operand(i32** %X, i32** %Y, i1 %cond) {
+; CHECK-LABEL: @func_single_operand(
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PHI_IN:%.*]] = phi i32** [ [[X:%.*]], [[BB1]] ], [ [[Y:%.*]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    [[X_P_I:%.*]] = ptrtoint i32** [[PHI_IN]] to i64
+; CHECK-NEXT:    ret i64 [[X_P_I]]
+;
+  %Y.p = bitcast i32** %Y to i32*
+  br i1 %cond, label %bb1, label %exit
+
+bb1:
+  %X.i = ptrtoint i32** %X to i64
+  %X.p = inttoptr i64 %X.i to i32*
+  br label %exit
+
+exit:
+  %phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
+  %X.p.i = ptrtoint i32* %phi to i64
+  ret i64 %X.p.i
+}
+
+define i64 @func_pointer_
diff erent_types(i16** %X, i32** %Y, i1 %cond) {
+; CHECK-LABEL: @func_pointer_
diff erent_types(
+; CHECK-NEXT:    [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i16** [[X:%.*]] to i32*
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32* [ [[TMP1]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    [[X_P_I:%.*]] = ptrtoint i32* [[PHI]] to i64
+; CHECK-NEXT:    ret i64 [[X_P_I]]
+;
+  %Y.p = bitcast i32** %Y to i32*
+  br i1 %cond, label %bb1, label %exit
+
+bb1:
+  %X.i = ptrtoint i16** %X to i64
+  %X.p = inttoptr i64 %X.i to i32*
+  br label %exit
+
+exit:
+  %phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
+  %X.p.i = ptrtoint i32* %phi to i64
+  ret i64 %X.p.i
+}
+
+; Negative test - Wrong Integer type
+
+define i64 @func_integer_type_too_small(i32** %X, i32** %Y, i1 %cond) {
+; CHECK-LABEL: @func_integer_type_too_small(
+; CHECK-NEXT:    [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint i32** [[X:%.*]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = and i64 [[TMP1]], 4294967295
+; CHECK-NEXT:    [[X_P:%.*]] = inttoptr i64 [[TMP2]] to i32*
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32* [ [[X_P]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    [[X_P_I:%.*]] = ptrtoint i32* [[PHI]] to i64
+; CHECK-NEXT:    ret i64 [[X_P_I]]
+;
+  %Y.p = bitcast i32** %Y to i32*
+  br i1 %cond, label %bb1, label %exit
+
+bb1:
+  %X.i = ptrtoint i32** %X to i32
+  %X.p = inttoptr i32 %X.i to i32*
+  br label %exit
+
+exit:
+  %phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
+  %X.p.i = ptrtoint i32* %phi to i64
+  ret i64 %X.p.i
+}
+
+; Negative test - phi not used in ptrtoint
+
+define i32* @func_phi_not_use_in_ptr2int(i32** %X, i32** %Y, i1 %cond) {
+; CHECK-LABEL: @func_phi_not_use_in_ptr2int(
+; CHECK-NEXT:    [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint i32** [[X:%.*]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = and i64 [[TMP1]], 4294967295
+; CHECK-NEXT:    [[X_P:%.*]] = inttoptr i64 [[TMP2]] to i32*
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32* [ [[X_P]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    ret i32* [[PHI]]
+;
+  %Y.p = bitcast i32** %Y to i32*
+  br i1 %cond, label %bb1, label %exit
+
+bb1:
+  %X.i = ptrtoint i32** %X to i32
+  %X.p = inttoptr i32 %X.i to i32*
+  br label %exit
+
+exit:
+  %phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
+  ret i32* %phi
+}
+
+; Negative test - Pointers in 
diff erent address spaces
+
+define i64 @func_ptr_
diff erent_addrspace(i16 addrspace(2)* %X, i32** %Y, i1 %cond) {
+; CHECK-LABEL: @func_ptr_
diff erent_addrspace(
+; CHECK-NEXT:    [[Y_P:%.*]] = bitcast i32** [[Y:%.*]] to i32*
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint i16 addrspace(2)* [[X:%.*]] to i32
+; CHECK-NEXT:    [[X_I:%.*]] = zext i32 [[TMP1]] to i64
+; CHECK-NEXT:    [[X_P:%.*]] = inttoptr i64 [[X_I]] to i32*
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32* [ [[X_P]], [[BB1]] ], [ [[Y_P]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    [[X_P_I:%.*]] = ptrtoint i32* [[PHI]] to i64
+; CHECK-NEXT:    ret i64 [[X_P_I]]
+;
+  %Y.p = bitcast i32** %Y to i32*
+  br i1 %cond, label %bb1, label %exit
+
+bb1:
+  %X.i = ptrtoint i16 addrspace(2)* %X to i64
+  %X.p = inttoptr i64 %X.i to i32*
+  br label %exit
+
+exit:
+  %phi = phi i32* [%X.p, %bb1], [%Y.p, %0]
+  %X.p.i = ptrtoint i32* %phi to i64
+  ret i64 %X.p.i
+}


        


More information about the llvm-commits mailing list