|
20 | 20 | #include "llvm/IR/InstIterator.h"
|
21 | 21 | #include "llvm/IR/LLVMContext.h"
|
22 | 22 | #include "llvm/IR/Module.h"
|
| 23 | +#include "llvm/IR/PatternMatch.h" |
23 | 24 | #include "llvm/IR/Verifier.h"
|
24 | 25 | #include "gtest/gtest.h"
|
25 | 26 |
|
26 | 27 | namespace llvm {
|
27 | 28 |
|
| 29 | +using namespace PatternMatch; |
| 30 | + |
28 | 31 | // We use this fixture to ensure that we clean up ScalarEvolution before
|
29 | 32 | // deleting the PassManager.
|
30 | 33 | class ScalarEvolutionExpanderTest : public testing::Test {
|
@@ -917,4 +920,53 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
|
917 | 920 | TestMatchingCanonicalIV(GetAR5, ARBitWidth);
|
918 | 921 | }
|
919 | 922 |
|
| 923 | +TEST_F(ScalarEvolutionExpanderTest, ExpandNonIntegralPtrWithNullBase) { |
| 924 | + LLVMContext C; |
| 925 | + SMDiagnostic Err; |
| 926 | + |
| 927 | + std::unique_ptr<Module> M = |
| 928 | + parseAssemblyString("target datalayout = " |
| 929 | + "\"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:" |
| 930 | + "128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2\"" |
| 931 | + "define float addrspace(1)* @test(i64 %offset) { " |
| 932 | + " %ptr = getelementptr inbounds float, float " |
| 933 | + "addrspace(1)* null, i64 %offset" |
| 934 | + " ret float addrspace(1)* %ptr" |
| 935 | + "}", |
| 936 | + Err, C); |
| 937 | + |
| 938 | + assert(M && "Could not parse module?"); |
| 939 | + assert(!verifyModule(*M) && "Must have been well formed!"); |
| 940 | + |
| 941 | + runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) { |
| 942 | + auto &I = GetInstByName(F, "ptr"); |
| 943 | + auto PtrPlus1 = |
| 944 | + SE.getAddExpr(SE.getSCEV(&I), SE.getConstant(I.getType(), 1)); |
| 945 | + SCEVExpander Exp(SE, M->getDataLayout(), "expander"); |
| 946 | + |
| 947 | + Value *V = Exp.expandCodeFor(PtrPlus1, I.getType(), &I); |
| 948 | + I.replaceAllUsesWith(V); |
| 949 | + |
| 950 | + // Check the expander created bitcast (gep i8* null, %offset). |
| 951 | + auto *Cast = dyn_cast<BitCastInst>(V); |
| 952 | + EXPECT_TRUE(Cast); |
| 953 | + EXPECT_EQ(Cast->getType(), I.getType()); |
| 954 | + auto *GEP = dyn_cast<GetElementPtrInst>(Cast->getOperand(0)); |
| 955 | + EXPECT_TRUE(GEP); |
| 956 | + EXPECT_TRUE(cast<Constant>(GEP->getPointerOperand())->isNullValue()); |
| 957 | + EXPECT_EQ(cast<PointerType>(GEP->getPointerOperand()->getType()) |
| 958 | + ->getAddressSpace(), |
| 959 | + cast<PointerType>(I.getType())->getAddressSpace()); |
| 960 | + |
| 961 | + // Check the expander created the expected index computation: add (shl |
| 962 | + // %offset, 2), 1. |
| 963 | + Value *Arg; |
| 964 | + EXPECT_TRUE( |
| 965 | + match(GEP->getOperand(1), |
| 966 | + m_Add(m_Shl(m_Value(Arg), m_SpecificInt(2)), m_SpecificInt(1)))); |
| 967 | + EXPECT_EQ(Arg, &*F.arg_begin()); |
| 968 | + EXPECT_FALSE(verifyFunction(F, &errs())); |
| 969 | + }); |
| 970 | +} |
| 971 | + |
920 | 972 | } // end namespace llvm
|
0 commit comments