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 |