1 //===- DeadCodeElimination.cpp - Eliminate dead iteration ----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // The polyhedral dead code elimination pass analyses a SCoP to eliminate 11 // statement instances that can be proven dead. 12 // As a consequence, the code generated for this SCoP may execute a statement 13 // less often. This means, a statement may be executed only in certain loop 14 // iterations or it may not even be part of the generated code at all. 15 // 16 // This code: 17 // 18 // for (i = 0; i < N; i++) 19 // arr[i] = 0; 20 // for (i = 0; i < N; i++) 21 // arr[i] = 10; 22 // for (i = 0; i < N; i++) 23 // arr[i] = i; 24 // 25 // is e.g. simplified to: 26 // 27 // for (i = 0; i < N; i++) 28 // arr[i] = i; 29 // 30 // The idea and the algorithm used was first implemented by Sven Verdoolaege in 31 // the 'ppcg' tool. 32 // 33 //===----------------------------------------------------------------------===// 34 35 #include "polly/DependenceInfo.h" 36 #include "polly/LinkAllPasses.h" 37 #include "polly/Options.h" 38 #include "polly/ScopInfo.h" 39 #include "llvm/Support/CommandLine.h" 40 #include "isl/flow.h" 41 #include "isl/isl-noexceptions.h" 42 #include "isl/map.h" 43 #include "isl/set.h" 44 #include "isl/union_map.h" 45 #include "isl/union_set.h" 46 47 using namespace llvm; 48 using namespace polly; 49 50 namespace { 51 52 cl::opt<int> DCEPreciseSteps( 53 "polly-dce-precise-steps", 54 cl::desc("The number of precise steps between two approximating " 55 "iterations. (A value of -1 schedules another approximation stage " 56 "before the actual dead code elimination."), 57 cl::ZeroOrMore, cl::init(-1), cl::cat(PollyCategory)); 58 59 class DeadCodeElim : public ScopPass { 60 public: 61 static char ID; 62 explicit DeadCodeElim() : ScopPass(ID) {} 63 64 /// Remove dead iterations from the schedule of @p S. 65 bool runOnScop(Scop &S) override; 66 67 /// Register all analyses and transformation required. 68 void getAnalysisUsage(AnalysisUsage &AU) const override; 69 70 private: 71 /// Return the set of live iterations. 72 /// 73 /// The set of live iterations are all iterations that write to memory and for 74 /// which we can not prove that there will be a later write that _must_ 75 /// overwrite the same memory location and is consequently the only one that 76 /// is visible after the execution of the SCoP. 77 /// 78 isl::union_set getLiveOut(Scop &S); 79 bool eliminateDeadCode(Scop &S, int PreciseSteps); 80 }; 81 } // namespace 82 83 char DeadCodeElim::ID = 0; 84 85 // To compute the live outs, we compute for the data-locations that are 86 // must-written to the last statement that touches these locations. On top of 87 // this we add all statements that perform may-write accesses. 88 // 89 // We could be more precise by removing may-write accesses for which we know 90 // that they are overwritten by a must-write after. However, at the moment the 91 // only may-writes we introduce access the full (unbounded) array, such that 92 // bounded write accesses can not overwrite all of the data-locations. As 93 // this means may-writes are in the current situation always live, there is 94 // no point in trying to remove them from the live-out set. 95 isl::union_set DeadCodeElim::getLiveOut(Scop &S) { 96 isl::union_map Schedule = S.getSchedule(); 97 isl::union_map MustWrites = S.getMustWrites(); 98 isl::union_map WriteIterations = MustWrites.reverse(); 99 isl::union_map WriteTimes = WriteIterations.apply_range(Schedule); 100 101 isl::union_map LastWriteTimes = WriteTimes.lexmax(); 102 isl::union_map LastWriteIterations = 103 LastWriteTimes.apply_range(Schedule.reverse()); 104 105 isl::union_set Live = LastWriteIterations.range(); 106 isl::union_map MayWrites = S.getMayWrites(); 107 Live = Live.unite(MayWrites.domain()); 108 return Live.coalesce(); 109 } 110 111 /// Performs polyhedral dead iteration elimination by: 112 /// o Assuming that the last write to each location is live. 113 /// o Following each RAW dependency from a live iteration backwards and adding 114 /// that iteration to the live set. 115 /// 116 /// To ensure the set of live iterations does not get too complex we always 117 /// combine a certain number of precise steps with one approximating step that 118 /// simplifies the life set with an affine hull. 119 bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) { 120 DependenceInfo &DI = getAnalysis<DependenceInfo>(); 121 const Dependences &D = DI.getDependences(Dependences::AL_Statement); 122 123 if (!D.hasValidDependences()) 124 return false; 125 126 isl::union_set Live = getLiveOut(S); 127 isl::union_map Dep = isl::manage( 128 D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED)); 129 Dep = Dep.reverse(); 130 131 if (PreciseSteps == -1) 132 Live = Live.affine_hull(); 133 134 isl::union_set OriginalDomain = S.getDomains(); 135 int Steps = 0; 136 while (true) { 137 Steps++; 138 139 isl::union_set Extra = Live.apply(Dep); 140 141 if (Extra.is_subset(Live)) 142 break; 143 144 Live = Live.unite(Extra); 145 146 if (Steps > PreciseSteps) { 147 Steps = 0; 148 Live = Live.affine_hull(); 149 } 150 151 Live = Live.intersect(OriginalDomain); 152 } 153 154 Live = Live.coalesce(); 155 156 bool Changed = S.restrictDomains(Live); 157 158 // FIXME: We can probably avoid the recomputation of all dependences by 159 // updating them explicitly. 160 if (Changed) 161 DI.recomputeDependences(Dependences::AL_Statement); 162 return Changed; 163 } 164 165 bool DeadCodeElim::runOnScop(Scop &S) { 166 return eliminateDeadCode(S, DCEPreciseSteps); 167 } 168 169 void DeadCodeElim::getAnalysisUsage(AnalysisUsage &AU) const { 170 ScopPass::getAnalysisUsage(AU); 171 AU.addRequired<DependenceInfo>(); 172 } 173 174 Pass *polly::createDeadCodeElimPass() { return new DeadCodeElim(); } 175 176 INITIALIZE_PASS_BEGIN(DeadCodeElim, "polly-dce", 177 "Polly - Remove dead iterations", false, false) 178 INITIALIZE_PASS_DEPENDENCY(DependenceInfo) 179 INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass) 180 INITIALIZE_PASS_END(DeadCodeElim, "polly-dce", "Polly - Remove dead iterations", 181 false, false) 182