| OLD | NEW |
| 1 //===- SimplifyAllocas.cpp - Simplify allocas to arrays of bytes --===// | 1 //===- SimplifyAllocas.cpp - Simplify allocas to arrays of bytes --===// |
| 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 // Simplify all allocas into allocas of byte arrays. | 10 // Simplify all allocas into allocas of byte arrays. |
| 11 // | 11 // |
| 12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
| 13 | 13 |
| 14 #include "llvm/IR/Constants.h" | 14 #include "llvm/IR/Constants.h" |
| 15 #include "llvm/IR/DataLayout.h" | 15 #include "llvm/IR/DataLayout.h" |
| 16 #include "llvm/IR/Function.h" | 16 #include "llvm/IR/Function.h" |
| 17 #include "llvm/IR/Instructions.h" | 17 #include "llvm/IR/Instructions.h" |
| 18 #include "llvm/IR/IntrinsicInst.h" |
| 18 #include "llvm/IR/Module.h" | 19 #include "llvm/IR/Module.h" |
| 19 #include "llvm/Transforms/NaCl.h" | 20 #include "llvm/Transforms/NaCl.h" |
| 20 | 21 #include "llvm/Support/raw_ostream.h" |
| 21 using namespace llvm; | 22 using namespace llvm; |
| 22 namespace { | 23 namespace { |
| 23 class SimplifyAllocas : public BasicBlockPass { | 24 class SimplifyAllocas : public BasicBlockPass { |
| 24 public: | 25 public: |
| 25 static char ID; // Pass identification, replacement for typeid | 26 static char ID; // Pass identification, replacement for typeid |
| 26 SimplifyAllocas() | 27 SimplifyAllocas() |
| 27 : BasicBlockPass(ID), Initialized(false), M(nullptr), IntPtrType(nullptr), | 28 : BasicBlockPass(ID), Initialized(false), M(nullptr), IntPtrType(nullptr), |
| 28 Int8Type(nullptr), DL(nullptr) { | 29 Int8Type(nullptr), DL(nullptr) { |
| 29 initializeSimplifyAllocasPass(*PassRegistry::getPassRegistry()); | 30 initializeSimplifyAllocasPass(*PassRegistry::getPassRegistry()); |
| 30 } | 31 } |
| 31 | 32 |
| 32 private: | 33 private: |
| 33 bool Initialized; | 34 bool Initialized; |
| 34 const Module *M; | 35 const Module *M; |
| 35 Type *IntPtrType; | 36 Type *IntPtrType; |
| 36 Type *Int8Type; | 37 Type *Int8Type; |
| 37 const DataLayout *DL; | 38 const DataLayout *DL; |
| 38 | 39 |
| 39 using llvm::Pass::doInitialization; | 40 using llvm::Pass::doInitialization; |
| 40 bool doInitialization(Function &F) override { | 41 bool doInitialization(Function &F) override { |
| 41 if (!Initialized) { | 42 if (!Initialized) { |
| 42 M = F.getParent(); | 43 M = F.getParent(); |
| 43 DL = M->getDataLayout(); | 44 DL = &M->getDataLayout(); |
| 44 IntPtrType = DL->getIntPtrType(M->getContext()); | 45 IntPtrType = DL->getIntPtrType(M->getContext()); |
| 45 Int8Type = Type::getInt8Ty(M->getContext()); | 46 Int8Type = Type::getInt8Ty(M->getContext()); |
| 46 Initialized = true; | 47 Initialized = true; |
| 47 return true; | 48 return true; |
| 48 } | 49 } |
| 49 return false; | 50 return false; |
| 50 } | 51 } |
| 51 | 52 |
| 52 bool runOnBasicBlock(BasicBlock &BB) override { | 53 bool runOnBasicBlock(BasicBlock &BB) override { |
| 53 bool Changed = false; | 54 bool Changed = false; |
| 54 for (BasicBlock::iterator I = BB.getFirstInsertionPt(), E = BB.end(); | 55 for (BasicBlock::iterator I = BB.getFirstInsertionPt(), E = BB.end(); |
| 55 I != E;) { | 56 I != E;) { |
| 56 if (AllocaInst *Alloca = dyn_cast<AllocaInst>(I++)) { | 57 Instruction *Inst = &*I++; |
| 58 if (AllocaInst *Alloca = dyn_cast<AllocaInst>(Inst)) { |
| 57 Changed = true; | 59 Changed = true; |
| 58 Type *ElementTy = Alloca->getType()->getPointerElementType(); | 60 Type *ElementTy = Alloca->getType()->getPointerElementType(); |
| 59 Constant *ElementSize = | 61 Constant *ElementSize = |
| 60 ConstantInt::get(IntPtrType, DL->getTypeAllocSize(ElementTy)); | 62 ConstantInt::get(IntPtrType, DL->getTypeAllocSize(ElementTy)); |
| 61 // Expand out alloca's built-in multiplication. | 63 // Expand out alloca's built-in multiplication. |
| 62 Value *MulSize; | 64 Value *MulSize; |
| 63 if (ConstantInt *C = dyn_cast<ConstantInt>(Alloca->getArraySize())) { | 65 if (ConstantInt *C = dyn_cast<ConstantInt>(Alloca->getArraySize())) { |
| 64 const APInt Value = | 66 const APInt Value = |
| 65 C->getValue().zextOrTrunc(IntPtrType->getScalarSizeInBits()); | 67 C->getValue().zextOrTrunc(IntPtrType->getScalarSizeInBits()); |
| 66 MulSize = ConstantExpr::getMul(ElementSize, | 68 MulSize = ConstantExpr::getMul(ElementSize, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 86 AllocaInst *Tmp = | 88 AllocaInst *Tmp = |
| 87 new AllocaInst(Int8Type, MulSize, Alignment, "", Alloca); | 89 new AllocaInst(Int8Type, MulSize, Alignment, "", Alloca); |
| 88 CopyDebug(Tmp, Alloca); | 90 CopyDebug(Tmp, Alloca); |
| 89 Tmp->takeName(Alloca); | 91 Tmp->takeName(Alloca); |
| 90 BitCastInst *BC = new BitCastInst(Tmp, Alloca->getType(), | 92 BitCastInst *BC = new BitCastInst(Tmp, Alloca->getType(), |
| 91 Tmp->getName() + ".bc", Alloca); | 93 Tmp->getName() + ".bc", Alloca); |
| 92 CopyDebug(BC, Alloca); | 94 CopyDebug(BC, Alloca); |
| 93 Alloca->replaceAllUsesWith(BC); | 95 Alloca->replaceAllUsesWith(BC); |
| 94 Alloca->eraseFromParent(); | 96 Alloca->eraseFromParent(); |
| 95 } | 97 } |
| 98 else if (auto *Call = dyn_cast<IntrinsicInst>(Inst)) { |
| 99 if (Call->getIntrinsicID() == Intrinsic::dbg_declare) { |
| 100 // dbg.declare's first argument is a special metadata that wraps a |
| 101 // value, and RAUW works on those. It is supposed to refer to the |
| 102 // alloca that represents the variable's storage, but the alloca |
| 103 // simplification may have RAUWed it to use the bitcast. |
| 104 // Fix it up here by recreating the metadata to use the new alloca. |
| 105 auto *MV = cast<MetadataAsValue>(Call->getArgOperand(0)); |
| 106 // Sometimes dbg.declare points to an argument instead of an alloca. |
| 107 if (auto *VM = dyn_cast<ValueAsMetadata>(MV->getMetadata())) { |
| 108 if (auto *BCInst = dyn_cast<BitCastInst>(VM->getValue())) { |
| 109 Value *CastSrc = BCInst->getOperand(0); |
| 110 assert(isa<AllocaInst>(CastSrc)); |
| 111 Call->setArgOperand( |
| 112 0, |
| 113 MetadataAsValue::get(Inst->getContext(), |
| 114 ValueAsMetadata::get(CastSrc))); |
| 115 Changed = true; |
| 116 } |
| 117 } |
| 118 } |
| 119 } |
| 96 } | 120 } |
| 97 return Changed; | 121 return Changed; |
| 98 } | 122 } |
| 99 }; | 123 }; |
| 100 } | 124 } |
| 101 char SimplifyAllocas::ID = 0; | 125 char SimplifyAllocas::ID = 0; |
| 102 | 126 |
| 103 INITIALIZE_PASS(SimplifyAllocas, "simplify-allocas", | 127 INITIALIZE_PASS(SimplifyAllocas, "simplify-allocas", |
| 104 "Simplify allocas to arrays of bytes", false, false) | 128 "Simplify allocas to arrays of bytes", false, false) |
| 105 | 129 |
| 106 BasicBlockPass *llvm::createSimplifyAllocasPass() { | 130 BasicBlockPass *llvm::createSimplifyAllocasPass() { |
| 107 return new SimplifyAllocas(); | 131 return new SimplifyAllocas(); |
| 108 } | 132 } |
| OLD | NEW |