blob: f8374d693aa58bc367e5c67a8cc7b7149780ddc0 [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 Doerfert45be6442015-09-27 15:43:29 +000062 /// @brief Remove dead iterations from the schedule of @p S.
Johannes Doerfert909a3bf2015-03-01 18:42:08 +000063 bool runOnScop(Scop &S) override;
Tobias Grosser37eb4222014-02-20 21:43:54 +000064
Johannes Doerfert45be6442015-09-27 15:43:29 +000065 /// @brief Register all analyses and transformation required.
Johannes Doerfert909a3bf2015-03-01 18:42:08 +000066 void getAnalysisUsage(AnalysisUsage &AU) const override;
Tobias Grosser37eb4222014-02-20 21:43:54 +000067
68private:
Tobias Grosser780ce0f2014-07-11 07:12:10 +000069 /// @brief Return the set of live iterations.
70 ///
71 /// The set of live iterations are all iterations that write to memory and for
72 /// which we can not prove that there will be a later write that _must_
73 /// overwrite the same memory location and is consequently the only one that
74 /// is visible after the execution of the SCoP.
75 ///
76 isl_union_set *getLiveOut(Scop &S);
Tobias Grosser817d51d2014-02-21 20:51:46 +000077 bool eliminateDeadCode(Scop &S, int PreciseSteps);
Tobias Grosser184e2fc2013-01-08 08:27:46 +000078};
Tobias Grosser1d348672012-01-31 14:00:27 +000079}
80
81char DeadCodeElim::ID = 0;
82
Tobias Grosserc2920ff2014-07-14 08:32:01 +000083// To compute the live outs, we compute for the data-locations that are
84// must-written to the last statement that touches these locations. On top of
85// this we add all statements that perform may-write accesses.
86//
87// We could be more precise by removing may-write accesses for which we know
88// that they are overwritten by a must-write after. However, at the moment the
89// only may-writes we introduce access the full (unbounded) array, such that
90// bounded write accesses can not overwrite all of the data-locations. As
91// this means may-writes are in the current situation always live, there is
92// no point in trying to remove them from the live-out set.
Tobias Grosser780ce0f2014-07-11 07:12:10 +000093isl_union_set *DeadCodeElim::getLiveOut(Scop &S) {
Tobias Grosserc2920ff2014-07-14 08:32:01 +000094 isl_union_map *Schedule = S.getSchedule();
95 isl_union_map *WriteIterations = isl_union_map_reverse(S.getMustWrites());
96 isl_union_map *WriteTimes =
97 isl_union_map_apply_range(WriteIterations, isl_union_map_copy(Schedule));
Tobias Grosser1d348672012-01-31 14:00:27 +000098
Tobias Grosserc2920ff2014-07-14 08:32:01 +000099 isl_union_map *LastWriteTimes = isl_union_map_lexmax(WriteTimes);
100 isl_union_map *LastWriteIterations = isl_union_map_apply_range(
101 LastWriteTimes, isl_union_map_reverse(Schedule));
Tobias Grosser1d348672012-01-31 14:00:27 +0000102
Tobias Grosserc2920ff2014-07-14 08:32:01 +0000103 isl_union_set *Live = isl_union_map_range(LastWriteIterations);
104 Live = isl_union_set_union(Live, isl_union_map_domain(S.getMayWrites()));
105 return isl_union_set_coalesce(Live);
Tobias Grosser1d348672012-01-31 14:00:27 +0000106}
107
Tobias Grosser37eb4222014-02-20 21:43:54 +0000108/// Performs polyhedral dead iteration elimination by:
109/// o Assuming that the last write to each location is live.
110/// o Following each RAW dependency from a live iteration backwards and adding
111/// that iteration to the live set.
Tobias Grosser817d51d2014-02-21 20:51:46 +0000112///
113/// To ensure the set of live iterations does not get too complex we always
114/// combine a certain number of precise steps with one approximating step that
115/// simplifies the life set with an affine hull.
116bool DeadCodeElim::eliminateDeadCode(Scop &S, int PreciseSteps) {
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000117 DependenceInfo &DI = getAnalysis<DependenceInfo>();
118 const Dependences &D = DI.getDependences();
Tobias Grosser38c36ea2014-02-23 15:15:44 +0000119
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000120 if (!D.hasValidDependences())
Tobias Grosser38c36ea2014-02-23 15:15:44 +0000121 return false;
122
Tobias Grosser780ce0f2014-07-11 07:12:10 +0000123 isl_union_set *Live = getLiveOut(S);
Johannes Doerfertf1906132014-06-20 16:37:11 +0000124 isl_union_map *Dep =
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000125 D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);
Tobias Grosser37eb4222014-02-20 21:43:54 +0000126 Dep = isl_union_map_reverse(Dep);
127
Tobias Grosser356faa82014-02-24 08:52:20 +0000128 if (PreciseSteps == -1)
129 Live = isl_union_set_affine_hull(Live);
130
Tobias Grosser37eb4222014-02-20 21:43:54 +0000131 isl_union_set *OriginalDomain = S.getDomains();
Tobias Grosser817d51d2014-02-21 20:51:46 +0000132 int Steps = 0;
Tobias Grosser0bc0ad02014-02-21 21:06:08 +0000133 while (true) {
Tobias Grosser37eb4222014-02-20 21:43:54 +0000134 isl_union_set *Extra;
Tobias Grosser817d51d2014-02-21 20:51:46 +0000135 Steps++;
Tobias Grosser37eb4222014-02-20 21:43:54 +0000136
137 Extra =
138 isl_union_set_apply(isl_union_set_copy(Live), isl_union_map_copy(Dep));
139
140 if (isl_union_set_is_subset(Extra, Live)) {
141 isl_union_set_free(Extra);
142 break;
143 }
144
145 Live = isl_union_set_union(Live, Extra);
Tobias Grosser817d51d2014-02-21 20:51:46 +0000146
147 if (Steps > PreciseSteps) {
148 Steps = 0;
Tobias Grosser37eb4222014-02-20 21:43:54 +0000149 Live = isl_union_set_affine_hull(Live);
Tobias Grosser817d51d2014-02-21 20:51:46 +0000150 }
151
Tobias Grosser37eb4222014-02-20 21:43:54 +0000152 Live = isl_union_set_intersect(Live, isl_union_set_copy(OriginalDomain));
153 }
154 isl_union_map_free(Dep);
155 isl_union_set_free(OriginalDomain);
156
Tobias Grosser11e38732014-12-17 21:13:55 +0000157 bool Changed = S.restrictDomains(isl_union_set_coalesce(Live));
158
159 // FIXME: We can probably avoid the recomputation of all dependences by
160 // updating them explicitly.
161 if (Changed)
Johannes Doerfert7e6424b2015-03-05 00:43:48 +0000162 DI.recomputeDependences();
Tobias Grosser11e38732014-12-17 21:13:55 +0000163 return Changed;
Tobias Grosser37eb4222014-02-20 21:43:54 +0000164}
165
Tobias Grosser817d51d2014-02-21 20:51:46 +0000166bool DeadCodeElim::runOnScop(Scop &S) {
167 return eliminateDeadCode(S, DCEPreciseSteps);
168}
Tobias Grosser37eb4222014-02-20 21:43:54 +0000169
Tobias Grosser1d348672012-01-31 14:00:27 +0000170void DeadCodeElim::getAnalysisUsage(AnalysisUsage &AU) const {
171 ScopPass::getAnalysisUsage(AU);
Johannes Doerfertf6557f92015-03-04 22:43:40 +0000172 AU.addRequired<DependenceInfo>();
Tobias Grosser1d348672012-01-31 14:00:27 +0000173}
174
Tobias Grosserc30d9cc2013-03-23 00:16:05 +0000175Pass *polly::createDeadCodeElimPass() { return new DeadCodeElim(); }
Tobias Grosser1d348672012-01-31 14:00:27 +0000176
Tobias Grosserc30d9cc2013-03-23 00:16:05 +0000177INITIALIZE_PASS_BEGIN(DeadCodeElim, "polly-dce",
Tobias Grosserd7e58642013-04-10 06:55:45 +0000178 "Polly - Remove dead iterations", false, false)
Johannes Doerfertf6557f92015-03-04 22:43:40 +0000179INITIALIZE_PASS_DEPENDENCY(DependenceInfo)
Tobias Grosserd7e58642013-04-10 06:55:45 +0000180INITIALIZE_PASS_DEPENDENCY(ScopInfo)
Tobias Grosserc30d9cc2013-03-23 00:16:05 +0000181INITIALIZE_PASS_END(DeadCodeElim, "polly-dce", "Polly - Remove dead iterations",
182 false, false)