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

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: Created 6 years, 4 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
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 void SplitUpPHINode(PHINode *Phi, bool &NeedsAnotherPass) {
JF 2014/12/06 23:52:13 I'd return a bool here instead, same with the othe
Richard Diamond 2014/12/09 04:33:15 Done.
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
72 // Create a separate PHINode for each struct field. 74 // Create a separate PHINode for each struct field.
73 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 75 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
74 SmallVector<unsigned, 1> EVIndexes; 76 SmallVector<unsigned, 1> EVIndexes;
75 EVIndexes.push_back(Index); 77 EVIndexes.push_back(Index);
76 78
77 PHINode *NewPhi = PHINode::Create( 79 Type *ElemTy = STy->getElementType(Index);
78 STy->getElementType(Index), Phi->getNumIncomingValues(), 80 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(ElemTy);
79 Phi->getName() + ".index", Phi); 81
82 PHINode *NewPhi = PHINode::Create(ElemTy, Phi->getNumIncomingValues(),
83 Phi->getName() + ".index", Phi);
80 CopyDebug(NewPhi, Phi); 84 CopyDebug(NewPhi, Phi);
81 for (unsigned PhiIndex = 0; PhiIndex < Phi->getNumIncomingValues(); 85 for (unsigned PhiIndex = 0; PhiIndex < Phi->getNumIncomingValues();
82 ++PhiIndex) { 86 ++PhiIndex) {
83 BasicBlock *IncomingBB = Phi->getIncomingBlock(PhiIndex); 87 BasicBlock *IncomingBB = Phi->getIncomingBlock(PhiIndex);
84 Value *EV = CopyDebug( 88 Value *EV = CopyDebug(
85 ExtractValueInst::Create( 89 ExtractValueInst::Create(
86 Phi->getIncomingValue(PhiIndex), EVIndexes, 90 Phi->getIncomingValue(PhiIndex), EVIndexes,
87 Phi->getName() + ".extract", IncomingBB->getTerminator()), Phi); 91 Phi->getName() + ".extract", IncomingBB->getTerminator()), Phi);
88 NewPhi->addIncoming(EV, IncomingBB); 92 NewPhi->addIncoming(EV, IncomingBB);
89 } 93 }
90 94
91 // Reconstruct the original struct value. 95 // Reconstruct the original struct value.
92 NewStruct = CopyDebug( 96 NewStruct = CopyDebug(
93 InsertValueInst::Create(NewStruct, NewPhi, EVIndexes, 97 InsertValueInst::Create(NewStruct, NewPhi, EVIndexes,
94 Phi->getName() + ".insert", NewStructInsertPt), 98 Phi->getName() + ".insert", NewStructInsertPt),
95 Phi); 99 Phi);
96 } 100 }
97 Phi->replaceAllUsesWith(NewStruct); 101 Phi->replaceAllUsesWith(NewStruct);
98 Phi->eraseFromParent(); 102 Phi->eraseFromParent();
99 } 103 }
100 104
101 static void SplitUpSelect(SelectInst *Select) { 105 static void SplitUpSelect(SelectInst *Select, bool &NeedsAnotherPass) {
102 StructType *STy = cast<StructType>(Select->getType()); 106 StructType *STy = cast<StructType>(Select->getType());
103 Value *NewStruct = UndefValue::get(STy); 107 Value *NewStruct = UndefValue::get(STy);
104 108
105 // Create a separate SelectInst for each struct field. 109 // Create a separate SelectInst for each struct field.
106 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 110 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
107 SmallVector<unsigned, 1> EVIndexes; 111 SmallVector<unsigned, 1> EVIndexes;
108 EVIndexes.push_back(Index); 112 EVIndexes.push_back(Index);
109 113
110 Value *TrueVal = CopyDebug( 114 Value *TrueVal = CopyDebug(
111 ExtractValueInst::Create(Select->getTrueValue(), EVIndexes, 115 ExtractValueInst::Create(Select->getTrueValue(), EVIndexes,
112 Select->getName() + ".extract", Select), 116 Select->getName() + ".extract", Select),
113 Select); 117 Select);
114 Value *FalseVal = CopyDebug( 118 Value *FalseVal = CopyDebug(
115 ExtractValueInst::Create(Select->getFalseValue(), EVIndexes, 119 ExtractValueInst::Create(Select->getFalseValue(), EVIndexes,
116 Select->getName() + ".extract", Select), 120 Select->getName() + ".extract", Select),
117 Select); 121 Select);
118 Value *NewSelect = CopyDebug( 122 Value *NewSelect = CopyDebug(
119 SelectInst::Create(Select->getCondition(), TrueVal, FalseVal, 123 SelectInst::Create(Select->getCondition(), TrueVal, FalseVal,
120 Select->getName() + ".index", Select), Select); 124 Select->getName() + ".index", Select), Select);
121 125
126 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewSelect);
127
122 // Reconstruct the original struct value. 128 // Reconstruct the original struct value.
123 NewStruct = CopyDebug( 129 NewStruct = CopyDebug(
124 InsertValueInst::Create(NewStruct, NewSelect, EVIndexes, 130 InsertValueInst::Create(NewStruct, NewSelect, EVIndexes,
125 Select->getName() + ".insert", Select), 131 Select->getName() + ".insert", Select),
126 Select); 132 Select);
127 } 133 }
128 Select->replaceAllUsesWith(NewStruct); 134 Select->replaceAllUsesWith(NewStruct);
129 Select->eraseFromParent(); 135 Select->eraseFromParent();
130 } 136 }
131 137
132 template <class InstType> 138 template <class InstType>
133 static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src) { 139 static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src) {
134 CopyDebug(Dest, Src); 140 CopyDebug(Dest, Src);
135 Dest->setVolatile(Src->isVolatile()); 141 Dest->setVolatile(Src->isVolatile());
136 if (Src->isAtomic()) { 142 if (Src->isAtomic()) {
137 errs() << "Use: " << *Src << "\n"; 143 errs() << "Use: " << *Src << "\n";
138 report_fatal_error("Atomic struct loads/stores not supported"); 144 report_fatal_error("Atomic struct loads/stores not supported");
139 } 145 }
140 // Make a pessimistic assumption about alignment. Preserving 146 // Make a pessimistic assumption about alignment. Preserving
141 // alignment information here is tricky and is not really desirable 147 // alignment information here is tricky and is not really desirable
142 // for PNaCl because mistakes here could lead to non-portable 148 // for PNaCl because mistakes here could lead to non-portable
143 // behaviour. 149 // behaviour.
144 Dest->setAlignment(1); 150 Dest->setAlignment(1);
145 } 151 }
146 152
147 static void SplitUpStore(StoreInst *Store) { 153 static void SplitUpStore(StoreInst *Store, bool &NeedsAnotherPass) {
148 StructType *STy = cast<StructType>(Store->getValueOperand()->getType()); 154 StructType *STy = cast<StructType>(Store->getValueOperand()->getType());
155
149 // Create a separate store instruction for each struct field. 156 // Create a separate store instruction for each struct field.
150 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 157 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
151 SmallVector<Value *, 2> Indexes; 158 SmallVector<Value *, 2> Indexes;
152 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); 159 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0)));
153 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index))); 160 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index)));
154 Value *GEP = CopyDebug(GetElementPtrInst::Create( 161 Value *GEP = CopyDebug(GetElementPtrInst::Create(
155 Store->getPointerOperand(), Indexes, 162 Store->getPointerOperand(), Indexes,
156 Store->getPointerOperand()->getName() + ".index", 163 Store->getPointerOperand()->getName() + ".index",
157 Store), Store); 164 Store), Store);
165 NeedsAnotherPass =
166 NeedsAnotherPass || DoAnotherPass(GEP->getType()->getContainedType(0));
167
158 SmallVector<unsigned, 1> EVIndexes; 168 SmallVector<unsigned, 1> EVIndexes;
159 EVIndexes.push_back(Index); 169 EVIndexes.push_back(Index);
160 Value *Field = ExtractValueInst::Create(Store->getValueOperand(), 170 Value *Field = ExtractValueInst::Create(Store->getValueOperand(),
161 EVIndexes, "", Store); 171 EVIndexes, "", Store);
162 StoreInst *NewStore = new StoreInst(Field, GEP, Store); 172 StoreInst *NewStore = new StoreInst(Field, GEP, Store);
163 ProcessLoadOrStoreAttrs(NewStore, Store); 173 ProcessLoadOrStoreAttrs(NewStore, Store);
164 } 174 }
165 Store->eraseFromParent(); 175 Store->eraseFromParent();
166 } 176 }
167 177
168 static void SplitUpLoad(LoadInst *Load) { 178 static void SplitUpLoad(LoadInst *Load, bool &NeedsAnotherPass) {
169 StructType *STy = cast<StructType>(Load->getType()); 179 StructType *STy = cast<StructType>(Load->getType());
170 Value *NewStruct = UndefValue::get(STy); 180 Value *NewStruct = UndefValue::get(STy);
171 181
172 // Create a separate load instruction for each struct field. 182 // Create a separate load instruction for each struct field.
173 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { 183 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) {
174 SmallVector<Value *, 2> Indexes; 184 SmallVector<Value *, 2> Indexes;
175 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0))); 185 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0)));
176 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index))); 186 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index)));
177 Value *GEP = CopyDebug( 187 Value *GEP = CopyDebug(
178 GetElementPtrInst::Create(Load->getPointerOperand(), Indexes, 188 GetElementPtrInst::Create(Load->getPointerOperand(), Indexes,
179 Load->getName() + ".index", Load), Load); 189 Load->getName() + ".index", Load), Load);
180 LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load); 190 LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load);
191
192 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewLoad);
181 ProcessLoadOrStoreAttrs(NewLoad, Load); 193 ProcessLoadOrStoreAttrs(NewLoad, Load);
182 194
183 // Reconstruct the struct value. 195 // Reconstruct the struct value.
184 SmallVector<unsigned, 1> EVIndexes; 196 SmallVector<unsigned, 1> EVIndexes;
185 EVIndexes.push_back(Index); 197 EVIndexes.push_back(Index);
186 NewStruct = CopyDebug( 198 NewStruct = CopyDebug(
187 InsertValueInst::Create(NewStruct, NewLoad, EVIndexes, 199 InsertValueInst::Create(NewStruct, NewLoad, EVIndexes,
188 Load->getName() + ".insert", Load), Load); 200 Load->getName() + ".insert", Load), Load);
189 } 201 }
190 Load->replaceAllUsesWith(NewStruct); 202 Load->replaceAllUsesWith(NewStruct);
191 Load->eraseFromParent(); 203 Load->eraseFromParent();
192 } 204 }
193 205
194 static void ExpandExtractValue(ExtractValueInst *EV) { 206 static void ExpandExtractValue(ExtractValueInst *EV, bool &NeedsAnotherPass) {
195 // Search for the insertvalue instruction that inserts the struct 207 // Search for the insertvalue instruction that inserts the struct
196 // field referenced by this extractvalue instruction. 208 // field referenced by this extractvalue instruction.
197 Value *StructVal = EV->getAggregateOperand(); 209 Value *StructVal = EV->getAggregateOperand();
198 Value *ResultField; 210 Value *ResultField = NULL;
JF 2014/12/06 23:52:13 nullptr
Richard Diamond 2014/12/09 04:33:13 Done.
211 size_t I = 0;
199 for (;;) { 212 for (;;) {
200 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(StructVal)) { 213 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(StructVal)) {
201 if (EV->getNumIndices() != 1 || IV->getNumIndices() != 1) { 214 size_t J = 0;
202 errs() << "Value: " << *EV << "\n"; 215 for (; I < EV->getIndices().size() && J < IV->getIndices().size();
203 errs() << "Value: " << *IV << "\n"; 216 ++J, ++I) {
204 report_fatal_error("ExpandStructRegs does not handle nested structs"); 217 const bool Equal = (EV->getIndices()[I] == IV->getIndices()[J]);
218 if (J + 1 == IV->getIndices().size() && Equal) {
219 if (I + 1 == EV->getIndices().size()) {
220 // Match
221 ResultField = IV->getInsertedValueOperand();
222 } else {
223 StructVal = IV->getInsertedValueOperand();
224 ++I;
225 }
226 break;
227 } else if (!Equal) {
228 // No match. Try the next struct value in the chain.
229 StructVal = IV->getAggregateOperand();
230 break;
231 }
205 } 232 }
206 if (EV->getIndices()[0] == IV->getIndices()[0]) { 233 if (ResultField != NULL) {
JF 2014/12/06 23:52:13 if (ResultField)
Richard Diamond 2014/12/09 04:33:16 Done.
207 ResultField = IV->getInsertedValueOperand(); 234 break;
235 } else if (I == EV->getIndices().size()) {
236 // We've found an insertvalue that inserts at one or more levels deeper
237 // than this extractvalue.
238 NeedsAnotherPass = true;
239 SmallVector<unsigned, 4> Indices(IV->getIndices().begin() + J,
240 IV->getIndices().end());
241
242 InsertValueInst *Insert = InsertValueInst::Create(
243 UndefValue::get(EV->getType()), IV->getInsertedValueOperand(),
244 Indices, "", EV);
245 ResultField = CopyDebug(Insert, EV);
208 break; 246 break;
209 } 247 }
210 // No match. Try the next struct value in the chain.
211 StructVal = IV->getAggregateOperand();
212 } else if (Constant *C = dyn_cast<Constant>(StructVal)) { 248 } else if (Constant *C = dyn_cast<Constant>(StructVal)) {
213 ResultField = ConstantExpr::getExtractValue(C, EV->getIndices()); 249 SmallVector<unsigned, 4> Indices(EV->getIndices().begin() + I,
250 EV->getIndices().end());
251 ResultField = ConstantExpr::getExtractValue(C, Indices);
252 break;
253 } else if (isa<LoadInst>(StructVal)) {
254 ResultField = StructVal;
214 break; 255 break;
215 } else { 256 } else {
216 errs() << "Value: " << *StructVal << "\n"; 257 errs() << "Value: " << *StructVal << "\n";
217 report_fatal_error("Unrecognized struct value"); 258 report_fatal_error("Unrecognized struct value");
218 } 259 }
219 } 260 }
261
262 assert(ResultField != NULL);
JF 2014/12/06 23:52:13 assert(ResultField);
Richard Diamond 2014/12/09 04:33:18 Done.
220 EV->replaceAllUsesWith(ResultField); 263 EV->replaceAllUsesWith(ResultField);
221 EV->eraseFromParent(); 264 EV->eraseFromParent();
222 } 265 }
223 266
267 static bool ExpandExtractValues(Function &Func) {
268 bool Changed = false;
269 bool NeedsAnotherPass = false;
270
271 // Expand out all the extractvalue instructions. Also collect up
272 // the insertvalue instructions for later deletion so that we do not
273 // need to make extra passes across the whole function.
274 SmallVector<Instruction *, 10> ToErase;
275 for (Function::iterator BB = Func.begin(), E = Func.end(); BB != E; ++BB) {
276 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E;) {
JF 2014/12/06 23:52:13 C++11 range-based for here.
Richard Diamond 2014/12/09 04:33:11 The inner loop can't use a range-based for loop be
277 Instruction *Inst = Iter++;
278 if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Inst)) {
279 ExpandExtractValue(EV, NeedsAnotherPass);
280 Changed = true;
281 } else if (isa<InsertValueInst>(Inst)) {
282 ToErase.push_back(Inst);
283 Changed = true;
284 }
285 }
286 }
287
288 if (!NeedsAnotherPass) {
289 // Delete the insertvalue instructions. These can reference each
290 // other, so we must do dropAllReferences() before doing
291 // eraseFromParent(), otherwise we will try to erase instructions
292 // that are still referenced.
293 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
294 E = ToErase.end();
295 I != E; ++I) {
JF 2014/12/06 23:52:13 Range-based.
Richard Diamond 2014/12/09 04:33:17 Done.
296 (*I)->dropAllReferences();
297 }
298 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
299 E = ToErase.end();
300 I != E; ++I) {
JF 2014/12/06 23:52:13 Range-based.
Richard Diamond 2014/12/09 04:33:12 Done.
301 (*I)->eraseFromParent();
302 }
303 }
304
305 return (NeedsAnotherPass && ExpandExtractValues(Func)) || Changed;
306 }
307
224 bool ExpandStructRegs::runOnFunction(Function &Func) { 308 bool ExpandStructRegs::runOnFunction(Function &Func) {
225 bool Changed = false; 309 bool Changed = false;
310 bool NeedsAnotherPass = false;
226 311
227 // Split up aggregate loads, stores and phi nodes into operations on 312 // Split up aggregate loads, stores and phi nodes into operations on
228 // scalar types. This inserts extractvalue and insertvalue 313 // scalar types. This inserts extractvalue and insertvalue
229 // instructions which we will expand out later. 314 // instructions which we will expand out later.
230 for (Function::iterator BB = Func.begin(), E = Func.end(); 315 for (Function::iterator BB = Func.begin(), E = Func.end();
231 BB != E; ++BB) { 316 BB != E; ++BB) {
232 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); 317 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
233 Iter != E; ) { 318 Iter != E; ) {
234 Instruction *Inst = Iter++; 319 Instruction *Inst = Iter++;
235 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 320 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
236 if (Store->getValueOperand()->getType()->isStructTy()) { 321 if (Store->getValueOperand()->getType()->isStructTy()) {
237 SplitUpStore(Store); 322 SplitUpStore(Store, NeedsAnotherPass);
238 Changed = true; 323 Changed = true;
239 } 324 }
240 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 325 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
241 if (Load->getType()->isStructTy()) { 326 if (Load->getType()->isStructTy()) {
242 SplitUpLoad(Load); 327 SplitUpLoad(Load, NeedsAnotherPass);
243 Changed = true; 328 Changed = true;
244 } 329 }
245 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { 330 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
246 if (Phi->getType()->isStructTy()) { 331 if (Phi->getType()->isStructTy()) {
247 SplitUpPHINode(Phi); 332 SplitUpPHINode(Phi, NeedsAnotherPass);
248 Changed = true; 333 Changed = true;
249 } 334 }
250 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) { 335 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) {
251 if (Select->getType()->isStructTy()) { 336 if (Select->getType()->isStructTy()) {
252 SplitUpSelect(Select); 337 SplitUpSelect(Select, NeedsAnotherPass);
253 Changed = true; 338 Changed = true;
254 } 339 }
255 } 340 }
256 } 341 }
257 } 342 }
258 343
259 // Expand out all the extractvalue instructions. Also collect up 344 if (!NeedsAnotherPass) {
260 // the insertvalue instructions for later deletion so that we do not 345 Changed = ExpandExtractValues(Func) || Changed;
261 // need to make extra passes across the whole function.
262 SmallVector<Instruction *, 10> ToErase;
263 for (Function::iterator BB = Func.begin(), E = Func.end();
264 BB != E; ++BB) {
265 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
266 Iter != E; ) {
267 Instruction *Inst = Iter++;
268 if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Inst)) {
269 ExpandExtractValue(EV);
270 Changed = true;
271 } else if (isa<InsertValueInst>(Inst)) {
272 ToErase.push_back(Inst);
273 Changed = true;
274 }
275 }
276 } 346 }
277 // Delete the insertvalue instructions. These can reference each 347
278 // other, so we must do dropAllReferences() before doing 348 return (NeedsAnotherPass && runOnFunction(Func)) || Changed;
279 // eraseFromParent(), otherwise we will try to erase instructions
280 // that are still referenced.
281 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
282 E = ToErase.end();
283 I != E; ++I) {
284 (*I)->dropAllReferences();
285 }
286 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
287 E = ToErase.end();
288 I != E; ++I) {
289 (*I)->eraseFromParent();
290 }
291 return Changed;
292 } 349 }
293 350
294 FunctionPass *llvm::createExpandStructRegsPass() { 351 FunctionPass *llvm::createExpandStructRegsPass() {
295 return new ExpandStructRegs(); 352 return new ExpandStructRegs();
296 } 353 }
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