Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: lib/Transforms/NaCl/ExpandStructRegs.cpp

Issue 460053003: PNaCl: Handle nested structure types in -expand-struct-regs. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Fix incorrect comment. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/Transforms/NaCl/expand-struct-regs.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- ExpandStructRegs.cpp - Expand out variables with struct type--------===// 1 //===- ExpandStructRegs.cpp - Expand out variables with struct type--------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This pass expands out some uses of LLVM variables 10 // This pass expands out some uses of LLVM variables
11 // (a.k.a. registers) of struct type. It replaces loads and stores of 11 // (a.k.a. registers) of struct type. It replaces loads and stores of
12 // structs with separate loads and stores of the structs' fields. The 12 // structs with separate loads and stores of the structs' fields. The
13 // motivation is to omit struct types from PNaCl's stable ABI. 13 // motivation is to omit struct types from PNaCl's stable ABI.
14 // 14 //
15 // ExpandStructRegs does not yet handle all possible uses of struct 15 // ExpandStructRegs does not yet handle all possible uses of struct
16 // values. It is intended to handle the uses that Clang and the SROA 16 // values. It is intended to handle the uses that Clang and the SROA
17 // pass generate. Clang generates struct loads and stores, along with 17 // pass generate. Clang generates struct loads and stores, along with
18 // extractvalue instructions, in its implementation of C++ method 18 // extractvalue instructions, in its implementation of C++ method
19 // pointers, and the SROA pass sometimes converts this code to using 19 // pointers, and the SROA pass sometimes converts this code to using
20 // insertvalue instructions too. 20 // insertvalue instructions too.
21 // 21 //
22 // ExpandStructRegs does not handle: 22 // ExpandStructRegs does not handle:
23 // 23 //
24 // * Nested struct types.
25 // * Array types. 24 // * Array types.
26 // * Function types containing arguments or return values of struct 25 // * Function types containing arguments or return values of struct
27 // type without the "byval" or "sret" attributes. Since by-value 26 // type without the "byval" or "sret" attributes. Since by-value
28 // struct-passing generally uses "byval"/"sret", this does not 27 // struct-passing generally uses "byval"/"sret", this does not
29 // matter. 28 // matter.
30 // 29 //
31 // Other limitations: 30 // Other limitations:
32 // 31 //
33 // * ExpandStructRegs does not attempt to use memcpy() where that 32 // * ExpandStructRegs does not attempt to use memcpy() where that
34 // might be more appropriate than copying fields individually. 33 // might be more appropriate than copying fields individually.
(...skipping 21 matching lines...) Expand all
56 } 55 }
57 56
58 virtual bool runOnFunction(Function &F); 57 virtual bool runOnFunction(Function &F);
59 }; 58 };
60 } 59 }
61 60
62 char ExpandStructRegs::ID = 0; 61 char ExpandStructRegs::ID = 0;
63 INITIALIZE_PASS(ExpandStructRegs, "expand-struct-regs", 62 INITIALIZE_PASS(ExpandStructRegs, "expand-struct-regs",
64 "Expand out variables with struct types", false, false) 63 "Expand out variables with struct types", false, false)
65 64
66 static void SplitUpPHINode(PHINode *Phi) { 65 static bool DoAnotherPass(Type *Ty) { return isa<StructType>(Ty); }
66 static bool DoAnotherPass(Value *V) { return DoAnotherPass(V->getType()); }
67
68 static bool SplitUpPHINode(PHINode *Phi) {
67 StructType *STy = cast<StructType>(Phi->getType()); 69 StructType *STy = cast<StructType>(Phi->getType());
68 70
69 Value *NewStruct = UndefValue::get(STy); 71 Value *NewStruct = UndefValue::get(STy);
70 Instruction *NewStructInsertPt = Phi->getParent()->getFirstInsertionPt(); 72 Instruction *NewStructInsertPt = Phi->getParent()->getFirstInsertionPt();
71 73
74 bool NeedsAnotherPass = false;
75
72 // Create a separate PHINode for each struct field. 76 // Create a separate PHINode for each struct field.
73 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 77 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
74 SmallVector<unsigned, 1> EVIndexes; 78 SmallVector<unsigned, 1> EVIndexes;
75 EVIndexes.push_back(Index); 79 EVIndexes.push_back(Index);
76 80
77 PHINode *NewPhi = PHINode::Create( 81 Type *ElemTy = STy->getElementType(Index);
78 STy->getElementType(Index), Phi->getNumIncomingValues(), 82 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(ElemTy);
79 Phi->getName() + ".index", Phi); 83
84 PHINode *NewPhi = PHINode::Create(ElemTy, Phi->getNumIncomingValues(),
85 Phi->getName() + ".index", Phi);
80 CopyDebug(NewPhi, Phi); 86 CopyDebug(NewPhi, Phi);
81 for (unsigned PhiIndex = 0; PhiIndex < Phi->getNumIncomingValues(); 87 for (unsigned PhiIndex = 0; PhiIndex < Phi->getNumIncomingValues();
82 ++PhiIndex) { 88 ++PhiIndex) {
83 BasicBlock *IncomingBB = Phi->getIncomingBlock(PhiIndex); 89 BasicBlock *IncomingBB = Phi->getIncomingBlock(PhiIndex);
84 Value *EV = CopyDebug( 90 Value *EV = CopyDebug(
85 ExtractValueInst::Create( 91 ExtractValueInst::Create(
86 Phi->getIncomingValue(PhiIndex), EVIndexes, 92 Phi->getIncomingValue(PhiIndex), EVIndexes,
87 Phi->getName() + ".extract", IncomingBB->getTerminator()), Phi); 93 Phi->getName() + ".extract", IncomingBB->getTerminator()), Phi);
88 NewPhi->addIncoming(EV, IncomingBB); 94 NewPhi->addIncoming(EV, IncomingBB);
89 } 95 }
90 96
91 // Reconstruct the original struct value. 97 // Reconstruct the original struct value.
92 NewStruct = CopyDebug( 98 NewStruct = CopyDebug(
93 InsertValueInst::Create(NewStruct, NewPhi, EVIndexes, 99 InsertValueInst::Create(NewStruct, NewPhi, EVIndexes,
94 Phi->getName() + ".insert", NewStructInsertPt), 100 Phi->getName() + ".insert", NewStructInsertPt),
95 Phi); 101 Phi);
96 } 102 }
97 Phi->replaceAllUsesWith(NewStruct); 103 Phi->replaceAllUsesWith(NewStruct);
98 Phi->eraseFromParent(); 104 Phi->eraseFromParent();
105
106 return NeedsAnotherPass;
99 } 107 }
100 108
101 static void SplitUpSelect(SelectInst *Select) { 109 static bool SplitUpSelect(SelectInst *Select) {
102 StructType *STy = cast<StructType>(Select->getType()); 110 StructType *STy = cast<StructType>(Select->getType());
103 Value *NewStruct = UndefValue::get(STy); 111 Value *NewStruct = UndefValue::get(STy);
104 112
113 bool NeedsAnotherPass = false;
105 // Create a separate SelectInst for each struct field. 114 // Create a separate SelectInst for each struct field.
106 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 115 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
107 SmallVector<unsigned, 1> EVIndexes; 116 SmallVector<unsigned, 1> EVIndexes;
108 EVIndexes.push_back(Index); 117 EVIndexes.push_back(Index);
109 118
110 Value *TrueVal = CopyDebug( 119 Value *TrueVal = CopyDebug(
111 ExtractValueInst::Create(Select->getTrueValue(), EVIndexes, 120 ExtractValueInst::Create(Select->getTrueValue(), EVIndexes,
112 Select->getName() + ".extract", Select), 121 Select->getName() + ".extract", Select),
113 Select); 122 Select);
114 Value *FalseVal = CopyDebug( 123 Value *FalseVal = CopyDebug(
115 ExtractValueInst::Create(Select->getFalseValue(), EVIndexes, 124 ExtractValueInst::Create(Select->getFalseValue(), EVIndexes,
116 Select->getName() + ".extract", Select), 125 Select->getName() + ".extract", Select),
117 Select); 126 Select);
118 Value *NewSelect = CopyDebug( 127 Value *NewSelect = CopyDebug(
119 SelectInst::Create(Select->getCondition(), TrueVal, FalseVal, 128 SelectInst::Create(Select->getCondition(), TrueVal, FalseVal,
120 Select->getName() + ".index", Select), Select); 129 Select->getName() + ".index", Select), Select);
121 130
131 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewSelect);
132
122 // Reconstruct the original struct value. 133 // Reconstruct the original struct value.
123 NewStruct = CopyDebug( 134 NewStruct = CopyDebug(
124 InsertValueInst::Create(NewStruct, NewSelect, EVIndexes, 135 InsertValueInst::Create(NewStruct, NewSelect, EVIndexes,
125 Select->getName() + ".insert", Select), 136 Select->getName() + ".insert", Select),
126 Select); 137 Select);
127 } 138 }
128 Select->replaceAllUsesWith(NewStruct); 139 Select->replaceAllUsesWith(NewStruct);
129 Select->eraseFromParent(); 140 Select->eraseFromParent();
141
142 return NeedsAnotherPass;
130 } 143 }
131 144
132 template <class InstType> 145 template <class InstType>
133 static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src) { 146 static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src) {
134 CopyDebug(Dest, Src); 147 CopyDebug(Dest, Src);
135 Dest->setVolatile(Src->isVolatile()); 148 Dest->setVolatile(Src->isVolatile());
136 if (Src->isAtomic()) { 149 if (Src->isAtomic()) {
137 errs() << "Use: " << *Src << "\n"; 150 errs() << "Use: " << *Src << "\n";
138 report_fatal_error("Atomic struct loads/stores not supported"); 151 report_fatal_error("Atomic struct loads/stores not supported");
139 } 152 }
140 // Make a pessimistic assumption about alignment. Preserving 153 // Make a pessimistic assumption about alignment. Preserving
141 // alignment information here is tricky and is not really desirable 154 // alignment information here is tricky and is not really desirable
142 // for PNaCl because mistakes here could lead to non-portable 155 // for PNaCl because mistakes here could lead to non-portable
143 // behaviour. 156 // behaviour.
144 Dest->setAlignment(1); 157 Dest->setAlignment(1);
145 } 158 }
146 159
147 static void SplitUpStore(StoreInst *Store) { 160 static bool SplitUpStore(StoreInst *Store) {
148 StructType *STy = cast<StructType>(Store->getValueOperand()->getType()); 161 StructType *STy = cast<StructType>(Store->getValueOperand()->getType());
162
163 bool NeedsAnotherPass = false;
149 // Create a separate store instruction for each struct field. 164 // Create a separate store instruction for each struct field.
150 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 165 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
151 SmallVector<Value *, 2> Indexes; 166 SmallVector<Value *, 2> Indexes;
152 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); 167 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0)));
153 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index))); 168 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index)));
154 Value *GEP = CopyDebug(GetElementPtrInst::Create( 169 Value *GEP = CopyDebug(GetElementPtrInst::Create(
155 Store->getPointerOperand(), Indexes, 170 Store->getPointerOperand(), Indexes,
156 Store->getPointerOperand()->getName() + ".index", 171 Store->getPointerOperand()->getName() + ".index",
157 Store), Store); 172 Store), Store);
173 NeedsAnotherPass =
174 NeedsAnotherPass || DoAnotherPass(GEP->getType()->getContainedType(0));
175
158 SmallVector<unsigned, 1> EVIndexes; 176 SmallVector<unsigned, 1> EVIndexes;
159 EVIndexes.push_back(Index); 177 EVIndexes.push_back(Index);
160 Value *Field = ExtractValueInst::Create(Store->getValueOperand(), 178 Value *Field = ExtractValueInst::Create(Store->getValueOperand(),
161 EVIndexes, "", Store); 179 EVIndexes, "", Store);
162 StoreInst *NewStore = new StoreInst(Field, GEP, Store); 180 StoreInst *NewStore = new StoreInst(Field, GEP, Store);
163 ProcessLoadOrStoreAttrs(NewStore, Store); 181 ProcessLoadOrStoreAttrs(NewStore, Store);
164 } 182 }
165 Store->eraseFromParent(); 183 Store->eraseFromParent();
184
185 return NeedsAnotherPass;
166 } 186 }
167 187
168 static void SplitUpLoad(LoadInst *Load) { 188 static bool SplitUpLoad(LoadInst *Load) {
169 StructType *STy = cast<StructType>(Load->getType()); 189 StructType *STy = cast<StructType>(Load->getType());
170 Value *NewStruct = UndefValue::get(STy); 190 Value *NewStruct = UndefValue::get(STy);
171 191
192 bool NeedsAnotherPass = false;
172 // Create a separate load instruction for each struct field. 193 // Create a separate load instruction for each struct field.
173 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 194 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
174 SmallVector<Value *, 2> Indexes; 195 SmallVector<Value *, 2> Indexes;
175 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0))); 196 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0)));
176 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index))); 197 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index)));
177 Value *GEP = CopyDebug( 198 Value *GEP = CopyDebug(
178 GetElementPtrInst::Create(Load->getPointerOperand(), Indexes, 199 GetElementPtrInst::Create(Load->getPointerOperand(), Indexes,
179 Load->getName() + ".index", Load), Load); 200 Load->getName() + ".index", Load), Load);
180 LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load); 201 LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load);
202
203 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewLoad);
181 ProcessLoadOrStoreAttrs(NewLoad, Load); 204 ProcessLoadOrStoreAttrs(NewLoad, Load);
182 205
183 // Reconstruct the struct value. 206 // Reconstruct the struct value.
184 SmallVector<unsigned, 1> EVIndexes; 207 SmallVector<unsigned, 1> EVIndexes;
185 EVIndexes.push_back(Index); 208 EVIndexes.push_back(Index);
186 NewStruct = CopyDebug( 209 NewStruct = CopyDebug(
187 InsertValueInst::Create(NewStruct, NewLoad, EVIndexes, 210 InsertValueInst::Create(NewStruct, NewLoad, EVIndexes,
188 Load->getName() + ".insert", Load), Load); 211 Load->getName() + ".insert", Load), Load);
189 } 212 }
190 Load->replaceAllUsesWith(NewStruct); 213 Load->replaceAllUsesWith(NewStruct);
191 Load->eraseFromParent(); 214 Load->eraseFromParent();
192 } 215
193 216 return NeedsAnotherPass;
194 static bool ExpandExtractValue(ExtractValueInst *EV) { 217 }
218
219 static bool ExpandExtractValue(ExtractValueInst *EV, SmallVectorImpl<Instruction *>& ToErase) {
JF 2014/12/10 22:54:56 Pass in a pointer to the SmallVector instead.
Richard Diamond 2014/12/11 16:32:08 Done.
195 // Search for the insertvalue instruction that inserts the struct field 220 // Search for the insertvalue instruction that inserts the struct field
196 // referenced by this extractvalue instruction, excluding CmpXchg which 221 // referenced by this extractvalue instruction, excluding CmpXchg which
197 // returns a struct and is handled by RewriteAtomics. 222 // returns a struct and is handled by RewriteAtomics.
198 Value *StructVal = EV->getAggregateOperand(); 223 Value *StructVal = EV->getAggregateOperand();
199 Value *ResultField; 224 Value *ResultField = nullptr;
225
226 // The current depth of the search. It's impossible to backtrack in our search
227 // tree (all prior (not in the CFG sense) extractvalues will already be
228 // expanded), so this variable is never reset to zero.
229 size_t EVIndex = 0;
230
200 if (isa<AtomicCmpXchgInst>(StructVal)) 231 if (isa<AtomicCmpXchgInst>(StructVal))
201 return false; 232 return false;
233
202 for (;;) { 234 for (;;) {
203 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(StructVal)) { 235 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(StructVal)) {
204 if (EV->getNumIndices() != 1 || IV->getNumIndices() != 1) { 236
205 errs() << "Value: " << *EV << "\n"; 237 size_t IVIndex = 0;
206 errs() << "Value: " << *IV << "\n"; 238 for (; EVIndex < EV->getIndices().size() && IVIndex < IV->getIndices().siz e();
JF 2014/12/10 22:54:56 Could you re-run clang-format on the code you've c
Richard Diamond 2014/12/11 16:32:08 Done.
207 report_fatal_error("ExpandStructRegs does not handle nested structs"); 239 ++IVIndex, ++EVIndex) {
208 } 240
209 if (EV->getIndices()[0] == IV->getIndices()[0]) { 241 const bool Equal = (EV->getIndices()[EVIndex] == IV->getIndices()[IVInde x]);
210 ResultField = IV->getInsertedValueOperand(); 242
243 if (IVIndex + 1 == IV->getIndices().size() && Equal) {
244 if (EVIndex + 1 == EV->getIndices().size()) {
245 // Exact match. We break out of all loops and ResultField will repla ce EV.
246 ResultField = IV->getInsertedValueOperand();
247 } else {
248 // We've found a match, but haven't reached the end of EV's indexes.
249 // We continue looping through the outermost loop, and search for
250 // indices on the next level down (ie we increment EVIndex).
251 // This branch is common when encountering nested insertvalues; for
252 // example:
253 // ```llvm
254 // %1 = insertvalue { i32 } undef, i32 1, 0
255 // %2 = insertvalue { { i32 } } %1, { i32 } %1, 0
256 // %3 = extractvalue { { i32 } } %2, 0, 0
257 // ```
258 StructVal = IV->getInsertedValueOperand();
259 ++EVIndex;
260 }
261 break;
262 } else if (!Equal) {
263 // No match. Try the next struct value in the chain.
264 // For example:
265 // ```llvm
266 // %1 = insertvalue { i32, i32, i32 } undef, i32 5, 0
267 // %2 = insertvalue { i32, i32, i32 } %1, i32 10, 1
268 // %3 = insertvalue { i32, i32, i32 } %2, i32 15, 2
269 // %4 = extractvalue { i32, i32, i32 } %3, 0
270 // ```
271 // In this case, to expand %4, this branch will hit insertvalues %3 an d %2 before
272 // it finds the solution, %1.
273 StructVal = IV->getAggregateOperand();
274 break;
275 }
276
277 // One last case worth mentioning:
278 // ```llvm
279 // %aa = alloca { i32 }
280 // %a = insertvalue { i32 } undef, i32 1, 0
281 // %b = insertvalue { { i32 } } undef, { i32 } %a, 0
282 // %c = extractvalue { { i32 } } %b, 0
283 // store { i32 } %c, { i32 }* %aa
284 // ```
285 // In the case of %c, the condition of our inner loop will be false, and
286 // we will fall into (EVIndex == EV->getIndices().size())
287 // Note that in this case, SplitStore will have inserted an extra
288 // extractvalue and GEP:
289 // ```llvm
290 // %aa = alloca { i32 }
291 // %a = insertvalue { i32 } undef, i32 1, 0
292 // %b = insertvalue { { i32 } } undef, { i32 } %a, 0
293 // %c.extractval = extractvalue { i32 } %a, 0
294 // %aa.index = getelementptr { i32 }* %aa, i32 0, i32 0
295 // store i32 %c, i32* %aa.index
296 // ```
297 }
298 if (ResultField) {
299 // \O/ We're done with this ExtractValueInst!
211 break; 300 break;
212 } 301 } else if (EVIndex == EV->getIndices().size()) {
213 // No match. Try the next struct value in the chain. 302 // We've found an insertvalue that inserts at one or more levels deeper
214 StructVal = IV->getAggregateOperand(); 303 // than this extractvalue. For example (borrowed from the tests), where
304 // %h is EV && %e is IV:
305 // ```llvm
306 // %e = insertvalue { { { i32, i64 } }, i64 } undef, { i32, i64 } %b, 0, 0
307 // %h = extractvalue { { { i32, i64 } }, i64 } %e, 0
308 // ; later on..
309 // %1 = extractvalue { { i32, i64 } } %h, 0
310 // ```
311 // This expands to:
312 // ```llvm
313 // %e = insertvalue { { { i32, i64 } }, i64 } undef, { i32, i64 } %b, 0, 0
314 // %1 = insertvalue { { i32, i64 } } undef, { i32, i64 } %b, 0
315 // %h = extractvalue { { { i32, i64 } }, i64 } %e, 0
316 // %2 = extractvalue { { i32, i64 } } %h, 0
317 // ```
318 // Then, outside the outer loop, %h is deleted:
319 // ```llvm
320 // %e = insertvalue { { { i32, i64 } }, i64 } undef, { i32, i64 } %b, 0, 0
321 // %1 = insertvalue { { i32, i64 } } undef, { i32, i64 } %b, 0
322 // %2 = extractvalue { { i32, i64 } } %1, 0
323 // ```
324 // %2 will be expanded at a later point.
325 // This branch used the second index in %e to create %1 (because %2 &&
326 // %e's first indices where equal).
327 //
328 // Additionally, it's impossible to not change StructVal && not hit this
329 // branch (but the reverse is not true!).
330
331 SmallVector<unsigned, 4> Indices(IV->getIndices().begin() + IVIndex,
332 IV->getIndices().end());
333
334 InsertValueInst *Insert = InsertValueInst::Create(
335 UndefValue::get(EV->getType()), IV->getInsertedValueOperand(),
336 Indices, "", EV);
337 ToErase.push_back(Insert);
338 ResultField = CopyDebug(Insert, EV);
339 break;
340 }
341
342 // At this point, StructVal must be changed.
215 } else if (Constant *C = dyn_cast<Constant>(StructVal)) { 343 } else if (Constant *C = dyn_cast<Constant>(StructVal)) {
216 ResultField = ConstantExpr::getExtractValue(C, EV->getIndices()); 344 SmallVector<unsigned, 4> Indices(EV->getIndices().begin() + EVIndex,
345 EV->getIndices().end());
346 ResultField = ConstantExpr::getExtractValue(C, Indices);
347 break;
348 } else if (isa<LoadInst>(StructVal)) {
349 ResultField = StructVal;
217 break; 350 break;
218 } else { 351 } else {
219 errs() << "Value: " << *StructVal << "\n"; 352 errs() << "Value: " << *StructVal << "\n";
220 report_fatal_error("Unrecognized struct value"); 353 report_fatal_error("Unrecognized struct value");
221 } 354 }
222 } 355 }
356
357 assert(ResultField); // Failsafe.
JF 2014/12/10 22:54:56 Failsafe?
Richard Diamond 2014/12/11 16:32:08 Nevermind, I've removed it.
223 EV->replaceAllUsesWith(ResultField); 358 EV->replaceAllUsesWith(ResultField);
224 EV->eraseFromParent(); 359 EV->eraseFromParent();
225 return true; 360 return true;
226 } 361 }
227 362
228 bool ExpandStructRegs::runOnFunction(Function &Func) { 363 static bool ExpandExtractValues(Function &Func) {
229 bool Changed = false; 364 bool Changed = false;
230 365
231 // Split up aggregate loads, stores and phi nodes into operations on 366 SmallVector<Instruction *, 10> ToErase;
232 // scalar types. This inserts extractvalue and insertvalue
233 // instructions which we will expand out later.
234 for (Function::iterator BB = Func.begin(), E = Func.end();
235 BB != E; ++BB) {
236 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
237 Iter != E; ) {
238 Instruction *Inst = Iter++;
239 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
240 if (Store->getValueOperand()->getType()->isStructTy()) {
241 SplitUpStore(Store);
242 Changed = true;
243 }
244 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
245 if (Load->getType()->isStructTy()) {
246 SplitUpLoad(Load);
247 Changed = true;
248 }
249 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
250 if (Phi->getType()->isStructTy()) {
251 SplitUpPHINode(Phi);
252 Changed = true;
253 }
254 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
255 if (Select->getType()->isStructTy()) {
256 SplitUpSelect(Select);
257 Changed = true;
258 }
259 }
260 }
261 }
262
263 // Expand out all the extractvalue instructions. Also collect up 367 // Expand out all the extractvalue instructions. Also collect up
264 // the insertvalue instructions for later deletion so that we do not 368 // the insertvalue instructions for later deletion so that we do not
265 // need to make extra passes across the whole function. 369 // need to make extra passes across the whole function.
266 SmallVector<Instruction *, 10> ToErase; 370
267 for (Function::iterator BB = Func.begin(), E = Func.end(); 371 for (auto &BB : Func) {
268 BB != E; ++BB) { 372 for (BasicBlock::iterator Iter = BB.begin(), E = BB.end();
269 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
270 Iter != E; ) { 373 Iter != E; ) {
271 Instruction *Inst = Iter++; 374 Instruction *Inst = Iter++;
272 if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Inst)) { 375 if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Inst)) {
273 Changed |= ExpandExtractValue(EV); 376 Changed |= ExpandExtractValue(EV, ToErase);
274 } else if (isa<InsertValueInst>(Inst)) { 377 } else if (isa<InsertValueInst>(Inst)) {
275 ToErase.push_back(Inst); 378 ToErase.push_back(Inst);
276 Changed = true; 379 Changed = true;
277 } 380 }
278 } 381 }
279 } 382 }
383
280 // Delete the insertvalue instructions. These can reference each 384 // Delete the insertvalue instructions. These can reference each
281 // other, so we must do dropAllReferences() before doing 385 // other, so we must do dropAllReferences() before doing
282 // eraseFromParent(), otherwise we will try to erase instructions 386 // eraseFromParent(), otherwise we will try to erase instructions
283 // that are still referenced. 387 // that are still referenced.
284 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(), 388 for (Instruction *I : ToErase) {
285 E = ToErase.end(); 389 I->dropAllReferences();
286 I != E; ++I) { 390 }
287 (*I)->dropAllReferences(); 391
288 } 392 for (Instruction *I : ToErase) {
289 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(), 393 I->eraseFromParent();
290 E = ToErase.end(); 394 }
291 I != E; ++I) { 395
292 (*I)->eraseFromParent();
293 }
294 return Changed; 396 return Changed;
295 } 397 }
296 398
399 bool ExpandStructRegs::runOnFunction(Function &Func) {
400 bool Changed = false;
401 bool NeedsAnotherPass;
402
403 do {
404 NeedsAnotherPass = false;
405 // Split up aggregate loads, stores and phi nodes into operations on
406 // scalar types. This inserts extractvalue and insertvalue
407 // instructions which we will expand out later.
408 for (Function::iterator BB = Func.begin(), E = Func.end();
409 BB != E; ++BB) {
410 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
411 Iter != E; ) {
412 Instruction *Inst = Iter++;
413 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
414 if (Store->getValueOperand()->getType()->isStructTy()) {
415 NeedsAnotherPass |= SplitUpStore(Store);
416 Changed = true;
417 }
418 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
419 if (Load->getType()->isStructTy()) {
420 NeedsAnotherPass |= SplitUpLoad(Load);
421 Changed = true;
422 }
423 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
424 if (Phi->getType()->isStructTy()) {
425 NeedsAnotherPass |= SplitUpPHINode(Phi);
426 Changed = true;
427 }
428 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
429 if (Select->getType()->isStructTy()) {
430 NeedsAnotherPass |= SplitUpSelect(Select);
431 Changed = true;
432 }
433 }
434 }
435 }
436 } while(NeedsAnotherPass);
437
438 Changed |= ExpandExtractValues(Func);
439
440 return Changed;
441 }
442
297 FunctionPass *llvm::createExpandStructRegsPass() { 443 FunctionPass *llvm::createExpandStructRegsPass() {
298 return new ExpandStructRegs(); 444 return new ExpandStructRegs();
299 } 445 }
OLDNEW
« no previous file with comments | « no previous file | test/Transforms/NaCl/expand-struct-regs.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698