1 //===- LICM.h - Loop Invariant Code Motion Pass -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass performs loop invariant code motion, attempting to remove as much 10 // code from the body of a loop as possible. It does this by either hoisting 11 // code into the preheader block, or by sinking code to the exit blocks if it is 12 // safe. This pass also promotes must-aliased memory locations in the loop to 13 // live in registers, thus hoisting and sinking "invariant" loads and stores. 14 // 15 // This pass uses alias analysis for two purposes: 16 // 17 // 1. Moving loop invariant loads and calls out of loops. If we can determine 18 // that a load or call inside of a loop never aliases anything stored to, 19 // we can hoist it or sink it like any other instruction. 20 // 2. Scalar Promotion of Memory - If there is a store instruction inside of 21 // the loop, we try to move the store to happen AFTER the loop instead of 22 // inside of the loop. This can only happen if a few conditions are true: 23 // A. The pointer stored through is loop invariant 24 // B. There are no stores or loads in the loop which _may_ alias the 25 // pointer. There are no calls in the loop which mod/ref the pointer. 26 // If these conditions are true, we can promote the loads and stores in the 27 // loop of the pointer to use a temporary alloca'd variable. We then use 28 // the SSAUpdater to construct the appropriate SSA form for the value. 29 // 30 //===----------------------------------------------------------------------===// 31 32 #ifndef LLVM_TRANSFORMS_SCALAR_LICM_H 33 #define LLVM_TRANSFORMS_SCALAR_LICM_H 34 35 #include "llvm/Analysis/LoopAnalysisManager.h" 36 #include "llvm/IR/PassManager.h" 37 #include "llvm/Support/CommandLine.h" 38 39 namespace llvm { 40 41 class LPMUpdater; 42 class Loop; 43 class LoopNest; 44 45 extern cl::opt<unsigned> SetLicmMssaOptCap; 46 extern cl::opt<unsigned> SetLicmMssaNoAccForPromotionCap; 47 48 struct LICMOptions { 49 unsigned MssaOptCap; 50 unsigned MssaNoAccForPromotionCap; 51 bool AllowSpeculation; 52 LICMOptionsLICMOptions53 LICMOptions() 54 : MssaOptCap(SetLicmMssaOptCap), 55 MssaNoAccForPromotionCap(SetLicmMssaNoAccForPromotionCap), 56 AllowSpeculation(true) {} 57 LICMOptionsLICMOptions58 LICMOptions(unsigned MssaOptCap, unsigned MssaNoAccForPromotionCap, 59 bool AllowSpeculation) 60 : MssaOptCap(MssaOptCap), 61 MssaNoAccForPromotionCap(MssaNoAccForPromotionCap), 62 AllowSpeculation(AllowSpeculation) {} 63 }; 64 65 /// Performs Loop Invariant Code Motion Pass. 66 class LICMPass : public PassInfoMixin<LICMPass> { 67 LICMOptions Opts; 68 69 public: LICMPass(unsigned MssaOptCap,unsigned MssaNoAccForPromotionCap,bool AllowSpeculation)70 LICMPass(unsigned MssaOptCap, unsigned MssaNoAccForPromotionCap, 71 bool AllowSpeculation) 72 : LICMPass(LICMOptions(MssaOptCap, MssaNoAccForPromotionCap, 73 AllowSpeculation)) {} LICMPass(LICMOptions Opts)74 LICMPass(LICMOptions Opts) : Opts(Opts) {} 75 76 PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, 77 LoopStandardAnalysisResults &AR, LPMUpdater &U); 78 79 void printPipeline(raw_ostream &OS, 80 function_ref<StringRef(StringRef)> MapClassName2PassName); 81 }; 82 83 /// Performs LoopNest Invariant Code Motion Pass. 84 class LNICMPass : public PassInfoMixin<LNICMPass> { 85 LICMOptions Opts; 86 87 public: LNICMPass(unsigned MssaOptCap,unsigned MssaNoAccForPromotionCap,bool AllowSpeculation)88 LNICMPass(unsigned MssaOptCap, unsigned MssaNoAccForPromotionCap, 89 bool AllowSpeculation) 90 : LNICMPass(LICMOptions(MssaOptCap, MssaNoAccForPromotionCap, 91 AllowSpeculation)) {} LNICMPass(LICMOptions Opts)92 LNICMPass(LICMOptions Opts) : Opts(Opts) {} 93 94 PreservedAnalyses run(LoopNest &L, LoopAnalysisManager &AM, 95 LoopStandardAnalysisResults &AR, LPMUpdater &U); 96 97 void printPipeline(raw_ostream &OS, 98 function_ref<StringRef(StringRef)> MapClassName2PassName); 99 }; 100 } // end namespace llvm 101 102 #endif // LLVM_TRANSFORMS_SCALAR_LICM_H 103