109d30697STobias Grosser //===------ CodeGeneration.cpp - Code generate the Scops using ISL. ----======// 209d30697STobias Grosser // 309d30697STobias Grosser // The LLVM Compiler Infrastructure 409d30697STobias Grosser // 509d30697STobias Grosser // This file is distributed under the University of Illinois Open Source 609d30697STobias Grosser // License. See LICENSE.TXT for details. 709d30697STobias Grosser // 809d30697STobias Grosser //===----------------------------------------------------------------------===// 909d30697STobias Grosser // 1009d30697STobias Grosser // The CodeGeneration pass takes a Scop created by ScopInfo and translates it 1109d30697STobias Grosser // back to LLVM-IR using the ISL code generator. 1209d30697STobias Grosser // 1309d30697STobias Grosser // The Scop describes the high level memory behaviour of a control flow region. 1409d30697STobias Grosser // Transformation passes can update the schedule (execution order) of statements 1509d30697STobias Grosser // in the Scop. ISL is used to generate an abstract syntax tree that reflects 1609d30697STobias Grosser // the updated execution order. This clast is used to create new LLVM-IR that is 1709d30697STobias Grosser // computationally equivalent to the original control flow region, but executes 1809d30697STobias Grosser // its code in the new execution order defined by the changed schedule. 1909d30697STobias Grosser // 2009d30697STobias Grosser //===----------------------------------------------------------------------===// 2109d30697STobias Grosser 2278ae52f0SPhilip Pfaffe #include "polly/CodeGen/CodeGeneration.h" 2309d30697STobias Grosser #include "polly/CodeGen/IslAst.h" 245624d3c9STobias Grosser #include "polly/CodeGen/IslNodeBuilder.h" 2565371af2STobias Grosser #include "polly/CodeGen/PerfMonitor.h" 2609d30697STobias Grosser #include "polly/CodeGen/Utils.h" 2709d30697STobias Grosser #include "polly/DependenceInfo.h" 2809d30697STobias Grosser #include "polly/LinkAllPasses.h" 2958e58544STobias Grosser #include "polly/Options.h" 3009d30697STobias Grosser #include "polly/ScopInfo.h" 3109d30697STobias Grosser #include "polly/Support/ScopHelper.h" 3266ef16b2SChandler Carruth #include "llvm/Analysis/AliasAnalysis.h" 3366ef16b2SChandler Carruth #include "llvm/Analysis/BasicAliasAnalysis.h" 3466ef16b2SChandler Carruth #include "llvm/Analysis/GlobalsModRef.h" 3578ae52f0SPhilip Pfaffe #include "llvm/Analysis/LoopInfo.h" 3666ef16b2SChandler Carruth #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" 37c2bb0cbeSTobias Grosser #include "llvm/IR/Module.h" 3878ae52f0SPhilip Pfaffe #include "llvm/IR/PassManager.h" 39c2bb0cbeSTobias Grosser #include "llvm/IR/Verifier.h" 40c2bb0cbeSTobias Grosser #include "llvm/Support/Debug.h" 4109d30697STobias Grosser 4209d30697STobias Grosser using namespace polly; 4309d30697STobias Grosser using namespace llvm; 4409d30697STobias Grosser 4509d30697STobias Grosser #define DEBUG_TYPE "polly-codegen" 4609d30697STobias Grosser 4758e58544STobias Grosser static cl::opt<bool> Verify("polly-codegen-verify", 4858e58544STobias Grosser cl::desc("Verify the function generated by Polly"), 49f1372217STobias Grosser cl::Hidden, cl::init(false), cl::ZeroOrMore, 5058e58544STobias Grosser cl::cat(PollyCategory)); 5158e58544STobias Grosser 5265371af2STobias Grosser static cl::opt<bool> 5365371af2STobias Grosser PerfMonitoring("polly-codegen-perf-monitoring", 5465371af2STobias Grosser cl::desc("Add run-time performance monitoring"), cl::Hidden, 5565371af2STobias Grosser cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 5665371af2STobias Grosser 5709d30697STobias Grosser namespace { 5809d30697STobias Grosser 5978ae52f0SPhilip Pfaffe static void verifyGeneratedFunction(Scop &S, Function &F, IslAstInfo &AI) { 60d439911fSTobias Grosser if (!Verify || !verifyFunction(F, &errs())) 6158e58544STobias Grosser return; 6209d30697STobias Grosser 6309d30697STobias Grosser DEBUG({ 6409d30697STobias Grosser errs() << "== ISL Codegen created an invalid function ==\n\n== The " 6509d30697STobias Grosser "SCoP ==\n"; 6609d30697STobias Grosser S.print(errs()); 6709d30697STobias Grosser errs() << "\n== The isl AST ==\n"; 6878ae52f0SPhilip Pfaffe AI.print(errs()); 6909d30697STobias Grosser errs() << "\n== The invalid function ==\n"; 7009d30697STobias Grosser F.print(errs()); 7109d30697STobias Grosser }); 7209d30697STobias Grosser 7358e58544STobias Grosser llvm_unreachable("Polly generated function could not be verified. Add " 7458e58544STobias Grosser "-polly-codegen-verify=false to disable this assertion."); 7509d30697STobias Grosser } 7609d30697STobias Grosser 779c483c58SMichael Kruse // CodeGeneration adds a lot of BBs without updating the RegionInfo 789c483c58SMichael Kruse // We make all created BBs belong to the scop's parent region without any 799c483c58SMichael Kruse // nested structure to keep the RegionInfo verifier happy. 8078ae52f0SPhilip Pfaffe static void fixRegionInfo(Function &F, Region &ParentRegion, RegionInfo &RI) { 8178ae52f0SPhilip Pfaffe for (BasicBlock &BB : F) { 8278ae52f0SPhilip Pfaffe if (RI.getRegionFor(&BB)) 839c483c58SMichael Kruse continue; 849c483c58SMichael Kruse 8578ae52f0SPhilip Pfaffe RI.setRegionFor(&BB, &ParentRegion); 869c483c58SMichael Kruse } 879c483c58SMichael Kruse } 889c483c58SMichael Kruse 89c80d6979STobias Grosser /// Mark a basic block unreachable. 90bfb6a968STobias Grosser /// 91bfb6a968STobias Grosser /// Marks the basic block @p Block unreachable by equipping it with an 92bfb6a968STobias Grosser /// UnreachableInst. 9378ae52f0SPhilip Pfaffe static void markBlockUnreachable(BasicBlock &Block, PollyIRBuilder &Builder) { 94bfb6a968STobias Grosser auto *OrigTerminator = Block.getTerminator(); 95bfb6a968STobias Grosser Builder.SetInsertPoint(OrigTerminator); 96bfb6a968STobias Grosser Builder.CreateUnreachable(); 97bfb6a968STobias Grosser OrigTerminator->eraseFromParent(); 98bfb6a968STobias Grosser } 99bfb6a968STobias Grosser 100895f5d80SMichael Kruse /// Remove all lifetime markers (llvm.lifetime.start, llvm.lifetime.end) from 101895f5d80SMichael Kruse /// @R. 102895f5d80SMichael Kruse /// 103895f5d80SMichael Kruse /// CodeGeneration does not copy lifetime markers into the optimized SCoP, 104895f5d80SMichael Kruse /// which would leave the them only in the original path. This can transform 105895f5d80SMichael Kruse /// code such as 106895f5d80SMichael Kruse /// 107895f5d80SMichael Kruse /// llvm.lifetime.start(%p) 108895f5d80SMichael Kruse /// llvm.lifetime.end(%p) 109895f5d80SMichael Kruse /// 110895f5d80SMichael Kruse /// into 111895f5d80SMichael Kruse /// 112895f5d80SMichael Kruse /// if (RTC) { 113895f5d80SMichael Kruse /// // generated code 114895f5d80SMichael Kruse /// } else { 115895f5d80SMichael Kruse /// // original code 116895f5d80SMichael Kruse /// llvm.lifetime.start(%p) 117895f5d80SMichael Kruse /// } 118895f5d80SMichael Kruse /// llvm.lifetime.end(%p) 119895f5d80SMichael Kruse /// 120895f5d80SMichael Kruse /// The current StackColoring algorithm cannot handle if some, but not all, 121895f5d80SMichael Kruse /// paths from the end marker to the entry block cross the start marker. Same 122895f5d80SMichael Kruse /// for start markers that do not always cross the end markers. We avoid any 123895f5d80SMichael Kruse /// issues by removing all lifetime markers, even from the original code. 124895f5d80SMichael Kruse /// 125895f5d80SMichael Kruse /// A better solution could be to hoist all llvm.lifetime.start to the split 126895f5d80SMichael Kruse /// node and all llvm.lifetime.end to the merge node, which should be 127895f5d80SMichael Kruse /// conservatively correct. 12878ae52f0SPhilip Pfaffe static void removeLifetimeMarkers(Region *R) { 129895f5d80SMichael Kruse for (auto *BB : R->blocks()) { 130895f5d80SMichael Kruse auto InstIt = BB->begin(); 131895f5d80SMichael Kruse auto InstEnd = BB->end(); 132895f5d80SMichael Kruse 133895f5d80SMichael Kruse while (InstIt != InstEnd) { 134895f5d80SMichael Kruse auto NextIt = InstIt; 135895f5d80SMichael Kruse ++NextIt; 136895f5d80SMichael Kruse 137895f5d80SMichael Kruse if (auto *IT = dyn_cast<IntrinsicInst>(&*InstIt)) { 138895f5d80SMichael Kruse switch (IT->getIntrinsicID()) { 139895f5d80SMichael Kruse case llvm::Intrinsic::lifetime_start: 140895f5d80SMichael Kruse case llvm::Intrinsic::lifetime_end: 141895f5d80SMichael Kruse BB->getInstList().erase(InstIt); 142895f5d80SMichael Kruse break; 143895f5d80SMichael Kruse default: 144895f5d80SMichael Kruse break; 145895f5d80SMichael Kruse } 146895f5d80SMichael Kruse } 147895f5d80SMichael Kruse 148895f5d80SMichael Kruse InstIt = NextIt; 149895f5d80SMichael Kruse } 150895f5d80SMichael Kruse } 151895f5d80SMichael Kruse } 152895f5d80SMichael Kruse 15378ae52f0SPhilip Pfaffe static bool CodeGen(Scop &S, IslAstInfo &AI, LoopInfo &LI, DominatorTree &DT, 15478ae52f0SPhilip Pfaffe ScalarEvolution &SE, RegionInfo &RI) { 15509d30697STobias Grosser // Check if we created an isl_ast root node, otherwise exit. 15678ae52f0SPhilip Pfaffe isl_ast_node *AstRoot = AI.getAst(); 15709d30697STobias Grosser if (!AstRoot) 15809d30697STobias Grosser return false; 15909d30697STobias Grosser 16078ae52f0SPhilip Pfaffe auto &DL = S.getFunction().getParent()->getDataLayout(); 16122370884SMichael Kruse Region *R = &S.getRegion(); 16222370884SMichael Kruse assert(!R->isTopLevelRegion() && "Top level regions are not supported"); 16309d30697STobias Grosser 164d78616f9STobias Grosser ScopAnnotator Annotator; 16509d30697STobias Grosser Annotator.buildAliasScopes(S); 16609d30697STobias Grosser 16778ae52f0SPhilip Pfaffe simplifyRegion(R, &DT, &LI, &RI); 16822370884SMichael Kruse assert(R->isSimple()); 169ef74443cSJohannes Doerfert BasicBlock *EnteringBB = S.getEnteringBlock(); 17022370884SMichael Kruse assert(EnteringBB); 17109d30697STobias Grosser PollyIRBuilder Builder = createPollyIRBuilder(EnteringBB, Annotator); 17209d30697STobias Grosser 17309d30697STobias Grosser // Only build the run-time condition and parameters _after_ having 17409d30697STobias Grosser // introduced the conditional branch. This is important as the conditional 17509d30697STobias Grosser // branch will guard the original scop from new induction variables that 17609d30697STobias Grosser // the SCEVExpander may introduce while code generating the parameters and 17709d30697STobias Grosser // which may introduce scalar dependences that prevent us from correctly 17809d30697STobias Grosser // code generating this scop. 17909d30697STobias Grosser BasicBlock *StartBlock = 18078ae52f0SPhilip Pfaffe executeScopConditionally(S, Builder.getTrue(), DT, RI, LI); 181895f5d80SMichael Kruse removeLifetimeMarkers(R); 182bfb6a968STobias Grosser auto *SplitBlock = StartBlock->getSinglePredecessor(); 18309e3697fSJohannes Doerfert 18478ae52f0SPhilip Pfaffe IslNodeBuilder NodeBuilder(Builder, Annotator, DL, LI, SE, DT, S, StartBlock); 185acf80064SEli Friedman 18665371af2STobias Grosser if (PerfMonitoring) { 187*07bee290SSiddharth Bhat PerfMonitor P(S, EnteringBB->getParent()->getParent()); 18865371af2STobias Grosser P.initialize(); 18965371af2STobias Grosser P.insertRegionStart(SplitBlock->getTerminator()); 19065371af2STobias Grosser 19165371af2STobias Grosser BasicBlock *MergeBlock = SplitBlock->getTerminator() 19265371af2STobias Grosser ->getSuccessor(0) 19365371af2STobias Grosser ->getUniqueSuccessor() 19465371af2STobias Grosser ->getUniqueSuccessor(); 19565371af2STobias Grosser P.insertRegionEnd(MergeBlock->getTerminator()); 19665371af2STobias Grosser } 19765371af2STobias Grosser 19809e3697fSJohannes Doerfert // First generate code for the hoisted invariant loads and transitively the 19909e3697fSJohannes Doerfert // parameters they reference. Afterwards, for the remaining parameters that 20009e3697fSJohannes Doerfert // might reference the hoisted loads. Finally, build the runtime check 20109e3697fSJohannes Doerfert // that might reference both hoisted loads as well as parameters. 202c4898504SJohannes Doerfert // If the hoisting fails we have to bail and execute the original code. 20309d30697STobias Grosser Builder.SetInsertPoint(SplitBlock->getTerminator()); 204c4898504SJohannes Doerfert if (!NodeBuilder.preloadInvariantLoads()) { 2051dd6e37aSJohannes Doerfert 206bfb6a968STobias Grosser // Patch the introduced branch condition to ensure that we always execute 207bfb6a968STobias Grosser // the original SCoP. 208c4898504SJohannes Doerfert auto *FalseI1 = Builder.getFalse(); 20937977076SJohannes Doerfert auto *SplitBBTerm = Builder.GetInsertBlock()->getTerminator(); 21037977076SJohannes Doerfert SplitBBTerm->setOperand(0, FalseI1); 2111dd6e37aSJohannes Doerfert 212bfb6a968STobias Grosser // Since the other branch is hence ignored we mark it as unreachable and 213bfb6a968STobias Grosser // adjust the dominator tree accordingly. 214bfb6a968STobias Grosser auto *ExitingBlock = StartBlock->getUniqueSuccessor(); 215bfb6a968STobias Grosser assert(ExitingBlock); 216bfb6a968STobias Grosser auto *MergeBlock = ExitingBlock->getUniqueSuccessor(); 217bfb6a968STobias Grosser assert(MergeBlock); 218bfb6a968STobias Grosser markBlockUnreachable(*StartBlock, Builder); 219bfb6a968STobias Grosser markBlockUnreachable(*ExitingBlock, Builder); 220ef74443cSJohannes Doerfert auto *ExitingBB = S.getExitingBlock(); 221bfb6a968STobias Grosser assert(ExitingBB); 22278ae52f0SPhilip Pfaffe DT.changeImmediateDominator(MergeBlock, ExitingBB); 22378ae52f0SPhilip Pfaffe DT.eraseNode(ExitingBlock); 224bfb6a968STobias Grosser 225bfb6a968STobias Grosser isl_ast_node_free(AstRoot); 2261dd6e37aSJohannes Doerfert } else { 227d7754a12SRoman Gareev NodeBuilder.allocateNewArrays(); 22809e3697fSJohannes Doerfert NodeBuilder.addParameters(S.getContext()); 22978ae52f0SPhilip Pfaffe Value *RTC = NodeBuilder.createRTC(AI.getRunCondition()); 230404a0f81SJohannes Doerfert 2313717aa5dSTobias Grosser Builder.GetInsertBlock()->getTerminator()->setOperand(0, RTC); 2323717aa5dSTobias Grosser Builder.SetInsertPoint(&StartBlock->front()); 2333717aa5dSTobias Grosser 2343717aa5dSTobias Grosser NodeBuilder.create(AstRoot); 2358ed5e599STobias Grosser NodeBuilder.finalize(); 23678ae52f0SPhilip Pfaffe fixRegionInfo(*EnteringBB->getParent(), *R->getParent(), RI); 2371dd6e37aSJohannes Doerfert } 238ecff11dcSJohannes Doerfert 2396a6a671cSJohannes Doerfert Function *F = EnteringBB->getParent(); 24078ae52f0SPhilip Pfaffe verifyGeneratedFunction(S, *F, AI); 241a9dc5294SJohannes Doerfert for (auto *SubF : NodeBuilder.getParallelSubfunctions()) 24278ae52f0SPhilip Pfaffe verifyGeneratedFunction(S, *SubF, AI); 243652f7808STobias Grosser 2444c86a1d9SMichael Kruse // Mark the function such that we run additional cleanup passes on this 2454c86a1d9SMichael Kruse // function (e.g. mem2reg to rediscover phi nodes). 2464c86a1d9SMichael Kruse F->addFnAttr("polly-optimized"); 24709d30697STobias Grosser return true; 24809d30697STobias Grosser } 24909d30697STobias Grosser 25078ae52f0SPhilip Pfaffe class CodeGeneration : public ScopPass { 25178ae52f0SPhilip Pfaffe public: 25278ae52f0SPhilip Pfaffe static char ID; 25378ae52f0SPhilip Pfaffe 25478ae52f0SPhilip Pfaffe CodeGeneration() : ScopPass(ID) {} 25578ae52f0SPhilip Pfaffe 25678ae52f0SPhilip Pfaffe /// The datalayout used 25778ae52f0SPhilip Pfaffe const DataLayout *DL; 25878ae52f0SPhilip Pfaffe 25978ae52f0SPhilip Pfaffe /// @name The analysis passes we need to generate code. 26078ae52f0SPhilip Pfaffe /// 26178ae52f0SPhilip Pfaffe ///{ 26278ae52f0SPhilip Pfaffe LoopInfo *LI; 26378ae52f0SPhilip Pfaffe IslAstInfo *AI; 26478ae52f0SPhilip Pfaffe DominatorTree *DT; 26578ae52f0SPhilip Pfaffe ScalarEvolution *SE; 26678ae52f0SPhilip Pfaffe RegionInfo *RI; 26778ae52f0SPhilip Pfaffe ///} 26878ae52f0SPhilip Pfaffe 26978ae52f0SPhilip Pfaffe /// Generate LLVM-IR for the SCoP @p S. 27078ae52f0SPhilip Pfaffe bool runOnScop(Scop &S) override { 27178ae52f0SPhilip Pfaffe AI = &getAnalysis<IslAstInfoWrapperPass>().getAI(); 27278ae52f0SPhilip Pfaffe LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 27378ae52f0SPhilip Pfaffe DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 27478ae52f0SPhilip Pfaffe SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 27578ae52f0SPhilip Pfaffe DL = &S.getFunction().getParent()->getDataLayout(); 27678ae52f0SPhilip Pfaffe RI = &getAnalysis<RegionInfoPass>().getRegionInfo(); 27778ae52f0SPhilip Pfaffe return CodeGen(S, *AI, *LI, *DT, *SE, *RI); 27878ae52f0SPhilip Pfaffe } 27978ae52f0SPhilip Pfaffe 280c80d6979STobias Grosser /// Register all analyses and transformation required. 28109d30697STobias Grosser void getAnalysisUsage(AnalysisUsage &AU) const override { 28209d30697STobias Grosser AU.addRequired<DominatorTreeWrapperPass>(); 2832b852e2eSPhilip Pfaffe AU.addRequired<IslAstInfoWrapperPass>(); 28409d30697STobias Grosser AU.addRequired<RegionInfoPass>(); 285c5bcf246STobias Grosser AU.addRequired<ScalarEvolutionWrapperPass>(); 2865cc87e3aSPhilip Pfaffe AU.addRequired<ScopDetectionWrapperPass>(); 28799191c78SJohannes Doerfert AU.addRequired<ScopInfoRegionPass>(); 28809d30697STobias Grosser AU.addRequired<LoopInfoWrapperPass>(); 28909d30697STobias Grosser 29009d30697STobias Grosser AU.addPreserved<DependenceInfo>(); 29109d30697STobias Grosser 29266ef16b2SChandler Carruth AU.addPreserved<AAResultsWrapperPass>(); 29366ef16b2SChandler Carruth AU.addPreserved<BasicAAWrapperPass>(); 29409d30697STobias Grosser AU.addPreserved<LoopInfoWrapperPass>(); 29509d30697STobias Grosser AU.addPreserved<DominatorTreeWrapperPass>(); 29666ef16b2SChandler Carruth AU.addPreserved<GlobalsAAWrapperPass>(); 2972b852e2eSPhilip Pfaffe AU.addPreserved<IslAstInfoWrapperPass>(); 2985cc87e3aSPhilip Pfaffe AU.addPreserved<ScopDetectionWrapperPass>(); 299c5bcf246STobias Grosser AU.addPreserved<ScalarEvolutionWrapperPass>(); 30066ef16b2SChandler Carruth AU.addPreserved<SCEVAAWrapperPass>(); 30109d30697STobias Grosser 30209d30697STobias Grosser // FIXME: We do not yet add regions for the newly generated code to the 30309d30697STobias Grosser // region tree. 30409d30697STobias Grosser AU.addPreserved<RegionInfoPass>(); 30599191c78SJohannes Doerfert AU.addPreserved<ScopInfoRegionPass>(); 30609d30697STobias Grosser } 30709d30697STobias Grosser }; 308522478d2STobias Grosser } // namespace 30909d30697STobias Grosser 31078ae52f0SPhilip Pfaffe PreservedAnalyses 31178ae52f0SPhilip Pfaffe polly::CodeGenerationPass::run(Scop &S, ScopAnalysisManager &SAM, 31278ae52f0SPhilip Pfaffe ScopStandardAnalysisResults &AR, SPMUpdater &U) { 31378ae52f0SPhilip Pfaffe auto &AI = SAM.getResult<IslAstAnalysis>(S, AR); 31478ae52f0SPhilip Pfaffe if (CodeGen(S, AI, AR.LI, AR.DT, AR.SE, AR.RI)) 31578ae52f0SPhilip Pfaffe return PreservedAnalyses::none(); 31678ae52f0SPhilip Pfaffe 31778ae52f0SPhilip Pfaffe return PreservedAnalyses::all(); 31878ae52f0SPhilip Pfaffe } 31978ae52f0SPhilip Pfaffe 32009d30697STobias Grosser char CodeGeneration::ID = 1; 32109d30697STobias Grosser 32209d30697STobias Grosser Pass *polly::createCodeGenerationPass() { return new CodeGeneration(); } 32309d30697STobias Grosser 32409d30697STobias Grosser INITIALIZE_PASS_BEGIN(CodeGeneration, "polly-codegen", 32509d30697STobias Grosser "Polly - Create LLVM-IR from SCoPs", false, false); 32609d30697STobias Grosser INITIALIZE_PASS_DEPENDENCY(DependenceInfo); 32709d30697STobias Grosser INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); 32809d30697STobias Grosser INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); 32909d30697STobias Grosser INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); 330c5bcf246STobias Grosser INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); 3315cc87e3aSPhilip Pfaffe INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); 33209d30697STobias Grosser INITIALIZE_PASS_END(CodeGeneration, "polly-codegen", 33309d30697STobias Grosser "Polly - Create LLVM-IR from SCoPs", false, false) 334