[llvm] 1d8f2e5 - [SCEVExpander] Support expanding nonintegral pointers with constant base.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 19 09:22:28 PDT 2020
Author: Florian Hahn
Date: 2020-09-19T17:19:53+01:00
New Revision: 1d8f2e52925b3a3ab52726c745169f273239329d
URL: https://github.com/llvm/llvm-project/commit/1d8f2e52925b3a3ab52726c745169f273239329d
DIFF: https://github.com/llvm/llvm-project/commit/1d8f2e52925b3a3ab52726c745169f273239329d.diff
LOG: [SCEVExpander] Support expanding nonintegral pointers with constant base.
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 & bitcast to convert
to a non-integral pointer. First, a GEP of i8* null is generated and the
integral value is used as index. The GEP is then bitcasted to the target
type.
This was exposed by D71539.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D87827
Added:
Modified:
llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 7621f1f35e4e..edf995ab4bb0 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -126,6 +126,20 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, Type *Ty) {
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 create a GEP on i8* null with the integral value as index. Note that
+ // it is safe to use GEP of null instead of inttoptr here, because only
+ // expressions already based on a GEP of null should be converted to pointers
+ // during expansion.
+ if (Op == Instruction::IntToPtr && DL.isNonIntegralPointerType(PtrTy)) {
+ auto *Int8PtrTy = Builder.getInt8PtrTy(PtrTy->getAddressSpace());
+ assert(DL.getTypeAllocSize(Int8PtrTy->getElementType()) == 1 &&
+ "alloc size of i8 must by 1 byte for the GEP to be correct");
+ auto *GEP = Builder.CreateGEP(
+ Builder.getInt8Ty(), Constant::getNullValue(Int8PtrTy), V, "uglygep");
+ return Builder.CreateBitCast(GEP, Ty);
+ }
// Short-circuit unnecessary bitcasts.
if (Op == Instruction::BitCast) {
if (V->getType() == Ty)
diff --git a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
index 6e83370dfeb9..249ba52413e0 100644
--- a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
+++ b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
@@ -20,11 +20,14 @@
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Verifier.h"
#include "gtest/gtest.h"
namespace llvm {
+using namespace PatternMatch;
+
// We use this fixture to ensure that we clean up ScalarEvolution before
// deleting the PassManager.
class ScalarEvolutionExpanderTest : public testing::Test {
@@ -917,4 +920,53 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
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 PtrPlus1 =
+ SE.getAddExpr(SE.getSCEV(&I), SE.getConstant(I.getType(), 1));
+ SCEVExpander Exp(SE, M->getDataLayout(), "expander");
+
+ Value *V = Exp.expandCodeFor(PtrPlus1, I.getType(), &I);
+ I.replaceAllUsesWith(V);
+
+ // Check the expander created bitcast (gep i8* null, %offset).
+ auto *Cast = dyn_cast<BitCastInst>(V);
+ EXPECT_TRUE(Cast);
+ EXPECT_EQ(Cast->getType(), I.getType());
+ auto *GEP = dyn_cast<GetElementPtrInst>(Cast->getOperand(0));
+ EXPECT_TRUE(GEP);
+ EXPECT_TRUE(cast<Constant>(GEP->getPointerOperand())->isNullValue());
+ EXPECT_EQ(cast<PointerType>(GEP->getPointerOperand()->getType())
+ ->getAddressSpace(),
+ cast<PointerType>(I.getType())->getAddressSpace());
+
+ // Check the expander created the expected index computation: add (shl
+ // %offset, 2), 1.
+ Value *Arg;
+ EXPECT_TRUE(
+ match(GEP->getOperand(1),
+ m_Add(m_Shl(m_Value(Arg), m_SpecificInt(2)), m_SpecificInt(1))));
+ EXPECT_EQ(Arg, &*F.arg_begin());
+ EXPECT_FALSE(verifyFunction(F, &errs()));
+ });
+}
+
} // end namespace llvm
More information about the llvm-commits
mailing list