diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/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(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) diff --git a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp --- a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp +++ b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp @@ -917,4 +917,38 @@ TestMatchingCanonicalIV(GetAR5, ARBitWidth); } +TEST_F(ScalarEvolutionExpanderTest, ExpandNonIntegralPtrWithNullBase) { + LLVMContext C; + SMDiagnostic Err; + + std::unique_ptr 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(V); + EXPECT_TRUE(GEP); + auto *UDiv = dyn_cast(GEP->getOperand(1)); + EXPECT_TRUE(UDiv); + EXPECT_FALSE(verifyFunction(F, &errs())); + }); +} + } // end namespace llvm