xref: /llvm-project/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp (revision 64b9753d03946d8100e017a5cc4861d5d671c6d0)
1bcbd26bfSFlorian Hahn //=== ScalarEvolutionExpanderTest.cpp - ScalarEvolutionExpander unit tests ===//
2bcbd26bfSFlorian Hahn //
3bcbd26bfSFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bcbd26bfSFlorian Hahn // See https://llvm.org/LICENSE.txt for license information.
5bcbd26bfSFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bcbd26bfSFlorian Hahn //
7bcbd26bfSFlorian Hahn //===----------------------------------------------------------------------===//
8bcbd26bfSFlorian Hahn 
9bcbd26bfSFlorian Hahn #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
10bcbd26bfSFlorian Hahn #include "llvm/ADT/SmallVector.h"
11bcbd26bfSFlorian Hahn #include "llvm/Analysis/AssumptionCache.h"
12bcbd26bfSFlorian Hahn #include "llvm/Analysis/LoopInfo.h"
13bcbd26bfSFlorian Hahn #include "llvm/Analysis/ScalarEvolutionExpressions.h"
14bcbd26bfSFlorian Hahn #include "llvm/Analysis/TargetLibraryInfo.h"
15bcbd26bfSFlorian Hahn #include "llvm/AsmParser/Parser.h"
16bcbd26bfSFlorian Hahn #include "llvm/IR/Constants.h"
17bcbd26bfSFlorian Hahn #include "llvm/IR/Dominators.h"
18bcbd26bfSFlorian Hahn #include "llvm/IR/GlobalVariable.h"
19bcbd26bfSFlorian Hahn #include "llvm/IR/IRBuilder.h"
20bcbd26bfSFlorian Hahn #include "llvm/IR/InstIterator.h"
21bcbd26bfSFlorian Hahn #include "llvm/IR/LLVMContext.h"
22bcbd26bfSFlorian Hahn #include "llvm/IR/Module.h"
231d8f2e52SFlorian Hahn #include "llvm/IR/PatternMatch.h"
24bcbd26bfSFlorian Hahn #include "llvm/IR/Verifier.h"
25ba7a92c0SNico Weber #include "llvm/Support/SourceMgr.h"
26bcbd26bfSFlorian Hahn #include "gtest/gtest.h"
27bcbd26bfSFlorian Hahn 
28bcbd26bfSFlorian Hahn namespace llvm {
29bcbd26bfSFlorian Hahn 
301d8f2e52SFlorian Hahn using namespace PatternMatch;
311d8f2e52SFlorian Hahn 
32bcbd26bfSFlorian Hahn // We use this fixture to ensure that we clean up ScalarEvolution before
33bcbd26bfSFlorian Hahn // deleting the PassManager.
34bcbd26bfSFlorian Hahn class ScalarEvolutionExpanderTest : public testing::Test {
35bcbd26bfSFlorian Hahn protected:
36bcbd26bfSFlorian Hahn   LLVMContext Context;
37bcbd26bfSFlorian Hahn   Module M;
38bcbd26bfSFlorian Hahn   TargetLibraryInfoImpl TLII;
39bcbd26bfSFlorian Hahn   TargetLibraryInfo TLI;
40bcbd26bfSFlorian Hahn 
41bcbd26bfSFlorian Hahn   std::unique_ptr<AssumptionCache> AC;
42bcbd26bfSFlorian Hahn   std::unique_ptr<DominatorTree> DT;
43bcbd26bfSFlorian Hahn   std::unique_ptr<LoopInfo> LI;
44bcbd26bfSFlorian Hahn 
45bcbd26bfSFlorian Hahn   ScalarEvolutionExpanderTest() : M("", Context), TLII(), TLI(TLII) {}
46bcbd26bfSFlorian Hahn 
47bcbd26bfSFlorian Hahn   ScalarEvolution buildSE(Function &F) {
48bcbd26bfSFlorian Hahn     AC.reset(new AssumptionCache(F));
49bcbd26bfSFlorian Hahn     DT.reset(new DominatorTree(F));
50bcbd26bfSFlorian Hahn     LI.reset(new LoopInfo(*DT));
51bcbd26bfSFlorian Hahn     return ScalarEvolution(F, TLI, *AC, *DT, *LI);
52bcbd26bfSFlorian Hahn   }
53bcbd26bfSFlorian Hahn 
54bcbd26bfSFlorian Hahn   void runWithSE(
55bcbd26bfSFlorian Hahn       Module &M, StringRef FuncName,
56bcbd26bfSFlorian Hahn       function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE)> Test) {
57bcbd26bfSFlorian Hahn     auto *F = M.getFunction(FuncName);
58bcbd26bfSFlorian Hahn     ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
59bcbd26bfSFlorian Hahn     ScalarEvolution SE = buildSE(*F);
60bcbd26bfSFlorian Hahn     Test(*F, *LI, SE);
61bcbd26bfSFlorian Hahn   }
62bcbd26bfSFlorian Hahn };
63bcbd26bfSFlorian Hahn 
64bcbd26bfSFlorian Hahn static Instruction &GetInstByName(Function &F, StringRef Name) {
65bcbd26bfSFlorian Hahn   for (auto &I : instructions(F))
66bcbd26bfSFlorian Hahn     if (I.getName() == Name)
67bcbd26bfSFlorian Hahn       return I;
68bcbd26bfSFlorian Hahn   llvm_unreachable("Could not find instructions!");
69bcbd26bfSFlorian Hahn }
70bcbd26bfSFlorian Hahn 
71bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, ExpandPtrTypeSCEV) {
72bcbd26bfSFlorian Hahn   // It is to test the fix for PR30213. It exercises the branch in scev
73bcbd26bfSFlorian Hahn   // expansion when the value in ValueOffsetPair is a ptr and the offset
74bcbd26bfSFlorian Hahn   // is not divisible by the elem type size of value.
75bcbd26bfSFlorian Hahn   auto *I8Ty = Type::getInt8Ty(Context);
76145aff6dSBjorn Pettersson   auto *PtrTy = PointerType::get(Context, 0);
77bcbd26bfSFlorian Hahn   auto *I32Ty = Type::getInt32Ty(Context);
78bcbd26bfSFlorian Hahn   FunctionType *FTy =
79bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), std::vector<Type *>(), false);
80bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", M);
81bcbd26bfSFlorian Hahn   BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", F);
82bcbd26bfSFlorian Hahn   BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", F);
83bcbd26bfSFlorian Hahn   BasicBlock *ExitBB = BasicBlock::Create(Context, "exit", F);
84bcbd26bfSFlorian Hahn   BranchInst::Create(LoopBB, EntryBB);
85bcbd26bfSFlorian Hahn   ReturnInst::Create(Context, nullptr, ExitBB);
86bcbd26bfSFlorian Hahn 
87bcbd26bfSFlorian Hahn   // loop:                            ; preds = %loop, %entry
88bcbd26bfSFlorian Hahn   //   %alloca = alloca i32
89145aff6dSBjorn Pettersson   //   %gep0 = getelementptr i32, ptr %alloca, i32 1
90145aff6dSBjorn Pettersson   //   %gep1 = getelementptr i8, ptr %gep0, i32 1
91145aff6dSBjorn Pettersson   //   %gep2 = getelementptr i8, ptr undef, i32 1
92145aff6dSBjorn Pettersson   //   %cmp = icmp ult ptr undef, %gep0
93145aff6dSBjorn Pettersson   //   %select = select i1 %cmp, ptr %gep1, ptr %gep2
94bcbd26bfSFlorian Hahn   //   br i1 undef, label %loop, label %exit
95bcbd26bfSFlorian Hahn 
969df71d76SNikita Popov   const DataLayout &DL = F->getDataLayout();
97bcbd26bfSFlorian Hahn   BranchInst *Br = BranchInst::Create(
98*64b9753dSLee Wei       LoopBB, ExitBB, PoisonValue::get(Type::getInt1Ty(Context)), LoopBB);
992b1122eaSJeremy Morse   AllocaInst *Alloca = new AllocaInst(I32Ty, DL.getAllocaAddrSpace(), "alloca",
1002b1122eaSJeremy Morse                                       Br->getIterator());
101bcbd26bfSFlorian Hahn   ConstantInt *Ci32 = ConstantInt::get(Context, APInt(32, 1));
102145aff6dSBjorn Pettersson   UndefValue *UndefPtr = UndefValue::get(PtrTy);
103bcbd26bfSFlorian Hahn   GetElementPtrInst *Gep0 =
1042b1122eaSJeremy Morse       GetElementPtrInst::Create(I32Ty, Alloca, Ci32, "gep0", Br->getIterator());
105bcbd26bfSFlorian Hahn   GetElementPtrInst *Gep1 =
106145aff6dSBjorn Pettersson       GetElementPtrInst::Create(I8Ty, Gep0, Ci32, "gep1", Br->getIterator());
107bcbd26bfSFlorian Hahn   GetElementPtrInst *Gep2 = GetElementPtrInst::Create(
108145aff6dSBjorn Pettersson       I8Ty, UndefPtr, Ci32, "gep2", Br->getIterator());
109bcbd26bfSFlorian Hahn   CmpInst *Cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT,
110145aff6dSBjorn Pettersson                                  UndefPtr, Gep0, "cmp", Br->getIterator());
111145aff6dSBjorn Pettersson   SelectInst *Select =
1122b1122eaSJeremy Morse       SelectInst::Create(Cmp, Gep1, Gep2, "select", Br->getIterator());
113bcbd26bfSFlorian Hahn 
114bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
115145aff6dSBjorn Pettersson   const SCEV *S = SE.getSCEV(Select);
1168a567e5fSEli Friedman   EXPECT_TRUE(isa<SCEVUnknown>(S));
117bcbd26bfSFlorian Hahn }
118bcbd26bfSFlorian Hahn 
119bcbd26bfSFlorian Hahn // Make sure that SCEV doesn't introduce illegal ptrtoint/inttoptr instructions
120bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVZeroExtendExprNonIntegral) {
121bcbd26bfSFlorian Hahn   /*
122bcbd26bfSFlorian Hahn    * Create the following code:
123bcbd26bfSFlorian Hahn    * func(i64 addrspace(10)* %arg)
124bcbd26bfSFlorian Hahn    * top:
125bcbd26bfSFlorian Hahn    *  br label %L.ph
126bcbd26bfSFlorian Hahn    * L.ph:
1272d8d622cSNikita Popov    *  %gepbase = getelementptr i64 addrspace(10)* %arg, i64 1
128bcbd26bfSFlorian Hahn    *  br label %L
129bcbd26bfSFlorian Hahn    * L:
130bcbd26bfSFlorian Hahn    *  %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
131bcbd26bfSFlorian Hahn    *  %add = add i64 %phi2, 1
132bcbd26bfSFlorian Hahn    *  br i1 undef, label %post, label %L2
133bcbd26bfSFlorian Hahn    * post:
134bcbd26bfSFlorian Hahn    *  #= %gep = getelementptr i64 addrspace(10)* %gepbase, i64 %add =#
135bcbd26bfSFlorian Hahn    *  ret void
136bcbd26bfSFlorian Hahn    *
137bcbd26bfSFlorian Hahn    * We will create the appropriate SCEV expression for %gep and expand it,
138bcbd26bfSFlorian Hahn    * then check that no inttoptr/ptrtoint instructions got inserted.
139bcbd26bfSFlorian Hahn    */
140bcbd26bfSFlorian Hahn 
141bcbd26bfSFlorian Hahn   // Create a module with non-integral pointers in it's datalayout
142bcbd26bfSFlorian Hahn   Module NIM("nonintegral", Context);
143bcbd26bfSFlorian Hahn   std::string DataLayout = M.getDataLayoutStr();
144bcbd26bfSFlorian Hahn   if (!DataLayout.empty())
145bcbd26bfSFlorian Hahn     DataLayout += "-";
146bcbd26bfSFlorian Hahn   DataLayout += "ni:10";
147bcbd26bfSFlorian Hahn   NIM.setDataLayout(DataLayout);
148bcbd26bfSFlorian Hahn 
149bcbd26bfSFlorian Hahn   Type *T_int1 = Type::getInt1Ty(Context);
150bcbd26bfSFlorian Hahn   Type *T_int64 = Type::getInt64Ty(Context);
151e53b28c8SBjorn Pettersson   Type *T_pint64 = PointerType::get(Context, 10);
152bcbd26bfSFlorian Hahn 
153bcbd26bfSFlorian Hahn   FunctionType *FTy =
154bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
155bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", NIM);
156bcbd26bfSFlorian Hahn 
157bcbd26bfSFlorian Hahn   Argument *Arg = &*F->arg_begin();
158bcbd26bfSFlorian Hahn 
159bcbd26bfSFlorian Hahn   BasicBlock *Top = BasicBlock::Create(Context, "top", F);
160bcbd26bfSFlorian Hahn   BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
161bcbd26bfSFlorian Hahn   BasicBlock *L = BasicBlock::Create(Context, "L", F);
162bcbd26bfSFlorian Hahn   BasicBlock *Post = BasicBlock::Create(Context, "post", F);
163bcbd26bfSFlorian Hahn 
164bcbd26bfSFlorian Hahn   IRBuilder<> Builder(Top);
165bcbd26bfSFlorian Hahn   Builder.CreateBr(LPh);
166bcbd26bfSFlorian Hahn 
167bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(LPh);
1682d8d622cSNikita Popov   Value *GepBase =
1692d8d622cSNikita Popov       Builder.CreateGEP(T_int64, Arg, ConstantInt::get(T_int64, 1));
170bcbd26bfSFlorian Hahn   Builder.CreateBr(L);
171bcbd26bfSFlorian Hahn 
172bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(L);
173bcbd26bfSFlorian Hahn   PHINode *Phi = Builder.CreatePHI(T_int64, 2);
174bcbd26bfSFlorian Hahn   Value *Add = Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add");
175*64b9753dSLee Wei   Builder.CreateCondBr(PoisonValue::get(T_int1), L, Post);
176bcbd26bfSFlorian Hahn   Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
177bcbd26bfSFlorian Hahn   Phi->addIncoming(Add, L);
178bcbd26bfSFlorian Hahn 
179bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Post);
180bcbd26bfSFlorian Hahn   Instruction *Ret = Builder.CreateRetVoid();
181bcbd26bfSFlorian Hahn 
182bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
183edf46f36SFlorian Hahn   const SCEV *AddRec =
184bcbd26bfSFlorian Hahn       SE.getAddRecExpr(SE.getUnknown(GepBase), SE.getConstant(T_int64, 1),
185bcbd26bfSFlorian Hahn                        LI->getLoopFor(L), SCEV::FlagNUW);
186bcbd26bfSFlorian Hahn 
187bcbd26bfSFlorian Hahn   SCEVExpander Exp(SE, NIM.getDataLayout(), "expander");
188bcbd26bfSFlorian Hahn   Exp.disableCanonicalMode();
189bcbd26bfSFlorian Hahn   Exp.expandCodeFor(AddRec, T_pint64, Ret);
190bcbd26bfSFlorian Hahn 
191bcbd26bfSFlorian Hahn   // Make sure none of the instructions inserted were inttoptr/ptrtoint.
192bcbd26bfSFlorian Hahn   // The verifier will check this.
193bcbd26bfSFlorian Hahn   EXPECT_FALSE(verifyFunction(*F, &errs()));
194bcbd26bfSFlorian Hahn }
195bcbd26bfSFlorian Hahn 
196bcbd26bfSFlorian Hahn // Check that we can correctly identify the points at which the SCEV of the
197bcbd26bfSFlorian Hahn // AddRec can be expanded.
198bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVExpanderIsSafeToExpandAt) {
199bcbd26bfSFlorian Hahn   /*
200bcbd26bfSFlorian Hahn    * Create the following code:
201bcbd26bfSFlorian Hahn    * func(i64 addrspace(10)* %arg)
202bcbd26bfSFlorian Hahn    * top:
203bcbd26bfSFlorian Hahn    *  br label %L.ph
204bcbd26bfSFlorian Hahn    * L.ph:
205bcbd26bfSFlorian Hahn    *  br label %L
206bcbd26bfSFlorian Hahn    * L:
207bcbd26bfSFlorian Hahn    *  %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
208bcbd26bfSFlorian Hahn    *  %add = add i64 %phi2, 1
209bcbd26bfSFlorian Hahn    *  %cond = icmp slt i64 %add, 1000; then becomes 2000.
210bcbd26bfSFlorian Hahn    *  br i1 %cond, label %post, label %L2
211bcbd26bfSFlorian Hahn    * post:
212bcbd26bfSFlorian Hahn    *  ret void
213bcbd26bfSFlorian Hahn    *
214bcbd26bfSFlorian Hahn    */
215bcbd26bfSFlorian Hahn 
216bcbd26bfSFlorian Hahn   // Create a module with non-integral pointers in it's datalayout
217bcbd26bfSFlorian Hahn   Module NIM("nonintegral", Context);
218bcbd26bfSFlorian Hahn   std::string DataLayout = M.getDataLayoutStr();
219bcbd26bfSFlorian Hahn   if (!DataLayout.empty())
220bcbd26bfSFlorian Hahn     DataLayout += "-";
221bcbd26bfSFlorian Hahn   DataLayout += "ni:10";
222bcbd26bfSFlorian Hahn   NIM.setDataLayout(DataLayout);
223bcbd26bfSFlorian Hahn 
224bcbd26bfSFlorian Hahn   Type *T_int64 = Type::getInt64Ty(Context);
225e53b28c8SBjorn Pettersson   Type *T_pint64 = PointerType::get(Context, 10);
226bcbd26bfSFlorian Hahn 
227bcbd26bfSFlorian Hahn   FunctionType *FTy =
228bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
229bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", NIM);
230bcbd26bfSFlorian Hahn 
231bcbd26bfSFlorian Hahn   BasicBlock *Top = BasicBlock::Create(Context, "top", F);
232bcbd26bfSFlorian Hahn   BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
233bcbd26bfSFlorian Hahn   BasicBlock *L = BasicBlock::Create(Context, "L", F);
234bcbd26bfSFlorian Hahn   BasicBlock *Post = BasicBlock::Create(Context, "post", F);
235bcbd26bfSFlorian Hahn 
236bcbd26bfSFlorian Hahn   IRBuilder<> Builder(Top);
237bcbd26bfSFlorian Hahn   Builder.CreateBr(LPh);
238bcbd26bfSFlorian Hahn 
239bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(LPh);
240bcbd26bfSFlorian Hahn   Builder.CreateBr(L);
241bcbd26bfSFlorian Hahn 
242bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(L);
243bcbd26bfSFlorian Hahn   PHINode *Phi = Builder.CreatePHI(T_int64, 2);
244bcbd26bfSFlorian Hahn   auto *Add = cast<Instruction>(
245bcbd26bfSFlorian Hahn       Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));
246bcbd26bfSFlorian Hahn   auto *Limit = ConstantInt::get(T_int64, 1000);
247bcbd26bfSFlorian Hahn   auto *Cond = cast<Instruction>(
248bcbd26bfSFlorian Hahn       Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Limit, "cond"));
249bcbd26bfSFlorian Hahn   Builder.CreateCondBr(Cond, L, Post);
250bcbd26bfSFlorian Hahn   Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
251bcbd26bfSFlorian Hahn   Phi->addIncoming(Add, L);
252bcbd26bfSFlorian Hahn 
253bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Post);
254f75564adSFlorian Hahn   Instruction *Ret = Builder.CreateRetVoid();
255bcbd26bfSFlorian Hahn 
256bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
257dcf4b733SNikita Popov   SCEVExpander Exp(SE, M.getDataLayout(), "expander");
258bcbd26bfSFlorian Hahn   const SCEV *S = SE.getSCEV(Phi);
259bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddRecExpr>(S));
260bcbd26bfSFlorian Hahn   const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
261bcbd26bfSFlorian Hahn   EXPECT_TRUE(AR->isAffine());
262dcf4b733SNikita Popov   EXPECT_FALSE(Exp.isSafeToExpandAt(AR, Top->getTerminator()));
263dcf4b733SNikita Popov   EXPECT_FALSE(Exp.isSafeToExpandAt(AR, LPh->getTerminator()));
264dcf4b733SNikita Popov   EXPECT_TRUE(Exp.isSafeToExpandAt(AR, L->getTerminator()));
265dcf4b733SNikita Popov   EXPECT_TRUE(Exp.isSafeToExpandAt(AR, Post->getTerminator()));
266f75564adSFlorian Hahn 
267f75564adSFlorian Hahn   EXPECT_TRUE(LI->getLoopFor(L)->isLCSSAForm(*DT));
268f75564adSFlorian Hahn   Exp.expandCodeFor(SE.getSCEV(Add), nullptr, Ret);
269f75564adSFlorian Hahn   EXPECT_TRUE(LI->getLoopFor(L)->isLCSSAForm(*DT));
270bcbd26bfSFlorian Hahn }
271bcbd26bfSFlorian Hahn 
272bcbd26bfSFlorian Hahn // Check that SCEV expander does not use the nuw instruction
273bcbd26bfSFlorian Hahn // for expansion.
274bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVExpanderNUW) {
275bcbd26bfSFlorian Hahn   /*
276bcbd26bfSFlorian Hahn    * Create the following code:
277bcbd26bfSFlorian Hahn    * func(i64 %a)
278bcbd26bfSFlorian Hahn    * entry:
279bcbd26bfSFlorian Hahn    *   br false, label %exit, label %body
280bcbd26bfSFlorian Hahn    * body:
281bcbd26bfSFlorian Hahn    *  %s1 = add i64 %a, -1
282bcbd26bfSFlorian Hahn    *  br label %exit
283bcbd26bfSFlorian Hahn    * exit:
284bcbd26bfSFlorian Hahn    *  %s = add nuw i64 %a, -1
285bcbd26bfSFlorian Hahn    *  ret %s
286bcbd26bfSFlorian Hahn    */
287bcbd26bfSFlorian Hahn 
288bcbd26bfSFlorian Hahn   // Create a module.
289bcbd26bfSFlorian Hahn   Module M("SCEVExpanderNUW", Context);
290bcbd26bfSFlorian Hahn 
291bcbd26bfSFlorian Hahn   Type *T_int64 = Type::getInt64Ty(Context);
292bcbd26bfSFlorian Hahn 
293bcbd26bfSFlorian Hahn   FunctionType *FTy =
294bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), {T_int64}, false);
295bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "func", M);
296bcbd26bfSFlorian Hahn   Argument *Arg = &*F->arg_begin();
297bcbd26bfSFlorian Hahn   ConstantInt *C = ConstantInt::get(Context, APInt(64, -1));
298bcbd26bfSFlorian Hahn 
299bcbd26bfSFlorian Hahn   BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
300bcbd26bfSFlorian Hahn   BasicBlock *Body = BasicBlock::Create(Context, "body", F);
301bcbd26bfSFlorian Hahn   BasicBlock *Exit = BasicBlock::Create(Context, "exit", F);
302bcbd26bfSFlorian Hahn 
303bcbd26bfSFlorian Hahn   IRBuilder<> Builder(Entry);
304bcbd26bfSFlorian Hahn   ConstantInt *Cond = ConstantInt::get(Context, APInt(1, 0));
305bcbd26bfSFlorian Hahn   Builder.CreateCondBr(Cond, Exit, Body);
306bcbd26bfSFlorian Hahn 
307bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Body);
308bcbd26bfSFlorian Hahn   auto *S1 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
309bcbd26bfSFlorian Hahn   Builder.CreateBr(Exit);
310bcbd26bfSFlorian Hahn 
311bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Exit);
312bcbd26bfSFlorian Hahn   auto *S2 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
313bcbd26bfSFlorian Hahn   S2->setHasNoUnsignedWrap(true);
314bcbd26bfSFlorian Hahn   auto *R = cast<Instruction>(Builder.CreateRetVoid());
315bcbd26bfSFlorian Hahn 
316bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
317bcbd26bfSFlorian Hahn   const SCEV *S = SE.getSCEV(S1);
318bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddExpr>(S));
319bcbd26bfSFlorian Hahn   SCEVExpander Exp(SE, M.getDataLayout(), "expander");
320bcbd26bfSFlorian Hahn   auto *I = cast<Instruction>(Exp.expandCodeFor(S, nullptr, R));
321bcbd26bfSFlorian Hahn   EXPECT_FALSE(I->hasNoUnsignedWrap());
322bcbd26bfSFlorian Hahn }
323bcbd26bfSFlorian Hahn 
324bcbd26bfSFlorian Hahn // Check that SCEV expander does not use the nsw instruction
325bcbd26bfSFlorian Hahn // for expansion.
326bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVExpanderNSW) {
327bcbd26bfSFlorian Hahn   /*
328bcbd26bfSFlorian Hahn    * Create the following code:
329bcbd26bfSFlorian Hahn    * func(i64 %a)
330bcbd26bfSFlorian Hahn    * entry:
331bcbd26bfSFlorian Hahn    *   br false, label %exit, label %body
332bcbd26bfSFlorian Hahn    * body:
333bcbd26bfSFlorian Hahn    *  %s1 = add i64 %a, -1
334bcbd26bfSFlorian Hahn    *  br label %exit
335bcbd26bfSFlorian Hahn    * exit:
336bcbd26bfSFlorian Hahn    *  %s = add nsw i64 %a, -1
337bcbd26bfSFlorian Hahn    *  ret %s
338bcbd26bfSFlorian Hahn    */
339bcbd26bfSFlorian Hahn 
340bcbd26bfSFlorian Hahn   // Create a module.
341bcbd26bfSFlorian Hahn   Module M("SCEVExpanderNSW", Context);
342bcbd26bfSFlorian Hahn 
343bcbd26bfSFlorian Hahn   Type *T_int64 = Type::getInt64Ty(Context);
344bcbd26bfSFlorian Hahn 
345bcbd26bfSFlorian Hahn   FunctionType *FTy =
346bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), {T_int64}, false);
347bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "func", M);
348bcbd26bfSFlorian Hahn   Argument *Arg = &*F->arg_begin();
349bcbd26bfSFlorian Hahn   ConstantInt *C = ConstantInt::get(Context, APInt(64, -1));
350bcbd26bfSFlorian Hahn 
351bcbd26bfSFlorian Hahn   BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
352bcbd26bfSFlorian Hahn   BasicBlock *Body = BasicBlock::Create(Context, "body", F);
353bcbd26bfSFlorian Hahn   BasicBlock *Exit = BasicBlock::Create(Context, "exit", F);
354bcbd26bfSFlorian Hahn 
355bcbd26bfSFlorian Hahn   IRBuilder<> Builder(Entry);
356bcbd26bfSFlorian Hahn   ConstantInt *Cond = ConstantInt::get(Context, APInt(1, 0));
357bcbd26bfSFlorian Hahn   Builder.CreateCondBr(Cond, Exit, Body);
358bcbd26bfSFlorian Hahn 
359bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Body);
360bcbd26bfSFlorian Hahn   auto *S1 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
361bcbd26bfSFlorian Hahn   Builder.CreateBr(Exit);
362bcbd26bfSFlorian Hahn 
363bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Exit);
364bcbd26bfSFlorian Hahn   auto *S2 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
365bcbd26bfSFlorian Hahn   S2->setHasNoSignedWrap(true);
366bcbd26bfSFlorian Hahn   auto *R = cast<Instruction>(Builder.CreateRetVoid());
367bcbd26bfSFlorian Hahn 
368bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
369bcbd26bfSFlorian Hahn   const SCEV *S = SE.getSCEV(S1);
370bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddExpr>(S));
371bcbd26bfSFlorian Hahn   SCEVExpander Exp(SE, M.getDataLayout(), "expander");
372bcbd26bfSFlorian Hahn   auto *I = cast<Instruction>(Exp.expandCodeFor(S, nullptr, R));
373bcbd26bfSFlorian Hahn   EXPECT_FALSE(I->hasNoSignedWrap());
374bcbd26bfSFlorian Hahn }
375bcbd26bfSFlorian Hahn 
376bcbd26bfSFlorian Hahn // Check that SCEV does not save the SCEV -> V
377bcbd26bfSFlorian Hahn // mapping of SCEV differ from V in NUW flag.
378bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVCacheNUW) {
379bcbd26bfSFlorian Hahn   /*
380bcbd26bfSFlorian Hahn    * Create the following code:
381bcbd26bfSFlorian Hahn    * func(i64 %a)
382bcbd26bfSFlorian Hahn    * entry:
383bcbd26bfSFlorian Hahn    *  %s1 = add i64 %a, -1
384bcbd26bfSFlorian Hahn    *  %s2 = add nuw i64 %a, -1
385bcbd26bfSFlorian Hahn    *  br label %exit
386bcbd26bfSFlorian Hahn    * exit:
387bcbd26bfSFlorian Hahn    *  ret %s
388bcbd26bfSFlorian Hahn    */
389bcbd26bfSFlorian Hahn 
390bcbd26bfSFlorian Hahn   // Create a module.
391bcbd26bfSFlorian Hahn   Module M("SCEVCacheNUW", Context);
392bcbd26bfSFlorian Hahn 
393bcbd26bfSFlorian Hahn   Type *T_int64 = Type::getInt64Ty(Context);
394bcbd26bfSFlorian Hahn 
395bcbd26bfSFlorian Hahn   FunctionType *FTy =
396bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), {T_int64}, false);
397bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "func", M);
398bcbd26bfSFlorian Hahn   Argument *Arg = &*F->arg_begin();
399bcbd26bfSFlorian Hahn   ConstantInt *C = ConstantInt::get(Context, APInt(64, -1));
400bcbd26bfSFlorian Hahn 
401bcbd26bfSFlorian Hahn   BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
402bcbd26bfSFlorian Hahn   BasicBlock *Exit = BasicBlock::Create(Context, "exit", F);
403bcbd26bfSFlorian Hahn 
404bcbd26bfSFlorian Hahn   IRBuilder<> Builder(Entry);
405bcbd26bfSFlorian Hahn   auto *S1 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
406bcbd26bfSFlorian Hahn   auto *S2 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
407bcbd26bfSFlorian Hahn   S2->setHasNoUnsignedWrap(true);
408bcbd26bfSFlorian Hahn   Builder.CreateBr(Exit);
409bcbd26bfSFlorian Hahn 
410bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Exit);
411bcbd26bfSFlorian Hahn   auto *R = cast<Instruction>(Builder.CreateRetVoid());
412bcbd26bfSFlorian Hahn 
413bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
414bcbd26bfSFlorian Hahn   // Get S2 first to move it to cache.
415bcbd26bfSFlorian Hahn   const SCEV *SC2 = SE.getSCEV(S2);
416bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddExpr>(SC2));
417bcbd26bfSFlorian Hahn   // Now get S1.
418bcbd26bfSFlorian Hahn   const SCEV *SC1 = SE.getSCEV(S1);
419bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddExpr>(SC1));
420bcbd26bfSFlorian Hahn   // Expand for S1, it should use S1 not S2 in spite S2
421bcbd26bfSFlorian Hahn   // first in the cache.
422bcbd26bfSFlorian Hahn   SCEVExpander Exp(SE, M.getDataLayout(), "expander");
423bcbd26bfSFlorian Hahn   auto *I = cast<Instruction>(Exp.expandCodeFor(SC1, nullptr, R));
424bcbd26bfSFlorian Hahn   EXPECT_FALSE(I->hasNoUnsignedWrap());
425bcbd26bfSFlorian Hahn }
426bcbd26bfSFlorian Hahn 
427bcbd26bfSFlorian Hahn // Check that SCEV does not save the SCEV -> V
428bcbd26bfSFlorian Hahn // mapping of SCEV differ from V in NSW flag.
429bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVCacheNSW) {
430bcbd26bfSFlorian Hahn   /*
431bcbd26bfSFlorian Hahn    * Create the following code:
432bcbd26bfSFlorian Hahn    * func(i64 %a)
433bcbd26bfSFlorian Hahn    * entry:
434bcbd26bfSFlorian Hahn    *  %s1 = add i64 %a, -1
435bcbd26bfSFlorian Hahn    *  %s2 = add nsw i64 %a, -1
436bcbd26bfSFlorian Hahn    *  br label %exit
437bcbd26bfSFlorian Hahn    * exit:
438bcbd26bfSFlorian Hahn    *  ret %s
439bcbd26bfSFlorian Hahn    */
440bcbd26bfSFlorian Hahn 
441bcbd26bfSFlorian Hahn   // Create a module.
442bcbd26bfSFlorian Hahn   Module M("SCEVCacheNUW", Context);
443bcbd26bfSFlorian Hahn 
444bcbd26bfSFlorian Hahn   Type *T_int64 = Type::getInt64Ty(Context);
445bcbd26bfSFlorian Hahn 
446bcbd26bfSFlorian Hahn   FunctionType *FTy =
447bcbd26bfSFlorian Hahn       FunctionType::get(Type::getVoidTy(Context), {T_int64}, false);
448bcbd26bfSFlorian Hahn   Function *F = Function::Create(FTy, Function::ExternalLinkage, "func", M);
449bcbd26bfSFlorian Hahn   Argument *Arg = &*F->arg_begin();
450bcbd26bfSFlorian Hahn   ConstantInt *C = ConstantInt::get(Context, APInt(64, -1));
451bcbd26bfSFlorian Hahn 
452bcbd26bfSFlorian Hahn   BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
453bcbd26bfSFlorian Hahn   BasicBlock *Exit = BasicBlock::Create(Context, "exit", F);
454bcbd26bfSFlorian Hahn 
455bcbd26bfSFlorian Hahn   IRBuilder<> Builder(Entry);
456bcbd26bfSFlorian Hahn   auto *S1 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
457bcbd26bfSFlorian Hahn   auto *S2 = cast<Instruction>(Builder.CreateAdd(Arg, C, "add"));
458bcbd26bfSFlorian Hahn   S2->setHasNoSignedWrap(true);
459bcbd26bfSFlorian Hahn   Builder.CreateBr(Exit);
460bcbd26bfSFlorian Hahn 
461bcbd26bfSFlorian Hahn   Builder.SetInsertPoint(Exit);
462bcbd26bfSFlorian Hahn   auto *R = cast<Instruction>(Builder.CreateRetVoid());
463bcbd26bfSFlorian Hahn 
464bcbd26bfSFlorian Hahn   ScalarEvolution SE = buildSE(*F);
465bcbd26bfSFlorian Hahn   // Get S2 first to move it to cache.
466bcbd26bfSFlorian Hahn   const SCEV *SC2 = SE.getSCEV(S2);
467bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddExpr>(SC2));
468bcbd26bfSFlorian Hahn   // Now get S1.
469bcbd26bfSFlorian Hahn   const SCEV *SC1 = SE.getSCEV(S1);
470bcbd26bfSFlorian Hahn   EXPECT_TRUE(isa<SCEVAddExpr>(SC1));
471bcbd26bfSFlorian Hahn   // Expand for S1, it should use S1 not S2 in spite S2
472bcbd26bfSFlorian Hahn   // first in the cache.
473bcbd26bfSFlorian Hahn   SCEVExpander Exp(SE, M.getDataLayout(), "expander");
474bcbd26bfSFlorian Hahn   auto *I = cast<Instruction>(Exp.expandCodeFor(SC1, nullptr, R));
475bcbd26bfSFlorian Hahn   EXPECT_FALSE(I->hasNoSignedWrap());
476bcbd26bfSFlorian Hahn }
477bcbd26bfSFlorian Hahn 
478bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVExpandInsertCanonicalIV) {
479bcbd26bfSFlorian Hahn   LLVMContext C;
480bcbd26bfSFlorian Hahn   SMDiagnostic Err;
481bcbd26bfSFlorian Hahn 
482bcbd26bfSFlorian Hahn   // Expand the addrec produced by GetAddRec into a loop without a canonical IV.
483bcbd26bfSFlorian Hahn   // SCEVExpander will insert one.
484bcbd26bfSFlorian Hahn   auto TestNoCanonicalIV =
485bcbd26bfSFlorian Hahn       [&](std::function<const SCEV *(ScalarEvolution & SE, Loop * L)>
486bcbd26bfSFlorian Hahn               GetAddRec) {
487bcbd26bfSFlorian Hahn         std::unique_ptr<Module> M = parseAssemblyString(
488bcbd26bfSFlorian Hahn             "define i32 @test(i32 %limit) { "
489bcbd26bfSFlorian Hahn             "entry: "
490bcbd26bfSFlorian Hahn             "  br label %loop "
491bcbd26bfSFlorian Hahn             "loop: "
492bcbd26bfSFlorian Hahn             "  %i = phi i32 [ 1, %entry ], [ %i.inc, %loop ] "
493bcbd26bfSFlorian Hahn             "  %i.inc = add nsw i32 %i, 1 "
494bcbd26bfSFlorian Hahn             "  %cont = icmp slt i32 %i.inc, %limit "
495bcbd26bfSFlorian Hahn             "  br i1 %cont, label %loop, label %exit "
496bcbd26bfSFlorian Hahn             "exit: "
497bcbd26bfSFlorian Hahn             "  ret i32 %i.inc "
498bcbd26bfSFlorian Hahn             "}",
499bcbd26bfSFlorian Hahn             Err, C);
500bcbd26bfSFlorian Hahn 
501bcbd26bfSFlorian Hahn         assert(M && "Could not parse module?");
502bcbd26bfSFlorian Hahn         assert(!verifyModule(*M) && "Must have been well formed!");
503bcbd26bfSFlorian Hahn 
504bcbd26bfSFlorian Hahn         runWithSE(
505bcbd26bfSFlorian Hahn             *M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
506bcbd26bfSFlorian Hahn               auto &I = GetInstByName(F, "i");
507bcbd26bfSFlorian Hahn               auto *Loop = LI.getLoopFor(I.getParent());
508bcbd26bfSFlorian Hahn               EXPECT_FALSE(Loop->getCanonicalInductionVariable());
509bcbd26bfSFlorian Hahn 
510bcbd26bfSFlorian Hahn               auto *AR = GetAddRec(SE, Loop);
511bcbd26bfSFlorian Hahn               unsigned ExpectedCanonicalIVWidth =
512bcbd26bfSFlorian Hahn                   SE.getTypeSizeInBits(AR->getType());
513bcbd26bfSFlorian Hahn 
514bcbd26bfSFlorian Hahn               SCEVExpander Exp(SE, M->getDataLayout(), "expander");
515bcbd26bfSFlorian Hahn               auto *InsertAt = I.getNextNode();
516bcbd26bfSFlorian Hahn               Exp.expandCodeFor(AR, nullptr, InsertAt);
517bcbd26bfSFlorian Hahn               PHINode *CanonicalIV = Loop->getCanonicalInductionVariable();
518bcbd26bfSFlorian Hahn               unsigned CanonicalIVBitWidth =
519bcbd26bfSFlorian Hahn                   cast<IntegerType>(CanonicalIV->getType())->getBitWidth();
520bcbd26bfSFlorian Hahn               EXPECT_EQ(CanonicalIVBitWidth, ExpectedCanonicalIVWidth);
521bcbd26bfSFlorian Hahn             });
522bcbd26bfSFlorian Hahn       };
523bcbd26bfSFlorian Hahn 
524bcbd26bfSFlorian Hahn   // Expand the addrec produced by GetAddRec into a loop with a canonical IV
525bcbd26bfSFlorian Hahn   // which is narrower than addrec type.
526bcbd26bfSFlorian Hahn   // SCEVExpander will insert a canonical IV of a wider type to expand the
527bcbd26bfSFlorian Hahn   // addrec.
528bcbd26bfSFlorian Hahn   auto TestNarrowCanonicalIV = [&](std::function<const SCEV *(
529bcbd26bfSFlorian Hahn                                        ScalarEvolution & SE, Loop * L)>
530bcbd26bfSFlorian Hahn                                        GetAddRec) {
531bcbd26bfSFlorian Hahn     std::unique_ptr<Module> M = parseAssemblyString(
532bcbd26bfSFlorian Hahn         "define i32 @test(i32 %limit) { "
533bcbd26bfSFlorian Hahn         "entry: "
534bcbd26bfSFlorian Hahn         "  br label %loop "
535bcbd26bfSFlorian Hahn         "loop: "
536bcbd26bfSFlorian Hahn         "  %i = phi i32 [ 1, %entry ], [ %i.inc, %loop ] "
537bcbd26bfSFlorian Hahn         "  %canonical.iv = phi i8 [ 0, %entry ], [ %canonical.iv.inc, %loop ] "
538bcbd26bfSFlorian Hahn         "  %i.inc = add nsw i32 %i, 1 "
539bcbd26bfSFlorian Hahn         "  %canonical.iv.inc = add i8 %canonical.iv, 1 "
540bcbd26bfSFlorian Hahn         "  %cont = icmp slt i32 %i.inc, %limit "
541bcbd26bfSFlorian Hahn         "  br i1 %cont, label %loop, label %exit "
542bcbd26bfSFlorian Hahn         "exit: "
543bcbd26bfSFlorian Hahn         "  ret i32 %i.inc "
544bcbd26bfSFlorian Hahn         "}",
545bcbd26bfSFlorian Hahn         Err, C);
546bcbd26bfSFlorian Hahn 
547bcbd26bfSFlorian Hahn     assert(M && "Could not parse module?");
548bcbd26bfSFlorian Hahn     assert(!verifyModule(*M) && "Must have been well formed!");
549bcbd26bfSFlorian Hahn 
550bcbd26bfSFlorian Hahn     runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
551bcbd26bfSFlorian Hahn       auto &I = GetInstByName(F, "i");
552bcbd26bfSFlorian Hahn 
553bcbd26bfSFlorian Hahn       auto *LoopHeaderBB = I.getParent();
554bcbd26bfSFlorian Hahn       auto *Loop = LI.getLoopFor(LoopHeaderBB);
555bcbd26bfSFlorian Hahn       PHINode *CanonicalIV = Loop->getCanonicalInductionVariable();
556bcbd26bfSFlorian Hahn       EXPECT_EQ(CanonicalIV, &GetInstByName(F, "canonical.iv"));
557bcbd26bfSFlorian Hahn 
558bcbd26bfSFlorian Hahn       auto *AR = GetAddRec(SE, Loop);
559bcbd26bfSFlorian Hahn 
560bcbd26bfSFlorian Hahn       unsigned ExpectedCanonicalIVWidth = SE.getTypeSizeInBits(AR->getType());
561bcbd26bfSFlorian Hahn       unsigned CanonicalIVBitWidth =
562bcbd26bfSFlorian Hahn           cast<IntegerType>(CanonicalIV->getType())->getBitWidth();
563bcbd26bfSFlorian Hahn       EXPECT_LT(CanonicalIVBitWidth, ExpectedCanonicalIVWidth);
564bcbd26bfSFlorian Hahn 
565bcbd26bfSFlorian Hahn       SCEVExpander Exp(SE, M->getDataLayout(), "expander");
566bcbd26bfSFlorian Hahn       auto *InsertAt = I.getNextNode();
567bcbd26bfSFlorian Hahn       Exp.expandCodeFor(AR, nullptr, InsertAt);
568bcbd26bfSFlorian Hahn 
569bcbd26bfSFlorian Hahn       // Loop over all of the PHI nodes, looking for the new canonical indvar.
570bcbd26bfSFlorian Hahn       PHINode *NewCanonicalIV = nullptr;
571bcbd26bfSFlorian Hahn       for (BasicBlock::iterator i = LoopHeaderBB->begin(); isa<PHINode>(i);
572bcbd26bfSFlorian Hahn            ++i) {
573bcbd26bfSFlorian Hahn         PHINode *PN = cast<PHINode>(i);
574bcbd26bfSFlorian Hahn         if (PN == &I || PN == CanonicalIV)
575bcbd26bfSFlorian Hahn           continue;
576bcbd26bfSFlorian Hahn         // We expect that the only PHI added is the new canonical IV
577bcbd26bfSFlorian Hahn         EXPECT_FALSE(NewCanonicalIV);
578bcbd26bfSFlorian Hahn         NewCanonicalIV = PN;
579bcbd26bfSFlorian Hahn       }
580bcbd26bfSFlorian Hahn 
581bcbd26bfSFlorian Hahn       // Check that NewCanonicalIV is a canonical IV, i.e {0,+,1}
582bcbd26bfSFlorian Hahn       BasicBlock *Incoming = nullptr, *Backedge = nullptr;
583bcbd26bfSFlorian Hahn       EXPECT_TRUE(Loop->getIncomingAndBackEdge(Incoming, Backedge));
584bcbd26bfSFlorian Hahn       auto *Start = NewCanonicalIV->getIncomingValueForBlock(Incoming);
585bcbd26bfSFlorian Hahn       EXPECT_TRUE(isa<ConstantInt>(Start));
586bcbd26bfSFlorian Hahn       EXPECT_TRUE(dyn_cast<ConstantInt>(Start)->isZero());
587bcbd26bfSFlorian Hahn       auto *Next = NewCanonicalIV->getIncomingValueForBlock(Backedge);
588bcbd26bfSFlorian Hahn       EXPECT_TRUE(isa<BinaryOperator>(Next));
589bcbd26bfSFlorian Hahn       auto *NextBinOp = dyn_cast<BinaryOperator>(Next);
590bcbd26bfSFlorian Hahn       EXPECT_EQ(NextBinOp->getOpcode(), Instruction::Add);
591bcbd26bfSFlorian Hahn       EXPECT_EQ(NextBinOp->getOperand(0), NewCanonicalIV);
592bcbd26bfSFlorian Hahn       auto *Step = NextBinOp->getOperand(1);
593bcbd26bfSFlorian Hahn       EXPECT_TRUE(isa<ConstantInt>(Step));
594bcbd26bfSFlorian Hahn       EXPECT_TRUE(dyn_cast<ConstantInt>(Step)->isOne());
595bcbd26bfSFlorian Hahn 
596bcbd26bfSFlorian Hahn       unsigned NewCanonicalIVBitWidth =
597bcbd26bfSFlorian Hahn           cast<IntegerType>(NewCanonicalIV->getType())->getBitWidth();
598bcbd26bfSFlorian Hahn       EXPECT_EQ(NewCanonicalIVBitWidth, ExpectedCanonicalIVWidth);
599bcbd26bfSFlorian Hahn     });
600bcbd26bfSFlorian Hahn   };
601bcbd26bfSFlorian Hahn 
602bcbd26bfSFlorian Hahn   // Expand the addrec produced by GetAddRec into a loop with a canonical IV
603bcbd26bfSFlorian Hahn   // of addrec width.
604bcbd26bfSFlorian Hahn   // To expand the addrec SCEVExpander should use the existing canonical IV.
605bcbd26bfSFlorian Hahn   auto TestMatchingCanonicalIV =
606bcbd26bfSFlorian Hahn       [&](std::function<const SCEV *(ScalarEvolution & SE, Loop * L)> GetAddRec,
607bcbd26bfSFlorian Hahn           unsigned ARBitWidth) {
608bcbd26bfSFlorian Hahn         auto ARBitWidthTypeStr = "i" + std::to_string(ARBitWidth);
609bcbd26bfSFlorian Hahn         std::unique_ptr<Module> M = parseAssemblyString(
610bcbd26bfSFlorian Hahn             "define i32 @test(i32 %limit) { "
611bcbd26bfSFlorian Hahn             "entry: "
612bcbd26bfSFlorian Hahn             "  br label %loop "
613bcbd26bfSFlorian Hahn             "loop: "
614bcbd26bfSFlorian Hahn             "  %i = phi i32 [ 1, %entry ], [ %i.inc, %loop ] "
615bcbd26bfSFlorian Hahn             "  %canonical.iv = phi " +
616bcbd26bfSFlorian Hahn                 ARBitWidthTypeStr +
617bcbd26bfSFlorian Hahn                 " [ 0, %entry ], [ %canonical.iv.inc, %loop ] "
618bcbd26bfSFlorian Hahn                 "  %i.inc = add nsw i32 %i, 1 "
619bcbd26bfSFlorian Hahn                 "  %canonical.iv.inc = add " +
620bcbd26bfSFlorian Hahn                 ARBitWidthTypeStr +
621bcbd26bfSFlorian Hahn                 " %canonical.iv, 1 "
622bcbd26bfSFlorian Hahn                 "  %cont = icmp slt i32 %i.inc, %limit "
623bcbd26bfSFlorian Hahn                 "  br i1 %cont, label %loop, label %exit "
624bcbd26bfSFlorian Hahn                 "exit: "
625bcbd26bfSFlorian Hahn                 "  ret i32 %i.inc "
626bcbd26bfSFlorian Hahn                 "}",
627bcbd26bfSFlorian Hahn             Err, C);
628bcbd26bfSFlorian Hahn 
629bcbd26bfSFlorian Hahn         assert(M && "Could not parse module?");
630bcbd26bfSFlorian Hahn         assert(!verifyModule(*M) && "Must have been well formed!");
631bcbd26bfSFlorian Hahn 
632bcbd26bfSFlorian Hahn         runWithSE(
633bcbd26bfSFlorian Hahn             *M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
634bcbd26bfSFlorian Hahn               auto &I = GetInstByName(F, "i");
635bcbd26bfSFlorian Hahn               auto &CanonicalIV = GetInstByName(F, "canonical.iv");
636bcbd26bfSFlorian Hahn 
637bcbd26bfSFlorian Hahn               auto *LoopHeaderBB = I.getParent();
638bcbd26bfSFlorian Hahn               auto *Loop = LI.getLoopFor(LoopHeaderBB);
639bcbd26bfSFlorian Hahn               EXPECT_EQ(&CanonicalIV, Loop->getCanonicalInductionVariable());
640bcbd26bfSFlorian Hahn               unsigned CanonicalIVBitWidth =
641bcbd26bfSFlorian Hahn                   cast<IntegerType>(CanonicalIV.getType())->getBitWidth();
642bcbd26bfSFlorian Hahn 
643bcbd26bfSFlorian Hahn               auto *AR = GetAddRec(SE, Loop);
644bcbd26bfSFlorian Hahn               EXPECT_EQ(ARBitWidth, SE.getTypeSizeInBits(AR->getType()));
645bcbd26bfSFlorian Hahn               EXPECT_EQ(CanonicalIVBitWidth, ARBitWidth);
646bcbd26bfSFlorian Hahn 
647bcbd26bfSFlorian Hahn               SCEVExpander Exp(SE, M->getDataLayout(), "expander");
648bcbd26bfSFlorian Hahn               auto *InsertAt = I.getNextNode();
649bcbd26bfSFlorian Hahn               Exp.expandCodeFor(AR, nullptr, InsertAt);
650bcbd26bfSFlorian Hahn 
651bcbd26bfSFlorian Hahn               // Loop over all of the PHI nodes, looking if a new canonical
652bcbd26bfSFlorian Hahn               // indvar was introduced.
653bcbd26bfSFlorian Hahn               PHINode *NewCanonicalIV = nullptr;
654bcbd26bfSFlorian Hahn               for (BasicBlock::iterator i = LoopHeaderBB->begin();
655bcbd26bfSFlorian Hahn                    isa<PHINode>(i); ++i) {
656bcbd26bfSFlorian Hahn                 PHINode *PN = cast<PHINode>(i);
657bcbd26bfSFlorian Hahn                 if (PN == &I || PN == &CanonicalIV)
658bcbd26bfSFlorian Hahn                   continue;
659bcbd26bfSFlorian Hahn                 NewCanonicalIV = PN;
660bcbd26bfSFlorian Hahn               }
661bcbd26bfSFlorian Hahn               EXPECT_FALSE(NewCanonicalIV);
662bcbd26bfSFlorian Hahn             });
663bcbd26bfSFlorian Hahn       };
664bcbd26bfSFlorian Hahn 
665bcbd26bfSFlorian Hahn   unsigned ARBitWidth = 16;
666bcbd26bfSFlorian Hahn   Type *ARType = IntegerType::get(C, ARBitWidth);
667bcbd26bfSFlorian Hahn 
668bcbd26bfSFlorian Hahn   // Expand {5,+,1}
669bcbd26bfSFlorian Hahn   auto GetAR2 = [&](ScalarEvolution &SE, Loop *L) -> const SCEV * {
670bcbd26bfSFlorian Hahn     return SE.getAddRecExpr(SE.getConstant(APInt(ARBitWidth, 5)),
671bcbd26bfSFlorian Hahn                             SE.getOne(ARType), L, SCEV::FlagAnyWrap);
672bcbd26bfSFlorian Hahn   };
673bcbd26bfSFlorian Hahn   TestNoCanonicalIV(GetAR2);
674bcbd26bfSFlorian Hahn   TestNarrowCanonicalIV(GetAR2);
675bcbd26bfSFlorian Hahn   TestMatchingCanonicalIV(GetAR2, ARBitWidth);
676bcbd26bfSFlorian Hahn }
677bcbd26bfSFlorian Hahn 
678bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVExpanderShlNSW) {
679bcbd26bfSFlorian Hahn 
680bcbd26bfSFlorian Hahn   auto checkOneCase = [this](std::string &&str) {
681bcbd26bfSFlorian Hahn     LLVMContext C;
682bcbd26bfSFlorian Hahn     SMDiagnostic Err;
683bcbd26bfSFlorian Hahn     std::unique_ptr<Module> M = parseAssemblyString(str, Err, C);
684bcbd26bfSFlorian Hahn 
685bcbd26bfSFlorian Hahn     assert(M && "Could not parse module?");
686bcbd26bfSFlorian Hahn     assert(!verifyModule(*M) && "Must have been well formed!");
687bcbd26bfSFlorian Hahn 
688bcbd26bfSFlorian Hahn     Function *F = M->getFunction("f");
689bcbd26bfSFlorian Hahn     ASSERT_NE(F, nullptr) << "Could not find function 'f'";
690bcbd26bfSFlorian Hahn 
691bcbd26bfSFlorian Hahn     BasicBlock &Entry = F->getEntryBlock();
692bcbd26bfSFlorian Hahn     LoadInst *Load = cast<LoadInst>(&Entry.front());
693bcbd26bfSFlorian Hahn     BinaryOperator *And = cast<BinaryOperator>(*Load->user_begin());
694bcbd26bfSFlorian Hahn 
695bcbd26bfSFlorian Hahn     ScalarEvolution SE = buildSE(*F);
696bcbd26bfSFlorian Hahn     const SCEV *AndSCEV = SE.getSCEV(And);
697bcbd26bfSFlorian Hahn     EXPECT_TRUE(isa<SCEVMulExpr>(AndSCEV));
698bcbd26bfSFlorian Hahn     EXPECT_TRUE(cast<SCEVMulExpr>(AndSCEV)->hasNoSignedWrap());
699bcbd26bfSFlorian Hahn 
700bcbd26bfSFlorian Hahn     SCEVExpander Exp(SE, M->getDataLayout(), "expander");
701bcbd26bfSFlorian Hahn     auto *I = cast<Instruction>(Exp.expandCodeFor(AndSCEV, nullptr, And));
702bcbd26bfSFlorian Hahn     EXPECT_EQ(I->getOpcode(), Instruction::Shl);
703bcbd26bfSFlorian Hahn     EXPECT_FALSE(I->hasNoSignedWrap());
704bcbd26bfSFlorian Hahn   };
705bcbd26bfSFlorian Hahn 
706bcbd26bfSFlorian Hahn   checkOneCase("define void @f(i16* %arrayidx) { "
707bcbd26bfSFlorian Hahn                "  %1 = load i16, i16* %arrayidx "
708bcbd26bfSFlorian Hahn                "  %2 = and i16 %1, -32768 "
709bcbd26bfSFlorian Hahn                "  ret void "
710bcbd26bfSFlorian Hahn                "} ");
711bcbd26bfSFlorian Hahn 
712bcbd26bfSFlorian Hahn   checkOneCase("define void @f(i8* %arrayidx) { "
713bcbd26bfSFlorian Hahn                "  %1 = load i8, i8* %arrayidx "
714bcbd26bfSFlorian Hahn                "  %2 = and i8 %1, -128 "
715bcbd26bfSFlorian Hahn                "  ret void "
716bcbd26bfSFlorian Hahn                "} ");
717bcbd26bfSFlorian Hahn }
718bcbd26bfSFlorian Hahn 
719bcbd26bfSFlorian Hahn // Test expansion of nested addrecs in CanonicalMode.
720bcbd26bfSFlorian Hahn // Expanding nested addrecs in canonical mode requiers a canonical IV of a
721bcbd26bfSFlorian Hahn // type wider than the type of the addrec itself. Currently, SCEVExpander
722bcbd26bfSFlorian Hahn // just falls back to literal mode for nested addrecs.
723bcbd26bfSFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
724bcbd26bfSFlorian Hahn   LLVMContext C;
725bcbd26bfSFlorian Hahn   SMDiagnostic Err;
726bcbd26bfSFlorian Hahn 
727bcbd26bfSFlorian Hahn   // Expand the addrec produced by GetAddRec into a loop without a canonical IV.
728bcbd26bfSFlorian Hahn   auto TestNoCanonicalIV =
729bcbd26bfSFlorian Hahn       [&](std::function<const SCEVAddRecExpr *(ScalarEvolution & SE, Loop * L)>
730bcbd26bfSFlorian Hahn               GetAddRec) {
731bcbd26bfSFlorian Hahn         std::unique_ptr<Module> M = parseAssemblyString(
732bcbd26bfSFlorian Hahn             "define i32 @test(i32 %limit) { "
733bcbd26bfSFlorian Hahn             "entry: "
734bcbd26bfSFlorian Hahn             "  br label %loop "
735bcbd26bfSFlorian Hahn             "loop: "
736bcbd26bfSFlorian Hahn             "  %i = phi i32 [ 1, %entry ], [ %i.inc, %loop ] "
737bcbd26bfSFlorian Hahn             "  %i.inc = add nsw i32 %i, 1 "
738bcbd26bfSFlorian Hahn             "  %cont = icmp slt i32 %i.inc, %limit "
739bcbd26bfSFlorian Hahn             "  br i1 %cont, label %loop, label %exit "
740bcbd26bfSFlorian Hahn             "exit: "
741bcbd26bfSFlorian Hahn             "  ret i32 %i.inc "
742bcbd26bfSFlorian Hahn             "}",
743bcbd26bfSFlorian Hahn             Err, C);
744bcbd26bfSFlorian Hahn 
745bcbd26bfSFlorian Hahn         assert(M && "Could not parse module?");
746bcbd26bfSFlorian Hahn         assert(!verifyModule(*M) && "Must have been well formed!");
747bcbd26bfSFlorian Hahn 
748bcbd26bfSFlorian Hahn         runWithSE(*M, "test",
749bcbd26bfSFlorian Hahn                   [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
750bcbd26bfSFlorian Hahn                     auto &I = GetInstByName(F, "i");
751bcbd26bfSFlorian Hahn                     auto *Loop = LI.getLoopFor(I.getParent());
752bcbd26bfSFlorian Hahn                     EXPECT_FALSE(Loop->getCanonicalInductionVariable());
753bcbd26bfSFlorian Hahn 
754bcbd26bfSFlorian Hahn                     auto *AR = GetAddRec(SE, Loop);
755bcbd26bfSFlorian Hahn                     EXPECT_FALSE(AR->isAffine());
756bcbd26bfSFlorian Hahn 
757bcbd26bfSFlorian Hahn                     SCEVExpander Exp(SE, M->getDataLayout(), "expander");
758bcbd26bfSFlorian Hahn                     auto *InsertAt = I.getNextNode();
759bcbd26bfSFlorian Hahn                     Value *V = Exp.expandCodeFor(AR, nullptr, InsertAt);
760edf46f36SFlorian Hahn                     const SCEV *ExpandedAR = SE.getSCEV(V);
761bcbd26bfSFlorian Hahn                     // Check that the expansion happened literally.
762bcbd26bfSFlorian Hahn                     EXPECT_EQ(AR, ExpandedAR);
763bcbd26bfSFlorian Hahn                   });
764bcbd26bfSFlorian Hahn       };
765bcbd26bfSFlorian Hahn 
766bcbd26bfSFlorian Hahn   // Expand the addrec produced by GetAddRec into a loop with a canonical IV
767bcbd26bfSFlorian Hahn   // which is narrower than addrec type.
768bcbd26bfSFlorian Hahn   auto TestNarrowCanonicalIV = [&](std::function<const SCEVAddRecExpr *(
769bcbd26bfSFlorian Hahn                                        ScalarEvolution & SE, Loop * L)>
770bcbd26bfSFlorian Hahn                                        GetAddRec) {
771bcbd26bfSFlorian Hahn     std::unique_ptr<Module> M = parseAssemblyString(
772bcbd26bfSFlorian Hahn         "define i32 @test(i32 %limit) { "
773bcbd26bfSFlorian Hahn         "entry: "
774bcbd26bfSFlorian Hahn         "  br label %loop "
775bcbd26bfSFlorian Hahn         "loop: "
776bcbd26bfSFlorian Hahn         "  %i = phi i32 [ 1, %entry ], [ %i.inc, %loop ] "
777bcbd26bfSFlorian Hahn         "  %canonical.iv = phi i8 [ 0, %entry ], [ %canonical.iv.inc, %loop ] "
778bcbd26bfSFlorian Hahn         "  %i.inc = add nsw i32 %i, 1 "
779bcbd26bfSFlorian Hahn         "  %canonical.iv.inc = add i8 %canonical.iv, 1 "
780bcbd26bfSFlorian Hahn         "  %cont = icmp slt i32 %i.inc, %limit "
781bcbd26bfSFlorian Hahn         "  br i1 %cont, label %loop, label %exit "
782bcbd26bfSFlorian Hahn         "exit: "
783bcbd26bfSFlorian Hahn         "  ret i32 %i.inc "
784bcbd26bfSFlorian Hahn         "}",
785bcbd26bfSFlorian Hahn         Err, C);
786bcbd26bfSFlorian Hahn 
787bcbd26bfSFlorian Hahn     assert(M && "Could not parse module?");
788bcbd26bfSFlorian Hahn     assert(!verifyModule(*M) && "Must have been well formed!");
789bcbd26bfSFlorian Hahn 
790bcbd26bfSFlorian Hahn     runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
791bcbd26bfSFlorian Hahn       auto &I = GetInstByName(F, "i");
792bcbd26bfSFlorian Hahn 
793bcbd26bfSFlorian Hahn       auto *LoopHeaderBB = I.getParent();
794bcbd26bfSFlorian Hahn       auto *Loop = LI.getLoopFor(LoopHeaderBB);
795bcbd26bfSFlorian Hahn       PHINode *CanonicalIV = Loop->getCanonicalInductionVariable();
796bcbd26bfSFlorian Hahn       EXPECT_EQ(CanonicalIV, &GetInstByName(F, "canonical.iv"));
797bcbd26bfSFlorian Hahn 
798bcbd26bfSFlorian Hahn       auto *AR = GetAddRec(SE, Loop);
799bcbd26bfSFlorian Hahn       EXPECT_FALSE(AR->isAffine());
800bcbd26bfSFlorian Hahn 
801bcbd26bfSFlorian Hahn       unsigned ExpectedCanonicalIVWidth = SE.getTypeSizeInBits(AR->getType());
802bcbd26bfSFlorian Hahn       unsigned CanonicalIVBitWidth =
803bcbd26bfSFlorian Hahn           cast<IntegerType>(CanonicalIV->getType())->getBitWidth();
804bcbd26bfSFlorian Hahn       EXPECT_LT(CanonicalIVBitWidth, ExpectedCanonicalIVWidth);
805bcbd26bfSFlorian Hahn 
806bcbd26bfSFlorian Hahn       SCEVExpander Exp(SE, M->getDataLayout(), "expander");
807bcbd26bfSFlorian Hahn       auto *InsertAt = I.getNextNode();
808bcbd26bfSFlorian Hahn       Value *V = Exp.expandCodeFor(AR, nullptr, InsertAt);
809edf46f36SFlorian Hahn       const SCEV *ExpandedAR = SE.getSCEV(V);
810bcbd26bfSFlorian Hahn       // Check that the expansion happened literally.
811bcbd26bfSFlorian Hahn       EXPECT_EQ(AR, ExpandedAR);
812bcbd26bfSFlorian Hahn     });
813bcbd26bfSFlorian Hahn   };
814bcbd26bfSFlorian Hahn 
815bcbd26bfSFlorian Hahn   // Expand the addrec produced by GetAddRec into a loop with a canonical IV
816bcbd26bfSFlorian Hahn   // of addrec width.
817bcbd26bfSFlorian Hahn   auto TestMatchingCanonicalIV =
818bcbd26bfSFlorian Hahn       [&](std::function<const SCEVAddRecExpr *(ScalarEvolution & SE, Loop * L)>
819bcbd26bfSFlorian Hahn               GetAddRec,
820bcbd26bfSFlorian Hahn           unsigned ARBitWidth) {
821bcbd26bfSFlorian Hahn         auto ARBitWidthTypeStr = "i" + std::to_string(ARBitWidth);
822bcbd26bfSFlorian Hahn         std::unique_ptr<Module> M = parseAssemblyString(
823bcbd26bfSFlorian Hahn             "define i32 @test(i32 %limit) { "
824bcbd26bfSFlorian Hahn             "entry: "
825bcbd26bfSFlorian Hahn             "  br label %loop "
826bcbd26bfSFlorian Hahn             "loop: "
827bcbd26bfSFlorian Hahn             "  %i = phi i32 [ 1, %entry ], [ %i.inc, %loop ] "
828bcbd26bfSFlorian Hahn             "  %canonical.iv = phi " +
829bcbd26bfSFlorian Hahn                 ARBitWidthTypeStr +
830bcbd26bfSFlorian Hahn                 " [ 0, %entry ], [ %canonical.iv.inc, %loop ] "
831bcbd26bfSFlorian Hahn                 "  %i.inc = add nsw i32 %i, 1 "
832bcbd26bfSFlorian Hahn                 "  %canonical.iv.inc = add " +
833bcbd26bfSFlorian Hahn                 ARBitWidthTypeStr +
834bcbd26bfSFlorian Hahn                 " %canonical.iv, 1 "
835bcbd26bfSFlorian Hahn                 "  %cont = icmp slt i32 %i.inc, %limit "
836bcbd26bfSFlorian Hahn                 "  br i1 %cont, label %loop, label %exit "
837bcbd26bfSFlorian Hahn                 "exit: "
838bcbd26bfSFlorian Hahn                 "  ret i32 %i.inc "
839bcbd26bfSFlorian Hahn                 "}",
840bcbd26bfSFlorian Hahn             Err, C);
841bcbd26bfSFlorian Hahn 
842bcbd26bfSFlorian Hahn         assert(M && "Could not parse module?");
843bcbd26bfSFlorian Hahn         assert(!verifyModule(*M) && "Must have been well formed!");
844bcbd26bfSFlorian Hahn 
845bcbd26bfSFlorian Hahn         runWithSE(
846bcbd26bfSFlorian Hahn             *M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
847bcbd26bfSFlorian Hahn               auto &I = GetInstByName(F, "i");
848bcbd26bfSFlorian Hahn               auto &CanonicalIV = GetInstByName(F, "canonical.iv");
849bcbd26bfSFlorian Hahn 
850bcbd26bfSFlorian Hahn               auto *LoopHeaderBB = I.getParent();
851bcbd26bfSFlorian Hahn               auto *Loop = LI.getLoopFor(LoopHeaderBB);
852bcbd26bfSFlorian Hahn               EXPECT_EQ(&CanonicalIV, Loop->getCanonicalInductionVariable());
853bcbd26bfSFlorian Hahn               unsigned CanonicalIVBitWidth =
854bcbd26bfSFlorian Hahn                   cast<IntegerType>(CanonicalIV.getType())->getBitWidth();
855bcbd26bfSFlorian Hahn 
856bcbd26bfSFlorian Hahn               auto *AR = GetAddRec(SE, Loop);
857bcbd26bfSFlorian Hahn               EXPECT_FALSE(AR->isAffine());
858bcbd26bfSFlorian Hahn               EXPECT_EQ(ARBitWidth, SE.getTypeSizeInBits(AR->getType()));
859bcbd26bfSFlorian Hahn               EXPECT_EQ(CanonicalIVBitWidth, ARBitWidth);
860bcbd26bfSFlorian Hahn 
861bcbd26bfSFlorian Hahn               SCEVExpander Exp(SE, M->getDataLayout(), "expander");
862bcbd26bfSFlorian Hahn               auto *InsertAt = I.getNextNode();
863bcbd26bfSFlorian Hahn               Value *V = Exp.expandCodeFor(AR, nullptr, InsertAt);
864edf46f36SFlorian Hahn               const SCEV *ExpandedAR = SE.getSCEV(V);
865bcbd26bfSFlorian Hahn               // Check that the expansion happened literally.
866bcbd26bfSFlorian Hahn               EXPECT_EQ(AR, ExpandedAR);
867bcbd26bfSFlorian Hahn             });
868bcbd26bfSFlorian Hahn       };
869bcbd26bfSFlorian Hahn 
870bcbd26bfSFlorian Hahn   unsigned ARBitWidth = 16;
871bcbd26bfSFlorian Hahn   Type *ARType = IntegerType::get(C, ARBitWidth);
872bcbd26bfSFlorian Hahn 
873bcbd26bfSFlorian Hahn   // Expand {5,+,1,+,1}
874bcbd26bfSFlorian Hahn   auto GetAR3 = [&](ScalarEvolution &SE, Loop *L) -> const SCEVAddRecExpr * {
875bcbd26bfSFlorian Hahn     SmallVector<const SCEV *, 3> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
876bcbd26bfSFlorian Hahn                                         SE.getOne(ARType), SE.getOne(ARType)};
877bcbd26bfSFlorian Hahn     return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, L, SCEV::FlagAnyWrap));
878bcbd26bfSFlorian Hahn   };
879bcbd26bfSFlorian Hahn   TestNoCanonicalIV(GetAR3);
880bcbd26bfSFlorian Hahn   TestNarrowCanonicalIV(GetAR3);
881bcbd26bfSFlorian Hahn   TestMatchingCanonicalIV(GetAR3, ARBitWidth);
882bcbd26bfSFlorian Hahn 
883bcbd26bfSFlorian Hahn   // Expand {5,+,1,+,1,+,1}
884bcbd26bfSFlorian Hahn   auto GetAR4 = [&](ScalarEvolution &SE, Loop *L) -> const SCEVAddRecExpr * {
885bcbd26bfSFlorian Hahn     SmallVector<const SCEV *, 4> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
886bcbd26bfSFlorian Hahn                                         SE.getOne(ARType), SE.getOne(ARType),
887bcbd26bfSFlorian Hahn                                         SE.getOne(ARType)};
888bcbd26bfSFlorian Hahn     return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, L, SCEV::FlagAnyWrap));
889bcbd26bfSFlorian Hahn   };
890bcbd26bfSFlorian Hahn   TestNoCanonicalIV(GetAR4);
891bcbd26bfSFlorian Hahn   TestNarrowCanonicalIV(GetAR4);
892bcbd26bfSFlorian Hahn   TestMatchingCanonicalIV(GetAR4, ARBitWidth);
893bcbd26bfSFlorian Hahn 
894bcbd26bfSFlorian Hahn   // Expand {5,+,1,+,1,+,1,+,1}
895bcbd26bfSFlorian Hahn   auto GetAR5 = [&](ScalarEvolution &SE, Loop *L) -> const SCEVAddRecExpr * {
896bcbd26bfSFlorian Hahn     SmallVector<const SCEV *, 5> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
897bcbd26bfSFlorian Hahn                                         SE.getOne(ARType), SE.getOne(ARType),
898bcbd26bfSFlorian Hahn                                         SE.getOne(ARType), SE.getOne(ARType)};
899bcbd26bfSFlorian Hahn     return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, L, SCEV::FlagAnyWrap));
900bcbd26bfSFlorian Hahn   };
901bcbd26bfSFlorian Hahn   TestNoCanonicalIV(GetAR5);
902bcbd26bfSFlorian Hahn   TestNarrowCanonicalIV(GetAR5);
903bcbd26bfSFlorian Hahn   TestMatchingCanonicalIV(GetAR5, ARBitWidth);
904bcbd26bfSFlorian Hahn }
905bcbd26bfSFlorian Hahn 
9061d8f2e52SFlorian Hahn TEST_F(ScalarEvolutionExpanderTest, ExpandNonIntegralPtrWithNullBase) {
9071d8f2e52SFlorian Hahn   LLVMContext C;
9081d8f2e52SFlorian Hahn   SMDiagnostic Err;
9091d8f2e52SFlorian Hahn 
9101d8f2e52SFlorian Hahn   std::unique_ptr<Module> M =
9111d8f2e52SFlorian Hahn       parseAssemblyString("target datalayout = "
9121d8f2e52SFlorian Hahn                           "\"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:"
9131d8f2e52SFlorian Hahn                           "128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2\""
9141ff25323SNikita Popov                           "define ptr addrspace(1) @test(i64 %offset) { "
9151ff25323SNikita Popov                           "  %ptr = getelementptr inbounds float, ptr "
9161ff25323SNikita Popov                           "addrspace(1) null, i64 %offset"
9171ff25323SNikita Popov                           "  ret ptr addrspace(1) %ptr"
9181d8f2e52SFlorian Hahn                           "}",
9191d8f2e52SFlorian Hahn                           Err, C);
9201d8f2e52SFlorian Hahn 
9211d8f2e52SFlorian Hahn   assert(M && "Could not parse module?");
9221d8f2e52SFlorian Hahn   assert(!verifyModule(*M) && "Must have been well formed!");
9231d8f2e52SFlorian Hahn 
9241d8f2e52SFlorian Hahn   runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
9251d8f2e52SFlorian Hahn     auto &I = GetInstByName(F, "ptr");
9261d8f2e52SFlorian Hahn     auto PtrPlus1 =
9271d8f2e52SFlorian Hahn         SE.getAddExpr(SE.getSCEV(&I), SE.getConstant(I.getType(), 1));
9281d8f2e52SFlorian Hahn     SCEVExpander Exp(SE, M->getDataLayout(), "expander");
9291d8f2e52SFlorian Hahn 
9301d8f2e52SFlorian Hahn     Value *V = Exp.expandCodeFor(PtrPlus1, I.getType(), &I);
9311d8f2e52SFlorian Hahn     I.replaceAllUsesWith(V);
9321d8f2e52SFlorian Hahn 
93378b8ce40SRoman Lebedev     // Check that the expander created:
9341ff25323SNikita Popov     // define ptr addrspace(1) @test(i64 %off) {
9351ff25323SNikita Popov     //   %1 = shl i64 %offset, 2
9361ff25323SNikita Popov     //   %2 = add nuw nsw i64 %1, 1
9371ff25323SNikita Popov     //   %uglygep = getelementptr i8, ptr addrspace(1) null, i64 %2
9381ff25323SNikita Popov     //   %ptr = getelementptr inbounds float, ptr addrspace(1) null, i64 %off
9391ff25323SNikita Popov     //   ret ptr addrspace(1) %uglygep
94078b8ce40SRoman Lebedev     // }
94178b8ce40SRoman Lebedev 
9421ff25323SNikita Popov     Value *Offset = &*F.arg_begin();
9431ff25323SNikita Popov     auto *GEP = dyn_cast<GetElementPtrInst>(V);
9441d8f2e52SFlorian Hahn     EXPECT_TRUE(GEP);
9451ff25323SNikita Popov     EXPECT_TRUE(cast<Constant>(GEP->getPointerOperand())->isNullValue());
9465f2acfb6SRoman Lebedev     EXPECT_EQ(GEP->getNumOperands(), 2U);
9471ff25323SNikita Popov     EXPECT_TRUE(match(
9481ff25323SNikita Popov         GEP->getOperand(1),
9491ff25323SNikita Popov         m_Add(m_Shl(m_Specific(Offset), m_SpecificInt(2)), m_SpecificInt(1))));
9501ff25323SNikita Popov     EXPECT_EQ(cast<PointerType>(GEP->getPointerOperand()->getType())
9511d8f2e52SFlorian Hahn                   ->getAddressSpace(),
9521d8f2e52SFlorian Hahn               cast<PointerType>(I.getType())->getAddressSpace());
9531d8f2e52SFlorian Hahn     EXPECT_FALSE(verifyFunction(F, &errs()));
9541d8f2e52SFlorian Hahn   });
9551d8f2e52SFlorian Hahn }
9561d8f2e52SFlorian Hahn 
9574b3ba64bSNikita Popov TEST_F(ScalarEvolutionExpanderTest, GEPFlags) {
9584b3ba64bSNikita Popov   LLVMContext C;
9594b3ba64bSNikita Popov   SMDiagnostic Err;
9604b3ba64bSNikita Popov   StringRef ModStr = R"(
9614b3ba64bSNikita Popov   define void @f(ptr %p, i64 %x) {
9624b3ba64bSNikita Popov     %gep_inbounds = getelementptr inbounds i8, ptr %p, i64 %x
9634b3ba64bSNikita Popov     ret void
9644b3ba64bSNikita Popov   })";
9654b3ba64bSNikita Popov   std::unique_ptr<Module> M = parseAssemblyString(ModStr, Err, C);
9664b3ba64bSNikita Popov 
9674b3ba64bSNikita Popov   assert(M && "Could not parse module?");
9684b3ba64bSNikita Popov   assert(!verifyModule(*M) && "Must have been well formed!");
9694b3ba64bSNikita Popov 
9704b3ba64bSNikita Popov   Function *F = M->getFunction("f");
9714b3ba64bSNikita Popov   ASSERT_NE(F, nullptr) << "Could not find function 'f'";
9724b3ba64bSNikita Popov   BasicBlock &Entry = F->getEntryBlock();
9734b3ba64bSNikita Popov   auto *GEP = cast<GetElementPtrInst>(&Entry.front());
9744b3ba64bSNikita Popov 
9754b3ba64bSNikita Popov   ScalarEvolution SE = buildSE(*F);
9764b3ba64bSNikita Popov   const SCEV *Ptr = SE.getSCEV(F->getArg(0));
9774b3ba64bSNikita Popov   const SCEV *X = SE.getSCEV(F->getArg(1));
9784b3ba64bSNikita Popov   const SCEV *PtrX = SE.getAddExpr(Ptr, X);
9794b3ba64bSNikita Popov 
9804b3ba64bSNikita Popov   SCEVExpander Exp(SE, M->getDataLayout(), "expander");
9814b3ba64bSNikita Popov   auto *I = cast<Instruction>(
9824b3ba64bSNikita Popov       Exp.expandCodeFor(PtrX, nullptr, Entry.getTerminator()));
9834b3ba64bSNikita Popov   // Check that the GEP is reused, but the inbounds flag cleared. We don't
9844b3ba64bSNikita Popov   // know that the newly introduced use is inbounds.
9854b3ba64bSNikita Popov   EXPECT_EQ(I, GEP);
9864b3ba64bSNikita Popov   EXPECT_EQ(GEP->getNoWrapFlags(), GEPNoWrapFlags::none());
9874b3ba64bSNikita Popov }
9884b3ba64bSNikita Popov 
989bcbd26bfSFlorian Hahn } // end namespace llvm
990