llvm.org GIT mirror llvm / 3a6d437
[PM] Port SpeculativeExecution to the new PM Differential Revision: https://reviews.llvm.org/D23033 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277393 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Kuperstein 3 years ago
7 changed file(s) with 158 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
312312 void initializeSinkingLegacyPassPass(PassRegistry&);
313313 void initializeSjLjEHPreparePass(PassRegistry&);
314314 void initializeSlotIndexesPass(PassRegistry&);
315 void initializeSpeculativeExecutionPass(PassRegistry&);
315 void initializeSpeculativeExecutionLegacyPassPass(PassRegistry&);
316316 void initializeSpillPlacementPass(PassRegistry&);
317317 void initializeStackColoringPass(PassRegistry&);
318318 void initializeStackMapLivenessPass(PassRegistry&);
0 //===- SpeculativeExecution.h -----------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass hoists instructions to enable speculative execution on
10 // targets where branches are expensive. This is aimed at GPUs. It
11 // currently works on simple if-then and if-then-else
12 // patterns.
13 //
14 // Removing branches is not the only motivation for this
15 // pass. E.g. consider this code and assume that there is no
16 // addressing mode for multiplying by sizeof(*a):
17 //
18 // if (b > 0)
19 // c = a[i + 1]
20 // if (d > 0)
21 // e = a[i + 2]
22 //
23 // turns into
24 //
25 // p = &a[i + 1];
26 // if (b > 0)
27 // c = *p;
28 // q = &a[i + 2];
29 // if (d > 0)
30 // e = *q;
31 //
32 // which could later be optimized to
33 //
34 // r = &a[i];
35 // if (b > 0)
36 // c = r[1];
37 // if (d > 0)
38 // e = r[2];
39 //
40 // Later passes sink back much of the speculated code that did not enable
41 // further optimization.
42 //
43 // This pass is more aggressive than the function SpeculativeyExecuteBB in
44 // SimplifyCFG. SimplifyCFG will not speculate if no selects are introduced and
45 // it will speculate at most one instruction. It also will not speculate if
46 // there is a value defined in the if-block that is only used in the then-block.
47 // These restrictions make sense since the speculation in SimplifyCFG seems
48 // aimed at introducing cheap selects, while this pass is intended to do more
49 // aggressive speculation while counting on later passes to either capitalize on
50 // that or clean it up.
51 //
52 // If the pass was created by calling
53 // createSpeculativeExecutionIfHasBranchDivergencePass or the
54 // -spec-exec-only-if-divergent-target option is present, this pass only has an
55 // effect on targets where TargetTransformInfo::hasBranchDivergence() is true;
56 // on other targets, it is a nop.
57 //
58 // This lets you include this pass unconditionally in the IR pass pipeline, but
59 // only enable it for relevant targets.
60 //
61 //===----------------------------------------------------------------------===//
62 #ifndef LLVM_TRANSFORMS_SCALAR_SPECULATIVEEXECUTION_H
63 #define LLVM_TRANSFORMS_SCALAR_SPECULATIVEEXECUTION_H
64
65 #include "llvm/Analysis/TargetTransformInfo.h"
66 #include "llvm/IR/PassManager.h"
67
68 namespace llvm {
69 class SpeculativeExecutionPass
70 : public PassInfoMixin {
71 public:
72 SpeculativeExecutionPass(bool OnlyIfDivergentTarget = false);
73
74 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
75
76 // Glue for old PM
77 bool runImpl(Function &F, TargetTransformInfo *TTI);
78
79 private:
80 bool runOnBasicBlock(BasicBlock &B);
81 bool considerHoistingFromTo(BasicBlock &FromBlock, BasicBlock &ToBlock);
82
83 // If true, this pass is a nop unless the target architecture has branch
84 // divergence.
85 const bool OnlyIfDivergentTarget = false;
86
87 TargetTransformInfo *TTI = nullptr;
88 };
89 }
90
91 #endif //LLVM_TRANSFORMS_SCALAR_SPECULATIVEEXECUTION_H
111111 #include "llvm/Transforms/Scalar/SROA.h"
112112 #include "llvm/Transforms/Scalar/SimplifyCFG.h"
113113 #include "llvm/Transforms/Scalar/Sink.h"
114 #include "llvm/Transforms/Scalar/SpeculativeExecution.h"
114115 #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
115116 #include "llvm/Transforms/Utils/AddDiscriminators.h"
116117 #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
174174 FUNCTION_PASS("simplify-cfg", SimplifyCFGPass())
175175 FUNCTION_PASS("sink", SinkingPass())
176176 FUNCTION_PASS("slp-vectorizer", SLPVectorizerPass())
177 FUNCTION_PASS("speculative-execution", SpeculativeExecutionPass())
177178 FUNCTION_PASS("sroa", SROA())
178179 FUNCTION_PASS("tailcallelim", TailCallElimPass())
179180 FUNCTION_PASS("unreachableblockelim", UnreachableBlockElimPass())
7979 initializeSinkingLegacyPassPass(Registry);
8080 initializeTailCallElimPass(Registry);
8181 initializeSeparateConstOffsetFromGEPPass(Registry);
82 initializeSpeculativeExecutionPass(Registry);
82 initializeSpeculativeExecutionLegacyPassPass(Registry);
8383 initializeStraightLineStrengthReducePass(Registry);
8484 initializeLoadCombinePass(Registry);
8585 initializePlaceBackedgeSafepointsImplPass(Registry);
6060 //
6161 //===----------------------------------------------------------------------===//
6262
63 #include "llvm/Transforms/Scalar/SpeculativeExecution.h"
6364 #include "llvm/ADT/SmallSet.h"
6465 #include "llvm/Analysis/GlobalsModRef.h"
65 #include "llvm/Analysis/TargetTransformInfo.h"
6666 #include "llvm/Analysis/ValueTracking.h"
6767 #include "llvm/IR/Instructions.h"
6868 #include "llvm/IR/Module.h"
100100
101101 namespace {
102102
103 class SpeculativeExecution : public FunctionPass {
104 public:
105 static char ID;
106 explicit SpeculativeExecution(bool OnlyIfDivergentTarget = false)
107 : FunctionPass(ID),
108 OnlyIfDivergentTarget(OnlyIfDivergentTarget ||
109 SpecExecOnlyIfDivergentTarget) {}
110
111 void getAnalysisUsage(AnalysisUsage &AU) const override;
112 bool runOnFunction(Function &F) override;
113
114 const char *getPassName() const override {
115 if (OnlyIfDivergentTarget)
116 return "Speculatively execute instructions if target has divergent "
117 "branches";
118 return "Speculatively execute instructions";
119 }
120
121 private:
122 bool runOnBasicBlock(BasicBlock &B);
123 bool considerHoistingFromTo(BasicBlock &FromBlock, BasicBlock &ToBlock);
124
125 // If true, this pass is a nop unless the target architecture has branch
126 // divergence.
103 class SpeculativeExecutionLegacyPass : public FunctionPass {
104 public:
105 static char ID;
106 explicit SpeculativeExecutionLegacyPass(bool OnlyIfDivergentTarget = false)
107 : FunctionPass(ID), OnlyIfDivergentTarget(OnlyIfDivergentTarget ||
108 SpecExecOnlyIfDivergentTarget),
109 Impl(OnlyIfDivergentTarget) {}
110
111 void getAnalysisUsage(AnalysisUsage &AU) const override;
112 bool runOnFunction(Function &F) override;
113
114 const char *getPassName() const override {
115 if (OnlyIfDivergentTarget)
116 return "Speculatively execute instructions if target has divergent "
117 "branches";
118 return "Speculatively execute instructions";
119 }
120
121 private:
122 // Variable preserved purely for correct name printing.
127123 const bool OnlyIfDivergentTarget;
128 const TargetTransformInfo *TTI = nullptr;
124
125 SpeculativeExecutionPass Impl;
129126 };
130127 } // namespace
131128
132 char SpeculativeExecution::ID = 0;
133 INITIALIZE_PASS_BEGIN(SpeculativeExecution, "speculative-execution",
129 char SpeculativeExecutionLegacyPass::ID = 0;
130 INITIALIZE_PASS_BEGIN(SpeculativeExecutionLegacyPass, "speculative-execution",
134131 "Speculatively execute instructions", false, false)
135132 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
136 INITIALIZE_PASS_END(SpeculativeExecution, "speculative-execution",
133 INITIALIZE_PASS_END(SpeculativeExecutionLegacyPass, "speculative-execution",
137134 "Speculatively execute instructions", false, false)
138135
139 void SpeculativeExecution::getAnalysisUsage(AnalysisUsage &AU) const {
136 void SpeculativeExecutionLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
140137 AU.addRequired();
141138 AU.addPreserved();
142139 }
143140
144 bool SpeculativeExecution::runOnFunction(Function &F) {
141 bool SpeculativeExecutionLegacyPass::runOnFunction(Function &F) {
145142 if (skipFunction(F))
146143 return false;
147144
148 TTI = &getAnalysis().getTTI(F);
145 auto *TTI = &getAnalysis().getTTI(F);
146 return Impl.runImpl(F, TTI);
147 }
148
149 namespace llvm {
150
151 bool SpeculativeExecutionPass::runImpl(Function &F, TargetTransformInfo *TTI) {
149152 if (OnlyIfDivergentTarget && !TTI->hasBranchDivergence()) {
150153 DEBUG(dbgs() << "Not running SpeculativeExecution because "
151154 "TTI->hasBranchDivergence() is false.\n");
152155 return false;
153156 }
154157
158 this->TTI = TTI;
155159 bool Changed = false;
156160 for (auto& B : F) {
157161 Changed |= runOnBasicBlock(B);
159163 return Changed;
160164 }
161165
162 bool SpeculativeExecution::runOnBasicBlock(BasicBlock &B) {
166 bool SpeculativeExecutionPass::runOnBasicBlock(BasicBlock &B) {
163167 BranchInst *BI = dyn_cast(B.getTerminator());
164168 if (BI == nullptr)
165169 return false;
226230 }
227231 }
228232
229 bool SpeculativeExecution::considerHoistingFromTo(BasicBlock &FromBlock,
230 BasicBlock &ToBlock) {
233 bool SpeculativeExecutionPass::considerHoistingFromTo(
234 BasicBlock &FromBlock, BasicBlock &ToBlock) {
231235 SmallSet NotHoisted;
232236 const auto AllPrecedingUsesFromBlockHoisted = [&NotHoisted](User *U) {
233237 for (Value* V : U->operand_values()) {
269273 return true;
270274 }
271275
272 namespace llvm {
273
274276 FunctionPass *createSpeculativeExecutionPass() {
275 return new SpeculativeExecution();
277 return new SpeculativeExecutionLegacyPass();
276278 }
277279
278280 FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass() {
279 return new SpeculativeExecution(/* OnlyIfDivergentTarget = */ true);
280 }
281
281 return new SpeculativeExecutionLegacyPass(/* OnlyIfDivergentTarget = */ true);
282 }
283
284 SpeculativeExecutionPass::SpeculativeExecutionPass(bool OnlyIfDivergentTarget)
285 : OnlyIfDivergentTarget(OnlyIfDivergentTarget ||
286 SpecExecOnlyIfDivergentTarget) {}
287
288 PreservedAnalyses SpeculativeExecutionPass::run(Function &F,
289 FunctionAnalysisManager &AM) {
290 auto *TTI = &AM.getResult(F);
291
292 bool Changed = runImpl(F, TTI);
293
294 if (!Changed)
295 return PreservedAnalyses::all();
296 PreservedAnalyses PA;
297 PA.preserve();
298 return PA;
299 }
282300 } // namespace llvm
0 ; RUN: opt < %s -S -speculative-execution \
1 ; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
2 ; RUN: | FileCheck %s
3 ; RUN: opt < %s -S -passes='speculative-execution' \
14 ; RUN: -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
25 ; RUN: | FileCheck %s
36