@@ -9,7 +9,10 @@ SPDX-License-Identifier: MIT
9
9
#include " Compiler/CISACodeGen/PromoteConstantStructs.hpp"
10
10
#include " common/LLVMWarningsPush.hpp"
11
11
#include " llvm/Analysis/MemoryDependenceAnalysis.h"
12
+ #include " llvm/Analysis/LoopInfo.h"
13
+ #include " llvm/ADT/SetVector.h"
12
14
#include " llvm/Analysis/PtrUseVisitor.h"
15
+ #include " llvm/Analysis/CFG.h"
13
16
#include " common/LLVMWarningsPop.hpp"
14
17
15
18
using namespace llvm ;
@@ -28,7 +31,6 @@ namespace {
28
31
// work for large structures. This parameter can not be tweaked inside compiler
29
32
//
30
33
// Restrictions to this implementation to keep it simple and save compile time:
31
- // -- All stores to the structure must be in the same BB
32
34
// -- The structure does not escape
33
35
// -- We promote only constant values of the same type and store->load only
34
36
//
@@ -53,17 +55,19 @@ namespace {
53
55
54
56
MemoryDependenceResults *MD = nullptr ;
55
57
DominatorTree *DT = nullptr ;
58
+ LoopInfo* LPI = nullptr ;
56
59
57
60
void getAnalysisUsage (AnalysisUsage &AU) const override {
58
61
AU.addRequired <DominatorTreeWrapperPass>();
59
62
AU.addRequired <MemoryDependenceWrapperPass>();
63
+ AU.addRequired <LoopInfoWrapperPass>();
60
64
AU.setPreservesCFG ();
61
65
AU.addPreserved <DominatorTreeWrapperPass>();
62
66
}
63
67
64
68
bool processAlloca (AllocaInst &AI);
65
69
66
- bool processLoad (LoadInst *LI, BasicBlock *StoreBB );
70
+ bool processLoad (LoadInst *LI, SetVector< BasicBlock*>& StoreBBs );
67
71
68
72
};
69
73
@@ -86,7 +90,6 @@ IGC_INITIALIZE_PASS_END(PromoteConstantStructs, PASS_FLAG, PASS_DESC, PASS_CFG_O
86
90
87
91
// This class visits all alloca uses to check that
88
92
// -- it does not escape
89
- // -- all stores are in the same BB
90
93
// and collect all loads with constant offsets from alloca
91
94
92
95
class AllocaChecker : public PtrUseVisitor<AllocaChecker> {
@@ -95,28 +98,23 @@ class AllocaChecker : public PtrUseVisitor<AllocaChecker> {
95
98
96
99
public:
97
100
AllocaChecker (const DataLayout &DL)
98
- : PtrUseVisitor<AllocaChecker>(DL), StoreBB ( nullptr ) {}
101
+ : PtrUseVisitor<AllocaChecker>(DL), StoreBBs ( ) {}
99
102
100
103
SmallVector<LoadInst*, 8 >& getPotentialLoads () {
101
104
return Loads;
102
105
}
103
106
104
- BasicBlock * getStoreBB () {
105
- return StoreBB ;
107
+ SetVector< BasicBlock*>& getStoreBBs () {
108
+ return StoreBBs ;
106
109
}
107
110
108
111
private:
109
112
SmallVector<LoadInst*, 8 > Loads;
110
113
111
- BasicBlock *StoreBB ;
114
+ SetVector< BasicBlock*> StoreBBs ;
112
115
113
116
void visitStoreInst (StoreInst &SI) {
114
- if (!StoreBB) {
115
- StoreBB = SI.getParent ();
116
- }
117
- else if (SI.getParent () != StoreBB) {
118
- PI.setAborted (&SI);
119
- }
117
+ StoreBBs.insert (SI.getParent ());
120
118
}
121
119
122
120
void visitLoadInst (LoadInst &LI) {
@@ -126,10 +124,10 @@ class AllocaChecker : public PtrUseVisitor<AllocaChecker> {
126
124
}
127
125
};
128
126
129
- bool PromoteConstantStructs::runOnFunction (Function &F)
130
- {
127
+ bool PromoteConstantStructs::runOnFunction (Function &F) {
131
128
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree ();
132
129
MD = &getAnalysis<MemoryDependenceWrapperPass>().getMemDep ();
130
+ LPI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo ();
133
131
134
132
bool Changed = false ;
135
133
BasicBlock &EntryBB = F.getEntryBlock ();
@@ -142,8 +140,7 @@ bool PromoteConstantStructs::runOnFunction(Function &F)
142
140
return Changed;
143
141
}
144
142
145
- bool PromoteConstantStructs::processAlloca (AllocaInst &AI)
146
- {
143
+ bool PromoteConstantStructs::processAlloca (AllocaInst &AI) {
147
144
// we do not process single or array allocas
148
145
if (!AI.getAllocatedType ()->isStructTy ())
149
146
return false ;
@@ -153,37 +150,67 @@ bool PromoteConstantStructs::processAlloca(AllocaInst &AI)
153
150
if (PtrI.isEscaped () || PtrI.isAborted ())
154
151
return false ;
155
152
156
- BasicBlock *StoreBB = AC.getStoreBB ();
157
153
// if we don't have any stores, nothing to do
158
- if (!StoreBB )
154
+ if (AC. getStoreBBs (). empty () )
159
155
return false ;
160
156
161
157
bool Changed = false ;
162
- for (auto LI : AC.getPotentialLoads ())
163
- Changed |= processLoad (LI, StoreBB);
158
+ bool LocalChanged = true ;
159
+ while (LocalChanged) {
160
+ LocalChanged = false ;
161
+
162
+ auto LII = AC.getPotentialLoads ().begin ();
163
+ while (LII != AC.getPotentialLoads ().end ()) {
164
+ if (processLoad (*LII, AC.getStoreBBs ())) {
165
+ LII = AC.getPotentialLoads ().erase (LII);
166
+ LocalChanged = true ;
167
+ } else {
168
+ ++LII;
169
+ }
170
+ }
171
+ Changed |= LocalChanged;
172
+ }
164
173
165
174
return Changed;
166
175
}
167
176
168
- bool PromoteConstantStructs::processLoad (LoadInst *LI, BasicBlock *StoreBB)
169
- {
170
- if (!DT->dominates (StoreBB->getFirstNonPHI (), LI))
171
- return false ;
177
+ bool PromoteConstantStructs::processLoad (LoadInst *LI, SetVector<BasicBlock*>& StoreBBs) {
178
+ unsigned limit = InstructionsLimit;
179
+ StoreInst* SI = nullptr ;
172
180
173
- Instruction *InstPt = StoreBB->getTerminator ();
174
- if (StoreBB == LI->getParent ()) InstPt = LI;
181
+ auto ML = MemoryLocation::get (LI);
182
+ for (auto StBB : StoreBBs) {
183
+ SmallVector<BasicBlock*, 32 > Worklist;
184
+ Worklist.push_back (StBB);
175
185
176
- unsigned limit = InstructionsLimit;
186
+ if (!isPotentiallyReachableFromMany (Worklist, LI->getParent (), nullptr , DT, LPI))
187
+ continue ;
177
188
178
- MemDepResult Dep = MD->getPointerDependencyFrom (MemoryLocation::get (LI), true ,
179
- InstPt->getIterator (), StoreBB, LI, &limit);
189
+ Instruction* InstPt = StBB->getTerminator ();
190
+ if (StBB == LI->getParent ())
191
+ InstPt = LI;
180
192
181
- // we care only about must aliases, no clobber dependencies
182
- if (!Dep.isDef ())
183
- return false ;
193
+ MemDepResult Dep = MD->getPointerDependencyFrom (ML, true ,
194
+ InstPt->getIterator (), StBB, LI, &limit);
195
+
196
+ if (Dep.isDef ()) {
197
+ // skip if more than one def
198
+ if (SI)
199
+ return false ;
200
+
201
+ // we search only for stores
202
+ SI = dyn_cast<StoreInst>(Dep.getInst ());
203
+ if (!SI)
204
+ return false ;
205
+
206
+ if (!DT->dominates (SI, LI))
207
+ return false ;
208
+ } else if (!Dep.isNonLocal ()) {
209
+ return false ;
210
+ }
211
+ // else no memdep in this BB, can move on
212
+ }
184
213
185
- // we search only for stores
186
- StoreInst *SI = dyn_cast<StoreInst>(Dep.getInst ());
187
214
if (!SI)
188
215
return false ;
189
216
0 commit comments