[llvm] [InferAddressSpaces] apply InferAddressSpaces to inttoptr-zext-ptrtoint address expression. (PR #79108)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 22 23:59:26 PST 2024


https://github.com/yujc9 updated https://github.com/llvm/llvm-project/pull/79108

>From 0f1319119257535b88290954022bd24935d566a2 Mon Sep 17 00:00:00 2001
From: "Jincheng.Yu" <jincheng.yu at iluvatar.com>
Date: Tue, 23 Jan 2024 15:04:06 +0800
Subject: [PATCH] [InferAddressSpaces] apply InferAddressSpaces to
 inttoptr-zext-ptrtoint address expression.

Signed-off-by: Jincheng.Yu <yujc.astro at outlook.com>
---
 .../Transforms/Scalar/InferAddressSpaces.cpp  | 61 ++++++++++++++++---
 .../AMDGPU/zext-ptrint-conversion.ll          | 58 ++++++++++++++++++
 2 files changed, 112 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/Transforms/InferAddressSpaces/AMDGPU/zext-ptrint-conversion.ll

diff --git a/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp b/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp
index 1bf50d79e5331e9..b2008576e56489c 100644
--- a/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp
+++ b/llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp
@@ -300,6 +300,34 @@ static bool isNoopPtrIntCastPair(const Operator *I2P, const DataLayout &DL,
          (P2IOp0AS == I2PAS || TTI->isNoopAddrSpaceCast(P2IOp0AS, I2PAS));
 }
 
+// Check whether that's pointer bitcast using `ptrtoint`-`zext`-`inttoptr`
+static bool isZExtPtrIntCastPair(const Operator *I2P, const DataLayout &DL) {
+  assert(I2P->getOpcode() == Instruction::IntToPtr);
+  auto *ZExt = dyn_cast<Operator>(I2P->getOperand(0));
+  if (!ZExt || ZExt->getOpcode() != Instruction::ZExt)
+    return false;
+  auto *P2I = dyn_cast<Operator>(ZExt->getOperand(0));
+  if (!P2I || P2I->getOpcode() != Instruction::PtrToInt)
+    return false;
+  unsigned P2IOp0AS = P2I->getOperand(0)->getType()->getPointerAddressSpace();
+  unsigned I2PAS = I2P->getType()->getPointerAddressSpace();
+  unsigned P2IOp0SizeInBits =
+      DL.getIntPtrType(P2I->getOperand(0)->getType())->getScalarSizeInBits();
+  unsigned I2PSizeInBits =
+      DL.getIntPtrType(I2P->getType())->getScalarSizeInBits();
+  // Check:
+  // 1. `inttoptr` and `ptrtoint` are no-op casts
+  // 2. src address pointer and dst address pointer should be different address
+  // space and different size
+  return CastInst::isNoopCast(Instruction::CastOps(I2P->getOpcode()),
+                              I2P->getOperand(0)->getType(), I2P->getType(),
+                              DL) &&
+         CastInst::isNoopCast(Instruction::CastOps(P2I->getOpcode()),
+                              P2I->getOperand(0)->getType(), P2I->getType(),
+                              DL) &&
+         (P2IOp0AS != I2PAS) && (P2IOp0SizeInBits < I2PSizeInBits);
+}
+
 // Returns true if V is an address expression.
 // TODO: Currently, we consider only phi, bitcast, addrspacecast, and
 // getelementptr operators.
@@ -324,7 +352,7 @@ static bool isAddressExpression(const Value &V, const DataLayout &DL,
     return II && II->getIntrinsicID() == Intrinsic::ptrmask;
   }
   case Instruction::IntToPtr:
-    return isNoopPtrIntCastPair(Op, DL, TTI);
+    return isNoopPtrIntCastPair(Op, DL, TTI) || isZExtPtrIntCastPair(Op, DL);
   default:
     // That value is an address expression if it has an assumed address space.
     return TTI->getAssumedAddrSpace(&V) != UninitializedAddressSpace;
@@ -356,9 +384,15 @@ getPointerOperands(const Value &V, const DataLayout &DL,
     return {II.getArgOperand(0)};
   }
   case Instruction::IntToPtr: {
-    assert(isNoopPtrIntCastPair(&Op, DL, TTI));
-    auto *P2I = cast<Operator>(Op.getOperand(0));
-    return {P2I->getOperand(0)};
+    assert(isNoopPtrIntCastPair(&Op, DL, TTI) || isZExtPtrIntCastPair(&Op, DL));
+    if (isNoopPtrIntCastPair(&Op, DL, TTI)) {
+      auto *P2I = cast<Operator>(Op.getOperand(0));
+      return {P2I->getOperand(0)};
+    } else {
+      auto *ZExt = cast<Operator>(Op.getOperand(0));
+      auto *P2I = dyn_cast<Operator>(ZExt->getOperand(0));
+      return {P2I->getOperand(0)};
+    }
   }
   default:
     llvm_unreachable("Unexpected instruction type.");
@@ -521,8 +555,13 @@ InferAddressSpacesImpl::collectFlatAddressExpressions(Function &F) const {
     } else if (auto *ASC = dyn_cast<AddrSpaceCastInst>(&I)) {
       PushPtrOperand(ASC->getPointerOperand());
     } else if (auto *I2P = dyn_cast<IntToPtrInst>(&I)) {
-      if (isNoopPtrIntCastPair(cast<Operator>(I2P), *DL, TTI))
+      if (isNoopPtrIntCastPair(cast<Operator>(I2P), *DL, TTI)) {
         PushPtrOperand(cast<Operator>(I2P->getOperand(0))->getOperand(0));
+      } else if (isZExtPtrIntCastPair(cast<Operator>(I2P), *DL)) {
+        auto *ZExt = I2P->getOperand(0);
+        auto *P2I = cast<Operator>(ZExt)->getOperand(0);
+        PushPtrOperand(cast<Operator>(P2I)->getOperand(0));
+      }
     } else if (auto *RI = dyn_cast<ReturnInst>(&I)) {
       if (auto *RV = RI->getReturnValue();
           RV && RV->getType()->isPtrOrPtrVectorTy())
@@ -683,8 +722,16 @@ Value *InferAddressSpacesImpl::cloneInstructionWithNewAddressSpace(
     return SelectInst::Create(I->getOperand(0), NewPointerOperands[1],
                               NewPointerOperands[2], "", nullptr, I);
   case Instruction::IntToPtr: {
-    assert(isNoopPtrIntCastPair(cast<Operator>(I), *DL, TTI));
-    Value *Src = cast<Operator>(I->getOperand(0))->getOperand(0);
+    assert(isNoopPtrIntCastPair(cast<Operator>(I), *DL, TTI) ||
+           isZExtPtrIntCastPair(cast<Operator>(I), *DL));
+    Value *Src;
+    if (isNoopPtrIntCastPair(cast<Operator>(I), *DL, TTI)) {
+      Src = cast<Operator>(I->getOperand(0))->getOperand(0);
+    } else { // isZExtPtrIntCastPair
+      auto *ZExt = I->getOperand(0);
+      auto *P2I = cast<Operator>(ZExt)->getOperand(0);
+      Src = cast<Operator>(P2I)->getOperand(0);
+    }
     if (Src->getType() == NewPtrType)
       return Src;
 
diff --git a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/zext-ptrint-conversion.ll b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/zext-ptrint-conversion.ll
new file mode 100644
index 000000000000000..28acbb6a37a600b
--- /dev/null
+++ b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/zext-ptrint-conversion.ll
@@ -0,0 +1,58 @@
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -o - -passes=infer-address-spaces %s | FileCheck -check-prefixes=COMMON,AMDGCN %s
+; RUN: opt -S -o - -passes=infer-address-spaces -assume-default-is-flat-addrspace %s | FileCheck -check-prefixes=COMMON,NOTTI %s
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-ni:7:8"
+
+; COMMON-LABEL: @zext_ptrint_conversion(
+; AMDGCN-NEXT: store i32 0, ptr addrspace(3) %{{.*}}
+; AMDGCN-NEXT: ret void
+; NOTTI-NEXT: ptrtoint ptr addrspace(3) %{{.*}} to i64
+; NOTTI-NEXT: zext i32 %{{.*}} to i64
+; NOTTI-NEXT: inttoptr i64 %{{.*}} to ptr
+; NOTTI-NEXT: store i32 0, ptr %{{.*}}
+; NOTTI-NEXT: ret void
+define void @zext_ptrint_conversion(ptr addrspace(3) %x) {
+  %1 = ptrtoint ptr addrspace(3) %x to i32
+  %2 = zext i32 %1 to i64
+  %3 = inttoptr i64 %2 to ptr
+  store i32 0, ptr %3
+  ret void
+}
+
+; COMMON-LABEL: @non_zext_ptrint_conversion(
+; AMDGCN-NEXT: ptrtoint ptr addrspace(3) %{{.*}} to i16
+; AMDGCN-NEXT: zext i16 %{{.*}} to i64
+; AMDGCN-NEXT: inttoptr i64 %{{.*}} to ptr
+; AMDGCN-NEXT: store i32 0, ptr %{{.*}}
+; AMDGCN-NEXT: ret void
+; NOTTI-NEXT: ptrtoint ptr addrspace(3) %{{.*}} to i16
+; NOTTI-NEXT: zext i16 %{{.*}} to i64
+; NOTTI-NEXT: inttoptr i64 %{{.*}} to ptr
+; NOTTI-NEXT: store i32 0, ptr %{{.*}}
+; NOTTI-NEXT: ret void
+define void @non_zext_ptrint_conversion(ptr addrspace(3) %x) {
+  %1 = ptrtoint ptr addrspace(3) %x to i16
+  %2 = zext i16 %1 to i64
+  %3 = inttoptr i64 %2 to ptr
+  store i32 0, ptr %3
+  ret void
+}
+
+; COMMON-LABEL: @non_zext_ptrint_conversion2(
+; AMDGCN-NEXT: ptrtoint ptr addrspace(3) %{{.*}} to i32
+; AMDGCN-NEXT: zext i32 %{{.*}} to i128
+; AMDGCN-NEXT: inttoptr i128 %{{.*}} to ptr
+; AMDGCN-NEXT: store i32 0, ptr %{{.*}}
+; AMDGCN-NEXT: ret void
+; NOTTI-NEXT: ptrtoint ptr addrspace(3) %{{.*}} to i32
+; NOTTI-NEXT: zext i32 %{{.*}} to i128
+; NOTTI-NEXT: inttoptr i128 %{{.*}} to ptr
+; NOTTI-NEXT: store i32 0, ptr %{{.*}}
+; NOTTI-NEXT: ret void
+define void @non_zext_ptrint_conversion2(ptr addrspace(3) %x) {
+  %1 = ptrtoint ptr addrspace(3) %x to i32
+  %2 = zext i32 %1 to i128
+  %3 = inttoptr i128 %2 to ptr
+  store i32 0, ptr %3
+  ret void
+}



More information about the llvm-commits mailing list