| 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 |