OLD | NEW |
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 |
(...skipping 25 matching lines...) Expand all Loading... |
36 // padding fields are not defined anyway. | 36 // padding fields are not defined anyway. |
37 // | 37 // |
38 //===----------------------------------------------------------------------===// | 38 //===----------------------------------------------------------------------===// |
39 | 39 |
40 #include "llvm/ADT/SmallVector.h" | 40 #include "llvm/ADT/SmallVector.h" |
41 #include "llvm/IR/Constants.h" | 41 #include "llvm/IR/Constants.h" |
42 #include "llvm/IR/DataLayout.h" | 42 #include "llvm/IR/DataLayout.h" |
43 #include "llvm/IR/Function.h" | 43 #include "llvm/IR/Function.h" |
44 #include "llvm/IR/Instructions.h" | 44 #include "llvm/IR/Instructions.h" |
45 #include "llvm/IR/IntrinsicInst.h" | 45 #include "llvm/IR/IntrinsicInst.h" |
| 46 #include "llvm/IR/Module.h" |
46 #include "llvm/Pass.h" | 47 #include "llvm/Pass.h" |
47 #include "llvm/Support/Debug.h" | 48 #include "llvm/Support/Debug.h" |
48 #include "llvm/Support/raw_ostream.h" | 49 #include "llvm/Support/raw_ostream.h" |
49 #include "llvm/Transforms/NaCl.h" | 50 #include "llvm/Transforms/NaCl.h" |
50 | 51 |
51 #define DEBUG_TYPE "expand-struct-regs" | 52 #define DEBUG_TYPE "expand-struct-regs" |
52 | 53 |
53 using namespace llvm; | 54 using namespace llvm; |
54 | 55 |
55 namespace { | 56 namespace { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 Select); | 145 Select); |
145 } | 146 } |
146 Select->replaceAllUsesWith(NewStruct); | 147 Select->replaceAllUsesWith(NewStruct); |
147 Select->eraseFromParent(); | 148 Select->eraseFromParent(); |
148 | 149 |
149 return NeedsAnotherPass; | 150 return NeedsAnotherPass; |
150 } | 151 } |
151 | 152 |
152 template <class InstType> | 153 template <class InstType> |
153 static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src, | 154 static void ProcessLoadOrStoreAttrs(InstType *Dest, InstType *Src, |
154 StructType* STy, const unsigned Index) { | 155 StructType* STy, const unsigned Index, |
| 156 const DataLayout *DL) { |
155 CopyDebug(Dest, Src); | 157 CopyDebug(Dest, Src); |
156 Dest->setVolatile(Src->isVolatile()); | 158 Dest->setVolatile(Src->isVolatile()); |
157 if (Src->isAtomic()) { | 159 if (Src->isAtomic()) { |
158 errs() << "Use: " << *Src << "\n"; | 160 errs() << "Use: " << *Src << "\n"; |
159 report_fatal_error("Atomic struct loads/stores not supported"); | 161 report_fatal_error("Atomic struct loads/stores not supported"); |
160 } | 162 } |
161 | 163 |
162 if (!Src->getAlignment()) { | 164 if (!Src->getAlignment()) { |
163 return; | 165 return; |
164 } | 166 } |
165 | 167 |
166 const DataLayout *DL = Src->getParent()->getDataLayout(); | |
167 if (!DL) { | |
168 report_fatal_error("Need DataLayout"); | |
169 } | |
170 const StructLayout *SL = DL->getStructLayout(STy); | 168 const StructLayout *SL = DL->getStructLayout(STy); |
171 const unsigned Alignment = Src->getAlignment(); | 169 const unsigned Alignment = Src->getAlignment(); |
172 Dest->setAlignment(MinAlign(Alignment, SL->getElementOffset(Index))); | 170 Dest->setAlignment(MinAlign(Alignment, SL->getElementOffset(Index))); |
173 } | 171 } |
174 | 172 |
175 static bool SplitUpStore(StoreInst *Store) { | 173 static bool SplitUpStore(StoreInst *Store, const DataLayout *DL) { |
176 StructType *STy = cast<StructType>(Store->getValueOperand()->getType()); | 174 StructType *STy = cast<StructType>(Store->getValueOperand()->getType()); |
177 | 175 |
178 bool NeedsAnotherPass = false; | 176 bool NeedsAnotherPass = false; |
179 // Create a separate store instruction for each struct field. | 177 // Create a separate store instruction for each struct field. |
180 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { | 178 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { |
181 SmallVector<Value *, 2> Indexes; | 179 SmallVector<Value *, 2> Indexes; |
182 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); | 180 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, 0))); |
183 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index))); | 181 Indexes.push_back(ConstantInt::get(Store->getContext(), APInt(32, Index))); |
184 Value *GEP = | 182 Value *GEP = |
185 CopyDebug(GetElementPtrInst::Create( | 183 CopyDebug(GetElementPtrInst::Create( |
| 184 STy, |
186 Store->getPointerOperand(), Indexes, | 185 Store->getPointerOperand(), Indexes, |
187 Store->getPointerOperand()->getName() + ".index", Store), | 186 Store->getPointerOperand()->getName() + ".index", Store), |
188 Store); | 187 Store); |
189 NeedsAnotherPass = | 188 NeedsAnotherPass = |
190 NeedsAnotherPass || DoAnotherPass(GEP->getType()->getContainedType(0)); | 189 NeedsAnotherPass || DoAnotherPass(GEP->getType()->getContainedType(0)); |
191 | 190 |
192 SmallVector<unsigned, 1> EVIndexes; | 191 SmallVector<unsigned, 1> EVIndexes; |
193 EVIndexes.push_back(Index); | 192 EVIndexes.push_back(Index); |
194 Value *Field = ExtractValueInst::Create(Store->getValueOperand(), EVIndexes, | 193 Value *Field = ExtractValueInst::Create(Store->getValueOperand(), EVIndexes, |
195 "", Store); | 194 "", Store); |
196 StoreInst *NewStore = new StoreInst(Field, GEP, Store); | 195 StoreInst *NewStore = new StoreInst(Field, GEP, Store); |
197 ProcessLoadOrStoreAttrs(NewStore, Store, STy, Index); | 196 ProcessLoadOrStoreAttrs(NewStore, Store, STy, Index, DL); |
198 } | 197 } |
199 Store->eraseFromParent(); | 198 Store->eraseFromParent(); |
200 | 199 |
201 return NeedsAnotherPass; | 200 return NeedsAnotherPass; |
202 } | 201 } |
203 | 202 |
204 static bool SplitUpLoad(LoadInst *Load) { | 203 static bool SplitUpLoad(LoadInst *Load, const DataLayout *DL) { |
205 StructType *STy = cast<StructType>(Load->getType()); | 204 StructType *STy = cast<StructType>(Load->getType()); |
206 Value *NewStruct = UndefValue::get(STy); | 205 Value *NewStruct = UndefValue::get(STy); |
207 | 206 |
208 bool NeedsAnotherPass = false; | 207 bool NeedsAnotherPass = false; |
209 // Create a separate load instruction for each struct field. | 208 // Create a separate load instruction for each struct field. |
210 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { | 209 for (unsigned Index = 0; Index < STy->getNumElements(); ++Index) { |
211 SmallVector<Value *, 2> Indexes; | 210 SmallVector<Value *, 2> Indexes; |
212 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0))); | 211 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, 0))); |
213 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index))); | 212 Indexes.push_back(ConstantInt::get(Load->getContext(), APInt(32, Index))); |
214 Value *GEP = | 213 Value *GEP = |
215 CopyDebug(GetElementPtrInst::Create(Load->getPointerOperand(), Indexes, | 214 CopyDebug(GetElementPtrInst::Create(STy, |
| 215 Load->getPointerOperand(), Indexes, |
216 Load->getName() + ".index", Load), | 216 Load->getName() + ".index", Load), |
217 Load); | 217 Load); |
218 LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load); | 218 LoadInst *NewLoad = new LoadInst(GEP, Load->getName() + ".field", Load); |
219 | 219 |
220 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewLoad); | 220 NeedsAnotherPass = NeedsAnotherPass || DoAnotherPass(NewLoad); |
221 ProcessLoadOrStoreAttrs(NewLoad, Load, STy, Index); | 221 ProcessLoadOrStoreAttrs(NewLoad, Load, STy, Index, DL); |
222 | 222 |
223 // Reconstruct the struct value. | 223 // Reconstruct the struct value. |
224 SmallVector<unsigned, 1> EVIndexes; | 224 SmallVector<unsigned, 1> EVIndexes; |
225 EVIndexes.push_back(Index); | 225 EVIndexes.push_back(Index); |
226 NewStruct = | 226 NewStruct = |
227 CopyDebug(InsertValueInst::Create(NewStruct, NewLoad, EVIndexes, | 227 CopyDebug(InsertValueInst::Create(NewStruct, NewLoad, EVIndexes, |
228 Load->getName() + ".insert", Load), | 228 Load->getName() + ".insert", Load), |
229 Load); | 229 Load); |
230 } | 230 } |
231 Load->replaceAllUsesWith(NewStruct); | 231 Load->replaceAllUsesWith(NewStruct); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 for (Instruction *I : ToErase) { | 418 for (Instruction *I : ToErase) { |
419 I->eraseFromParent(); | 419 I->eraseFromParent(); |
420 } | 420 } |
421 | 421 |
422 return Changed; | 422 return Changed; |
423 } | 423 } |
424 | 424 |
425 bool ExpandStructRegs::runOnFunction(Function &Func) { | 425 bool ExpandStructRegs::runOnFunction(Function &Func) { |
426 bool Changed = false; | 426 bool Changed = false; |
427 bool NeedsAnotherPass; | 427 bool NeedsAnotherPass; |
| 428 const DataLayout *DL = &Func.getParent()->getDataLayout(); |
428 | 429 |
429 do { | 430 do { |
430 NeedsAnotherPass = false; | 431 NeedsAnotherPass = false; |
431 // Split up aggregate loads, stores and phi nodes into operations on | 432 // Split up aggregate loads, stores and phi nodes into operations on |
432 // scalar types. This inserts extractvalue and insertvalue | 433 // scalar types. This inserts extractvalue and insertvalue |
433 // instructions which we will expand out later. | 434 // instructions which we will expand out later. |
434 for (Function::iterator BB = Func.begin(), E = Func.end(); BB != E; ++BB) { | 435 for (Function::iterator BB = Func.begin(), E = Func.end(); BB != E; ++BB) { |
435 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E;) { | 436 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E;) { |
436 Instruction *Inst = Iter++; | 437 Instruction *Inst = Iter++; |
437 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { | 438 if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { |
438 if (Store->getValueOperand()->getType()->isStructTy()) { | 439 if (Store->getValueOperand()->getType()->isStructTy()) { |
439 NeedsAnotherPass |= SplitUpStore(Store); | 440 NeedsAnotherPass |= SplitUpStore(Store, DL); |
440 Changed = true; | 441 Changed = true; |
441 } | 442 } |
442 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { | 443 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { |
443 if (Load->getType()->isStructTy()) { | 444 if (Load->getType()->isStructTy()) { |
444 NeedsAnotherPass |= SplitUpLoad(Load); | 445 NeedsAnotherPass |= SplitUpLoad(Load, DL); |
445 Changed = true; | 446 Changed = true; |
446 } | 447 } |
447 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { | 448 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) { |
448 if (Phi->getType()->isStructTy()) { | 449 if (Phi->getType()->isStructTy()) { |
449 NeedsAnotherPass |= SplitUpPHINode(Phi); | 450 NeedsAnotherPass |= SplitUpPHINode(Phi); |
450 Changed = true; | 451 Changed = true; |
451 } | 452 } |
452 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) { | 453 } else if (SelectInst *Select = dyn_cast<SelectInst>(Inst)) { |
453 if (Select->getType()->isStructTy()) { | 454 if (Select->getType()->isStructTy()) { |
454 NeedsAnotherPass |= SplitUpSelect(Select); | 455 NeedsAnotherPass |= SplitUpSelect(Select); |
455 Changed = true; | 456 Changed = true; |
456 } | 457 } |
457 } | 458 } |
458 } | 459 } |
459 } | 460 } |
460 } while (NeedsAnotherPass); | 461 } while (NeedsAnotherPass); |
461 | 462 |
462 Changed |= ExpandExtractValues(Func); | 463 Changed |= ExpandExtractValues(Func); |
463 | 464 |
464 return Changed; | 465 return Changed; |
465 } | 466 } |
466 | 467 |
467 FunctionPass *llvm::createExpandStructRegsPass() { | 468 FunctionPass *llvm::createExpandStructRegsPass() { |
468 return new ExpandStructRegs(); | 469 return new ExpandStructRegs(); |
469 } | 470 } |
OLD | NEW |