OLD | NEW |
---|---|
(Empty) | |
1 //===- ConstantInsertExtractElementIndex.cpp - Insert/Extract element -----===// | |
2 // | |
3 // The LLVM Compiler Infrastructure | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // Transform all InsertElement and ExtractElement with non-constant or | |
11 // out-of-bounds indices into stack accesses. This moves all undefined | |
12 // behavior to the stack, making InsertElement and ExtractElement | |
13 // well-defined. | |
14 // | |
15 //===----------------------------------------------------------------------===// | |
16 | |
17 #include "llvm/IR/DataLayout.h" | |
18 #include "llvm/IR/IRBuilder.h" | |
19 #include "llvm/IR/Instruction.h" | |
20 #include "llvm/IR/Instructions.h" | |
21 #include "llvm/IR/Module.h" | |
22 #include "llvm/Pass.h" | |
23 #include "llvm/Transforms/NaCl.h" | |
24 | |
25 #include <algorithm> | |
26 | |
27 using namespace llvm; | |
28 | |
29 namespace { | |
30 class ConstantInsertExtractElementIndex : public BasicBlockPass { | |
31 public: | |
32 static char ID; // Pass identification, replacement for typeid | |
33 ConstantInsertExtractElementIndex() : BasicBlockPass(ID), M(0), TD(0) { | |
34 initializeConstantInsertExtractElementIndexPass( | |
35 *PassRegistry::getPassRegistry()); | |
36 } | |
37 virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
38 AU.addRequired<DataLayout>(); | |
39 BasicBlockPass::getAnalysisUsage(AU); | |
40 } | |
41 virtual bool doInitialization(Module &Mod) { | |
42 M = &Mod; | |
43 return false; // Unchanged. | |
44 } | |
45 virtual bool runOnBasicBlock(BasicBlock &BB); | |
46 | |
47 private: | |
48 typedef SmallVector<Instruction *, 8> Instructions; | |
49 const Module *M; | |
50 const DataLayout *TD; | |
jvoung (off chromium)
2014/04/04 23:20:21
I think TargetData was renamed to DataLayout. Some
JF
2014/04/15 01:52:27
Done, in this and other files.
| |
51 | |
52 /// Get the index of an InsertElement or ExtractElement instruction, or null. | |
53 static Value *getIdx(const Instruction *I); | |
54 | |
55 void findInvalidInsertExtractElements(const BasicBlock &BB, | |
jvoung (off chromium)
2014/04/04 23:20:21
nit: It's not actually invalid so "Invalid" should
JF
2014/04/15 01:52:27
Done.
| |
56 Instructions &BadVectorIdx) const; | |
57 void fixInvalidInsertExtractElements(BasicBlock &BB, | |
58 const Instructions &BadVectorIdx) const; | |
59 }; | |
60 } | |
61 | |
62 char ConstantInsertExtractElementIndex::ID = 0; | |
63 INITIALIZE_PASS( | |
64 ConstantInsertExtractElementIndex, "constant-insert-extract-element-index", | |
65 "Force insert and extract vector elemement to always be in bounds", false, | |
jvoung (off chromium)
2014/04/04 23:20:21
elemement -> element
This doesn't really force th
JF
2014/04/15 01:52:27
Correct. I don't mind doing what you suggest inste
jvoung (off chromium)
2014/04/16 00:10:27
Sure, I'm okay with leaving this as is for now, si
| |
66 false) | |
67 | |
68 Value *ConstantInsertExtractElementIndex::getIdx(const Instruction *I) { | |
jvoung (off chromium)
2014/04/04 23:20:21
Could have just been a static function that's not
JF
2014/04/15 01:52:27
Done.
| |
69 switch (I->getOpcode()) { | |
70 default: return 0; | |
Jim Stichnoth
2014/04/04 23:08:17
I don't know of a style guide reference, but could
JF
2014/04/15 01:52:27
Done.
| |
71 case Instruction::InsertElement: return I->getOperand(2); | |
72 case Instruction::ExtractElement: return I->getOperand(1); | |
73 } | |
74 } | |
75 | |
76 void ConstantInsertExtractElementIndex::findInvalidInsertExtractElements( | |
77 const BasicBlock &BB, Instructions &BadVectorIdx) const { | |
jvoung (off chromium)
2014/04/04 23:20:21
nit: BadVectorIdx sounds like it's a single index,
JF
2014/04/15 01:52:27
Done.
| |
78 for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; | |
79 ++BBI) { | |
80 const Instruction *I = &*BBI; | |
81 Value *Idx = getIdx(I); | |
82 if (!Idx) | |
83 // Not and InsertElement or ExtractElement, ignore the instruction. | |
Jim Stichnoth
2014/04/04 23:08:17
and --> an
JF
2014/04/15 01:52:27
Done.
| |
84 continue; | |
85 if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) { | |
86 unsigned NumElements = | |
87 cast<VectorType>(I->getOperand(0)->getType())->getNumElements(); | |
88 if (CI->getValue().ult(NumElements)) | |
89 // Index is constant in-range for the vector type, keep as-is. | |
90 continue; | |
91 } | |
92 BadVectorIdx.push_back(const_cast<Instruction *>(I)); | |
Jim Stichnoth
2014/04/04 23:08:17
I trust const_cast is actually necessary :(
JF
2014/04/15 01:52:27
Yeah, I wanted to go all const-correctness, but so
| |
93 } | |
94 } | |
95 | |
96 void ConstantInsertExtractElementIndex::fixInvalidInsertExtractElements( | |
97 BasicBlock &BB, const Instructions &BadVectorIdx) const { | |
98 for (Instructions::const_iterator IB = BadVectorIdx.begin(), | |
99 IE = BadVectorIdx.end(); | |
100 IB != IE; ++IB) { | |
101 Instruction *I = *IB; | |
102 Value *Vec = I->getOperand(0); | |
103 Value *Idx = getIdx(I); | |
104 VectorType *VecTy = cast<VectorType>(Vec->getType()); | |
105 Type *ElemTy = VecTy->getElementType(); | |
106 unsigned ElemAlign = TD->getPrefTypeAlignment(ElemTy); | |
107 unsigned VecAlign = std::max(ElemAlign, TD->getPrefTypeAlignment(VecTy)); | |
108 | |
109 IRBuilder<> IRB(I); | |
110 AllocaInst *Alloca = IRB.CreateAlloca( | |
111 ElemTy, ConstantInt::get(Type::getInt32Ty(M->getContext()), | |
jvoung (off chromium)
2014/04/04 23:20:21
Instead of ElemTy, have the alloca be i8, and mult
jvoung (off chromium)
2014/04/07 15:40:11
n/m about this point -- it'll be handled by the Re
JF
2014/04/15 01:52:27
Yeah I wanted to do the "right" thing for LLVM, an
| |
112 VecTy->getNumElements())); | |
113 Alloca->setAlignment(VecAlign); | |
114 Value *AllocaAsVec = IRB.CreateBitCast(Alloca, VecTy->getPointerTo()); | |
115 IRB.CreateAlignedStore(Vec, AllocaAsVec, Alloca->getAlignment()); | |
116 Value *GEP = IRB.CreateGEP(Alloca, Idx); | |
117 | |
118 Value *Res; | |
119 switch (I->getOpcode()) { | |
120 default: | |
121 llvm_unreachable("expected InsertElement or ExtractElement"); | |
122 case Instruction::InsertElement: { | |
123 IRB.CreateAlignedStore(I->getOperand(1), GEP, ElemAlign); | |
124 Res = IRB.CreateAlignedLoad(AllocaAsVec, Alloca->getAlignment()); | |
125 break; | |
126 } | |
127 case Instruction::ExtractElement: { | |
128 Res = IRB.CreateAlignedLoad(GEP, ElemAlign); | |
129 break; | |
130 } | |
131 } | |
Jim Stichnoth
2014/04/04 23:08:17
Sorry, these two perfectly aligned braces really b
JF
2014/04/15 01:52:27
Done, though if they *had* been required I'd have
| |
132 | |
133 I->replaceAllUsesWith(Res); | |
jvoung (off chromium)
2014/04/04 23:20:21
CopyDebug?
JF
2014/04/15 01:52:27
I was going to fix IRBuilder instead so it copies
| |
134 I->eraseFromParent(); | |
135 } | |
136 } | |
137 | |
138 bool ConstantInsertExtractElementIndex::runOnBasicBlock(BasicBlock &BB) { | |
139 bool Changed = false; | |
140 if (!TD) | |
141 TD = &getAnalysis<DataLayout>(); | |
142 Instructions BadVectorIdx; | |
143 findInvalidInsertExtractElements(BB, BadVectorIdx); | |
144 if (!BadVectorIdx.empty()) { | |
145 Changed = true; | |
146 fixInvalidInsertExtractElements(BB, BadVectorIdx); | |
147 } | |
148 return Changed; | |
149 } | |
150 | |
151 BasicBlockPass *llvm::createConstantInsertExtractElementIndexPass() { | |
152 return new ConstantInsertExtractElementIndex(); | |
153 } | |
OLD | NEW |