//===- LoopVersioningLICM.cpp - LICM Loop Versioning ----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // When alias analysis is uncertain about the aliasing between any two accesses, // it will return MayAlias. This uncertainty from alias analysis restricts LICM // from proceeding further. In cases where alias analysis is uncertain we might // use loop versioning as an alternative. // // Loop Versioning will create a version of the loop with aggressive aliasing // assumptions in addition to the original with conservative (default) aliasing // assumptions. The version of the loop making aggressive aliasing assumptions // will have all the memory accesses marked as no-alias. These two versions of // loop will be preceded by a memory runtime check. This runtime check consists // of bound checks for all unique memory accessed in loop, and it ensures the // lack of memory aliasing. The result of the runtime check determines which of // the loop versions is executed: If the runtime check detects any memory // aliasing, then the original loop is executed. Otherwise, the version with // aggressive aliasing assumptions is used. // // Following are the top level steps: // // a) Perform LoopVersioningLICM's feasibility check. // b) If loop is a candidate for versioning then create a memory bound check, // by considering all the memory accesses in loop body. // c) Clone original loop and set all memory accesses as no-alias in new loop. // d) Set original loop & versioned loop as a branch target of the runtime check // result. // // It transforms loop as shown below: // // +----------------+ // |Runtime Memcheck| // +----------------+ // | // +----------+----------------+----------+ // | | // +---------+----------+ +-----------+----------+ // |Orig Loop Preheader | |Cloned Loop Preheader | // +--------------------+ +----------------------+ // | | // +--------------------+ +----------------------+ // |Orig Loop Body | |Cloned Loop Body | // +--------------------+ +----------------------+ // | | // +--------------------+ +----------------------+ // |Orig Loop Exit Block| |Cloned Loop Exit Block| // +--------------------+ +-----------+----------+ // | | // +----------+--------------+-----------+ // | // +-----+----+ // |Join Block| // +----------+ // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar/LoopVersioningLICM.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include "llvm/Transforms/Utils/LoopVersioning.h" #include <cassert> #include <memory> usingnamespacellvm; #define DEBUG_TYPE … static const char *LICMVersioningMetaData = …; /// Threshold minimum allowed percentage for possible /// invariant instructions in a loop. static cl::opt<float> LVInvarThreshold("licm-versioning-invariant-threshold", cl::desc("LoopVersioningLICM's minimum allowed percentage" "of possible invariant instructions per loop"), cl::init(25), cl::Hidden); /// Threshold for maximum allowed loop nest/depth static cl::opt<unsigned> LVLoopDepthThreshold( "licm-versioning-max-depth-threshold", cl::desc( "LoopVersioningLICM's threshold for maximum allowed loop nest/depth"), cl::init(2), cl::Hidden); namespace { struct LoopVersioningLICM { … }; } // end anonymous namespace /// Check loop structure and confirms it's good for LoopVersioningLICM. bool LoopVersioningLICM::legalLoopStructure() { … } /// Check memory accesses in loop and confirms it's good for /// LoopVersioningLICM. bool LoopVersioningLICM::legalLoopMemoryAccesses() { … } /// Check loop instructions safe for Loop versioning. /// It returns true if it's safe else returns false. /// Consider following: /// 1) Check all load store in loop body are non atomic & non volatile. /// 2) Check function call safety, by ensuring its not accessing memory. /// 3) Loop body shouldn't have any may throw instruction. /// 4) Loop body shouldn't have any convergent or noduplicate instructions. bool LoopVersioningLICM::instructionSafeForVersioning(Instruction *I) { … } /// Check loop instructions and confirms it's good for /// LoopVersioningLICM. bool LoopVersioningLICM::legalLoopInstructions() { … } /// It checks loop is already visited or not. /// check loop meta data, if loop revisited return true /// else false. bool LoopVersioningLICM::isLoopAlreadyVisited() { … } /// Checks legality for LoopVersioningLICM by considering following: /// a) loop structure legality b) loop instruction legality /// c) loop memory access legality. /// Return true if legal else returns false. bool LoopVersioningLICM::isLegalForVersioning() { … } /// Update loop with aggressive aliasing assumptions. /// It marks no-alias to any pairs of memory operations by assuming /// loop should not have any must-alias memory accesses pairs. /// During LoopVersioningLICM legality we ignore loops having must /// aliasing memory accesses. void LoopVersioningLICM::setNoAliasToLoop(Loop *VerLoop) { … } bool LoopVersioningLICM::run(DominatorTree *DT) { … } namespace llvm { PreservedAnalyses LoopVersioningLICMPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &LAR, LPMUpdater &U) { … } } // namespace llvm