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

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: Forgot a small change. 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
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();
215
216 return NeedsAnotherPass;
192 } 217 }
193 218
194 static bool ExpandExtractValue(ExtractValueInst *EV) { 219 static bool ExpandExtractValue(ExtractValueInst *EV, bool &NeedsAnotherPass) {
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 size_t I = 0;
Mark Seaborn 2014/12/09 20:39:46 "I" is too cryptic for an index used across multip
Richard Diamond 2014/12/10 00:58:06 Done.
226
200 if (isa<AtomicCmpXchgInst>(StructVal)) 227 if (isa<AtomicCmpXchgInst>(StructVal))
201 return false; 228 return false;
229
202 for (;;) { 230 for (;;) {
203 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(StructVal)) { 231 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(StructVal)) {
204 if (EV->getNumIndices() != 1 || IV->getNumIndices() != 1) { 232 size_t J = 0;
205 errs() << "Value: " << *EV << "\n"; 233 for (; I < EV->getIndices().size() && J < IV->getIndices().size();
206 errs() << "Value: " << *IV << "\n"; 234 ++J, ++I) {
Mark Seaborn 2014/12/09 20:39:46 This doesn't look right. You increment "I", but "
Richard Diamond 2014/12/10 00:58:05 Yes, see line 242 ((EVIndex + 1 == EV->getIndices(
207 report_fatal_error("ExpandStructRegs does not handle nested structs"); 235 const bool Equal = (EV->getIndices()[I] == IV->getIndices()[J]);
236 if (J + 1 == IV->getIndices().size() && Equal) {
237 if (I + 1 == EV->getIndices().size()) {
238 // Match
239 ResultField = IV->getInsertedValueOperand();
240 } else {
241 StructVal = IV->getInsertedValueOperand();
242 ++I;
243 }
244 break;
245 } else if (!Equal) {
246 // No match. Try the next struct value in the chain.
247 StructVal = IV->getAggregateOperand();
248 break;
249 }
208 } 250 }
209 if (EV->getIndices()[0] == IV->getIndices()[0]) { 251 if (ResultField) {
210 ResultField = IV->getInsertedValueOperand(); 252 break;
253 } else if (I == EV->getIndices().size()) {
254 // We've found an insertvalue that inserts at one or more levels deeper
255 // than this extractvalue.
256 NeedsAnotherPass = true;
257 SmallVector<unsigned, 4> Indices(IV->getIndices().begin() + J,
258 IV->getIndices().end());
259
260 InsertValueInst *Insert = InsertValueInst::Create(
261 UndefValue::get(EV->getType()), IV->getInsertedValueOperand(),
262 Indices, "", EV);
263 ResultField = CopyDebug(Insert, EV);
211 break; 264 break;
212 } 265 }
Mark Seaborn 2014/12/09 20:39:46 Can we reach after this "}" with StructVal not hav
Richard Diamond 2014/12/10 00:58:05 No, because all such cases would be caught by the
213 // No match. Try the next struct value in the chain.
214 StructVal = IV->getAggregateOperand();
215 } else if (Constant *C = dyn_cast<Constant>(StructVal)) { 266 } else if (Constant *C = dyn_cast<Constant>(StructVal)) {
216 ResultField = ConstantExpr::getExtractValue(C, EV->getIndices()); 267 SmallVector<unsigned, 4> Indices(EV->getIndices().begin() + I,
268 EV->getIndices().end());
269 ResultField = ConstantExpr::getExtractValue(C, Indices);
270 break;
271 } else if (isa<LoadInst>(StructVal)) {
272 ResultField = StructVal;
217 break; 273 break;
218 } else { 274 } else {
219 errs() << "Value: " << *StructVal << "\n"; 275 errs() << "Value: " << *StructVal << "\n";
220 report_fatal_error("Unrecognized struct value"); 276 report_fatal_error("Unrecognized struct value");
221 } 277 }
222 } 278 }
279
280 assert(ResultField);
Mark Seaborn 2014/12/09 20:39:46 Are there inputs for which this assertion would fa
Richard Diamond 2014/12/10 00:58:06 There shouldn't be, but that doesn't prevent a dev
223 EV->replaceAllUsesWith(ResultField); 281 EV->replaceAllUsesWith(ResultField);
224 EV->eraseFromParent(); 282 EV->eraseFromParent();
225 return true; 283 return true;
226 } 284 }
227 285
286 static bool ExpandExtractValues(Function &Func) {
287 bool Changed = false;
288 bool NeedsAnotherPass = false;
289
290 // Expand out all the extractvalue instructions. Also collect up
291 // the insertvalue instructions for later deletion so that we do not
292 // need to make extra passes across the whole function.
293 SmallVector<Instruction *, 10> ToErase;
294 for (auto &BB : Func) {
295 for (BasicBlock::iterator Iter = BB.begin(), E = BB.end();
296 Iter != E; ) {
297 Instruction* Inst = Iter++;
Mark Seaborn 2014/12/09 20:39:46 Nit: LLVM style is " *"
Richard Diamond 2014/12/10 00:58:06 Whoops. Done.
298 if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Inst)) {
299 Changed |= ExpandExtractValue(EV, NeedsAnotherPass);
300 } else if (isa<InsertValueInst>(Inst)) {
301 ToErase.push_back(Inst);
Mark Seaborn 2014/12/09 20:39:46 ExpandExtractValue() can create InsertValueInsts,
Richard Diamond 2014/12/10 00:58:05 Actually, extra passes in ExpandExtractValues are
302 Changed = true;
303 }
304 }
305 }
306
307 if (!NeedsAnotherPass) {
308 // Delete the insertvalue instructions. These can reference each
309 // other, so we must do dropAllReferences() before doing
310 // eraseFromParent(), otherwise we will try to erase instructions
311 // that are still referenced.
312 for (Instruction *I : ToErase) {
313 I->dropAllReferences();
314 }
315
316 for (Instruction *I : ToErase) {
317 I->eraseFromParent();
318 }
319 }
320
321 return (NeedsAnotherPass && ExpandExtractValues(Func)) || Changed;
322 }
323
228 bool ExpandStructRegs::runOnFunction(Function &Func) { 324 bool ExpandStructRegs::runOnFunction(Function &Func) {
229 bool Changed = false; 325 bool Changed = false;
326 bool NeedsAnotherPass = false;
230 327
231 // Split up aggregate loads, stores and phi nodes into operations on 328 // Split up aggregate loads, stores and phi nodes into operations on
Mark Seaborn 2014/12/09 20:39:46 I think there's a completeness problem here: This
Richard Diamond 2014/12/10 00:58:05 I was using recursion, however this patchset is ol
232 // scalar types. This inserts extractvalue and insertvalue 329 // scalar types. This inserts extractvalue and insertvalue
233 // instructions which we will expand out later. 330 // instructions which we will expand out later.
234 for (Function::iterator BB = Func.begin(), E = Func.end(); 331 for (Function::iterator BB = Func.begin(), E = Func.end();
235 BB != E; ++BB) { 332 BB != E; ++BB) {
236 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); 333 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
237 Iter != E; ) { 334 Iter != E; ) {
238 Instruction *Inst = Iter++; 335 Instruction *Inst = Iter++;
239 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 336 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
240 if (Store->getValueOperand()->getType()->isStructTy()) { 337 if (Store->getValueOperand()->getType()->isStructTy()) {
241 SplitUpStore(Store); 338 NeedsAnotherPass = SplitUpStore(Store) || NeedsAnotherPass;
JF 2014/12/09 19:20:22 I think this is cleaner: NeedsAnotherPass |= foo
Richard Diamond 2014/12/09 19:39:23 Done.
242 Changed = true; 339 Changed = true;
243 } 340 }
244 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 341 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
245 if (Load->getType()->isStructTy()) { 342 if (Load->getType()->isStructTy()) {
246 SplitUpLoad(Load); 343 NeedsAnotherPass = SplitUpLoad(Load) || NeedsAnotherPass;
247 Changed = true; 344 Changed = true;
248 } 345 }
249 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { 346 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
250 if (Phi->getType()->isStructTy()) { 347 if (Phi->getType()->isStructTy()) {
251 SplitUpPHINode(Phi); 348 NeedsAnotherPass = SplitUpPHINode(Phi) || NeedsAnotherPass;
252 Changed = true; 349 Changed = true;
253 } 350 }
254 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) { 351 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
255 if (Select->getType()->isStructTy()) { 352 if (Select->getType()->isStructTy()) {
256 SplitUpSelect(Select); 353 NeedsAnotherPass = SplitUpSelect(Select) || NeedsAnotherPass;
257 Changed = true; 354 Changed = true;
258 } 355 }
259 } 356 }
260 } 357 }
261 } 358 }
262 359
263 // Expand out all the extractvalue instructions. Also collect up 360 if (!NeedsAnotherPass) {
264 // the insertvalue instructions for later deletion so that we do not 361 Changed = ExpandExtractValues(Func) || Changed;
265 // need to make extra passes across the whole function.
266 SmallVector<Instruction *, 10> ToErase;
267 for (Function::iterator BB = Func.begin(), E = Func.end();
268 BB != E; ++BB) {
269 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
270 Iter != E; ) {
271 Instruction *Inst = Iter++;
272 if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Inst)) {
273 Changed |= ExpandExtractValue(EV);
274 } else if (isa<InsertValueInst>(Inst)) {
275 ToErase.push_back(Inst);
276 Changed = true;
277 }
278 }
279 } 362 }
280 // Delete the insertvalue instructions. These can reference each 363
281 // other, so we must do dropAllReferences() before doing 364 return (NeedsAnotherPass && runOnFunction(Func)) || Changed;
JF 2014/12/09 19:20:22 I'm not a fan of the tail recursion, could you jus
Richard Diamond 2014/12/09 19:39:23 Done.
282 // eraseFromParent(), otherwise we will try to erase instructions
283 // that are still referenced.
284 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
285 E = ToErase.end();
286 I != E; ++I) {
287 (*I)->dropAllReferences();
288 }
289 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
290 E = ToErase.end();
291 I != E; ++I) {
292 (*I)->eraseFromParent();
293 }
294 return Changed;
295 } 365 }
296 366
297 FunctionPass *llvm::createExpandStructRegsPass() { 367 FunctionPass *llvm::createExpandStructRegsPass() {
298 return new ExpandStructRegs(); 368 return new ExpandStructRegs();
299 } 369 }
OLDNEW
« no previous file with comments | « no previous file | test/Transforms/NaCl/expand-struct-regs.ll » ('j') | test/Transforms/NaCl/expand-struct-regs.ll » ('J')

Powered by Google App Engine
This is Rietveld 408576698