blob: 1d5ccbe5e6c9426c18718688ad5a686e9460d3be [file] [log] [blame]
Tobias Grosser1d348672012-01-31 14:00:27 +00001//===- 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//
Tobias Grosserecae17f2014-02-21 20:51:40 +000010// 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.
Tobias Grosserc30d9cc2013-03-23 00:16:05 +000015//
Tobias Grosserecae17f2014-02-21 20:51:40 +000016// This code:
Tobias Grosserc30d9cc2013-03-23 00:16:05 +000017//
Tobias Grosserecae17f2014-02-21 20:51:40 +000018// 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.
Tobias Grosserc30d9cc2013-03-23 00:16:05 +000032//
Tobias Grosser1d348672012-01-31 14:00:27 +000033//===----------------------------------------------------------------------===//
34
Johannes Doerfertf6557f92015-03-04 22:43:40 +000035#include "polly/DependenceInfo.h"
Tobias Grosser1d348672012-01-31 14:00:27 +000036#include "polly/LinkAllPasses.h"
37#include "polly/ScopInfo.h"
Tobias Grosser37eb4222014-02-20 21:43:54 +000038#include "llvm/Support/CommandLine.h"
Tobias Grosser780ce0f2014-07-11 07:12:10 +000039#include "isl/flow.h"
Tobias Grosser37eb4222014-02-20 21:43:54 +000040#include "isl/map.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000041#include "isl/set.h"
Tobias Grosser37eb4222014-02-20 21:43:54 +000042#include "isl/union_map.h"
Tobias Grossercd524dc2015-05-09 09:36:38 +000043#include "isl/union_set.h"
Tobias Grosser1d348672012-01-31 14:00:27 +000044
Tobias Grosser1d348672012-01-31 14:00:27 +000045using namespace llvm;
46using namespace polly;
47
48namespace {
Tobias Grosser37eb4222014-02-20 21:43:54 +000049
Tobias Grosser817d51d2014-02-21 20:51:46 +000050cl::opt<int> DCEPreciseSteps(
51 "polly-dce-precise-steps",
Tobias Grosser356faa82014-02-24 08:52:20 +000052 cl::desc("The number of precise steps between two approximating "
53 "iterations. (A value of -1 schedules another approximation stage "
54 "before the actual dead code elimination."),
Tobias Grosser64e8e372014-03-13 23:37:43 +000055 cl::ZeroOrMore, cl::init(-1));
Tobias Grosser1d348672012-01-31 14:00:27 +000056
Tobias Grosser184e2fc2013-01-08 08:27:46 +000057class DeadCodeElim : public ScopPass {
Tobias Grosser184e2fc2013-01-08 08:27:46 +000058public:
59 static char ID;
Tobias Grosserc30d9cc2013-03-23 00:16:05 +000060 explicit DeadCodeElim() : ScopPass(ID) {}
Tobias Grosser1d348672012-01-31 14:00:27 +000061
Johannes Doerfert909a3bf2015-03-01 18:42:08 +000062 bool runOnScop(Scop &S) override;
Tobias Grosser37eb4222014-02-20 21:43:54 +000063
Johannes Doerfert909a3bf2015-03-01 18:42:08 +000064 void printScop(raw_ostream &OS, Scop &S) const override;
65 void getAnalysisUsage(AnalysisUsage &AU) const override;
Tobias Grosser37eb4222014-02-20 21:43:54 +000066
67private:
Tobias Grosser780ce0f2014-07-11 07:12:10 +000068 /// @brief Return the set of live iterations.
69 ///
70 /// The set of live iterations are all iterations that write to memory and for
71 /// which we can not prove that there will be a later write that _must_
72 /// overwrite the same memory location and is consequently the only one that
73 /// is visible after the execution of the SCoP.
74 ///
75 isl_union_set *getLiveOut(Scop &S);
Tobias Grosser817d51d2014-02-21 20:51:46 +000076 bool eliminateDeadCode(Scop &S, int PreciseSteps);
Tobias Grosser184e2fc2013-01-08 08:27:46 +000077};
Tobias Grosser1d348672012-01-31 14:00:27 +000078}
79
80char DeadCodeElim::ID = 0;
81
Tobias Grosserc2920ff2014-07-14 08:32:01 +000082// To compute the live outs, we compute for the data-locations that are
83// must-written to the last statement that touches these locations. On top of
84// this we add all statements that perform may-write accesses.
85//
86// We could be more precise by removing may-write accesses for which we know
87// that they are overwritten by a must-write after. However, at the moment the
88// only may-writes we introduce access the full (unbounded) array, such that
89// bounded write accesses can not overwrite all of the data-locations. As
90// this means may-writes are in the current situation always live, there is
91// no point in trying to remove them from the live-out set.
Tobias Grosser780ce0f2014-07-11 07:12:10 +000092isl_union_set *DeadCodeElim::getLiveOut(Scop &S) {
Tobias Grosserc2920ff2014-07-14 08:32:01 +000093 isl_union_map *Schedule = S.getSchedule();
94 isl_union_map *WriteIterations = isl_union_map_reverse(S.getMustWrites());
95 isl_union_map *WriteTimes =
96 isl_union_map_apply_range(WriteIterations, isl_union_map_copy(Schedule));
Tobias Grosser1d348672012-01-31 14:00:27 +000097
Tobias Grosserc2920ff2014-07-14 08:32:01 +000098 isl_union_map *LastWriteTimes = isl_union_map_lexmax(WriteTimes);
99 isl_union_map *LastWriteIterations = isl_union_map_apply_range(
100 LastWriteTimes, isl_union_map_reverse(Schedule));
Tobias Grosser1d348672012-01-31 14:00:27 +0000101
Tobias Grosserc2920ff2014-07-14 08:32:01 +0000102 isl_union_set *Live = isl_union_map_range(LastWriteIterations);
103 Live = isl_union_set_union(Live, isl_union_map_domain(S.getMayWrites()));
104 return isl_union_set_coalesce(Live);
Tobias Grosser1d348672012-01-31 14:00:27 +0000105}
106
Tobias Grosser37eb4222014-02-20 21:43:54 +0000107/// Performs polyhedral dead iteration elimination by:
108/// o Assuming that the last write to each location is live.
109/// o Following each RAW dependency from a live iteration backwards and adding
110/// that iteration to the live set.
Tobias Grosser817d51d2014-02-21 20:51:46 +0000111///
112/// To ensure the set of live iterations does not get too complex we always
113/// combine a certain number of precise steps with one approximating step that
114/// simplifies the life set with an affine hull.
115bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) {
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000116 DependenceInfo &DI = getAnalysis<DependenceInfo>();
117 const Dependences &D = DI.getDependences();
Tobias Grosser38c36ea2014-02-23 15:15:44 +0000118
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000119 if (!D.hasValidDependences())
Tobias Grosser38c36ea2014-02-23 15:15:44 +0000120 return false;
121
Tobias Grosser780ce0f2014-07-11 07:12:10 +0000122 isl_union_set *Live = getLiveOut(S);
Johannes Doerfertf1906132014-06-20 16:37:11 +0000123 isl_union_map *Dep =
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000124 D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);
Tobias Grosser37eb4222014-02-20 21:43:54 +0000125 Dep = isl_union_map_reverse(Dep);
126
Tobias Grosser356faa82014-02-24 08:52:20 +0000127 if (PreciseSteps == -1)
128 Live = isl_union_set_affine_hull(Live);
129
Tobias Grosser37eb4222014-02-20 21:43:54 +0000130 isl_union_set *OriginalDomain = S.getDomains();
Tobias Grosser817d51d2014-02-21 20:51:46 +0000131 int Steps = 0;
Tobias Grosser0bc0ad02014-02-21 21:06:08 +0000132 while (true) {
Tobias Grosser37eb4222014-02-20 21:43:54 +0000133 isl_union_set *Extra;
Tobias Grosser817d51d2014-02-21 20:51:46 +0000134 Steps++;
Tobias Grosser37eb4222014-02-20 21:43:54 +0000135
136 Extra =
137 isl_union_set_apply(isl_union_set_copy(Live), isl_union_map_copy(Dep));
138
139 if (isl_union_set_is_subset(Extra, Live)) {
140 isl_union_set_free(Extra);
141 break;
142 }
143
144 Live = isl_union_set_union(Live, Extra);
Tobias Grosser817d51d2014-02-21 20:51:46 +0000145
146 if (Steps > PreciseSteps) {
147 Steps = 0;
Tobias Grosser37eb4222014-02-20 21:43:54 +0000148 Live = isl_union_set_affine_hull(Live);
Tobias Grosser817d51d2014-02-21 20:51:46 +0000149 }
150
Tobias Grosser37eb4222014-02-20 21:43:54 +0000151 Live = isl_union_set_intersect(Live, isl_union_set_copy(OriginalDomain));
152 }
153 isl_union_map_free(Dep);
154 isl_union_set_free(OriginalDomain);
155
Tobias Grosser11e38732014-12-17 21:13:55 +0000156 bool Changed = S.restrictDomains(isl_union_set_coalesce(Live));
157
158 // FIXME: We can probably avoid the recomputation of all dependences by
159 // updating them explicitly.
160 if (Changed)
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000161 DI.recomputeDependences();
Tobias Grosser11e38732014-12-17 21:13:55 +0000162 return Changed;
Tobias Grosser37eb4222014-02-20 21:43:54 +0000163}
164
Tobias Grosser817d51d2014-02-21 20:51:46 +0000165bool DeadCodeElim::runOnScop(Scop &S) {
166 return eliminateDeadCode(S, DCEPreciseSteps);
167}
Tobias Grosser37eb4222014-02-20 21:43:54 +0000168
Johannes Doerfert3fe584d2015-03-01 18:40:25 +0000169void DeadCodeElim::printScop(raw_ostream &, Scop &) const {}
Tobias Grosser1d348672012-01-31 14:00:27 +0000170
171void DeadCodeElim::getAnalysisUsage(AnalysisUsage &AU) const {
172 ScopPass::getAnalysisUsage(AU);
Johannes Doerfertf6557f92015-03-04 22:43:40 +0000173 AU.addRequired<DependenceInfo>();
Tobias Grosser1d348672012-01-31 14:00:27 +0000174}
175
Tobias Grosserc30d9cc2013-03-23 00:16:05 +0000176Pass *polly::createDeadCodeElimPass() { return new DeadCodeElim(); }
Tobias Grosser1d348672012-01-31 14:00:27 +0000177
Tobias Grosserc30d9cc2013-03-23 00:16:05 +0000178INITIALIZE_PASS_BEGIN(DeadCodeElim, "polly-dce",
Tobias Grosserd7e58642013-04-10 06:55:45 +0000179 "Polly - Remove dead iterations", false, false)
Johannes Doerfertf6557f92015-03-04 22:43:40 +0000180INITIALIZE_PASS_DEPENDENCY(DependenceInfo)
Tobias Grosserd7e58642013-04-10 06:55:45 +0000181INITIALIZE_PASS_DEPENDENCY(ScopInfo)
Tobias Grosserc30d9cc2013-03-23 00:16:05 +0000182INITIALIZE_PASS_END(DeadCodeElim, "polly-dce", "Polly - Remove dead iterations",
183 false, false)