[PATCH] D87827: [SCEVExpander] Support expanding nonintegral pointers with constant base.

Florian Hahn via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 05:39:15 PDT 2020


fhahn created this revision.
fhahn added reviewers: mkazantsev, reames, efriedma, arsenm.
Herald added subscribers: javed.absar, hiraditya.
Herald added a project: LLVM.
fhahn requested review of this revision.
Herald added a subscriber: wdng.

Currently SCEVExpander creates inttoptr for non-integral pointers if the
base is a null constant for example. This results in invalid IR.

This patch changes InsertNoopCastOfTo to emit a GEP to convert to a
non-integral pointer. The GEP uses null as base. The original value is
converted to an index by dividing by the alloc size of the type.

Note that this requires the original value to be divisible by the alloc
size, otherwise the pointer value will be changed. I am not sure if that
is an issue in practice (ideally the expander would only be used for
expanding pointer arithmetic that keeps the result divisible by the
alloc size) and there is not much we could do otherwise.

I guess we could instead try to create a pointer with alloc size of 1
byte, create a GEP with the original value as index and bitcast to the
target type. I am not sure if we can always do that, but I guess we
could add an assertion if that happens.

This was exposed by D71539 <https://reviews.llvm.org/D71539>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87827

Files:
  llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
  llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp


Index: llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
===================================================================
--- llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
+++ llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
@@ -917,4 +917,38 @@
   TestMatchingCanonicalIV(GetAR5, ARBitWidth);
 }
 
+TEST_F(ScalarEvolutionExpanderTest, ExpandNonIntegralPtrWithNullBase) {
+  LLVMContext C;
+  SMDiagnostic Err;
+
+  std::unique_ptr<Module> M =
+      parseAssemblyString("target datalayout = "
+                          "\"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:"
+                          "128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2\""
+                          "define float addrspace(1)* @test(i64 %offset) { "
+                          "  %ptr = getelementptr inbounds float, float "
+                          "addrspace(1)* null, i64 %offset"
+                          "  ret float addrspace(1)* %ptr"
+                          "}",
+                          Err, C);
+
+  assert(M && "Could not parse module?");
+  assert(!verifyModule(*M) && "Must have been well formed!");
+
+  runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+    auto &I = GetInstByName(F, "ptr");
+    auto PtrPlus4 =
+        SE.getAddExpr(SE.getSCEV(&I), SE.getConstant(I.getType(), 4));
+    SCEVExpander Exp(SE, M->getDataLayout(), "expander");
+
+    Value *V = Exp.expandCodeFor(PtrPlus4, I.getType(), &I);
+    I.replaceAllUsesWith(V);
+    auto *GEP = dyn_cast<GetElementPtrInst>(V);
+    EXPECT_TRUE(GEP);
+    auto *UDiv = dyn_cast<BinaryOperator>(GEP->getOperand(1));
+    EXPECT_TRUE(UDiv);
+    EXPECT_FALSE(verifyFunction(F, &errs()));
+  });
+}
+
 } // end namespace llvm
Index: llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
===================================================================
--- llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -126,6 +126,19 @@
   assert(SE.getTypeSizeInBits(V->getType()) == SE.getTypeSizeInBits(Ty) &&
          "InsertNoopCastOfTo cannot change sizes!");
 
+  auto *PtrTy = dyn_cast<PointerType>(Ty);
+  // inttoptr only works for integral pointers. For non-integral pointers, we
+  // can convert the integer value to an index and create a GEP starting at
+  // null. The conversion requires dividing by the alloc size of the type and
+  // the reminder of the division will be stripped.
+  if (Op == Instruction::IntToPtr && DL.isNonIntegralPointerType(PtrTy)) {
+    auto *Idx = Builder.CreateUDiv(
+        V, ConstantInt::get(V->getType(),
+                            DL.getTypeAllocSize(PtrTy->getElementType())));
+    auto *GEP = Builder.CreateGEP(
+        PtrTy->getElementType(), Constant::getNullValue(PtrTy), Idx, "uglygep");
+    return GEP;
+  }
   // Short-circuit unnecessary bitcasts.
   if (Op == Instruction::BitCast) {
     if (V->getType() == Ty)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87827.292472.patch
Type: text/x-patch
Size: 2973 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200917/91e4430f/attachment.bin>


More information about the llvm-commits mailing list