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

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

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

Powered by Google App Engine
This is Rietveld 408576698