OLD | NEW |
---|---|
(Empty) | |
1 //===- FixVectorLoadStoreAlignment.cpp - Vector load/store alignment ------===// | |
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 // Replace all vector load/store instructions by loads/stores of each | |
11 // individual element since different architectures have different | |
12 // faults on unaligned memory access. This pass pessimizes all vector | |
13 // memory accesses. It's expected that backends with more liberal | |
14 // alignment restrictions recognize this pattern and reconstruct the | |
15 // original vector load/store. | |
16 // | |
17 // Volatile load/store are broken up as allowed by C/C++, and atomic | |
18 // accesses cause errors at compile-time. | |
19 // | |
20 //===----------------------------------------------------------------------===// | |
21 | |
22 #include "llvm/IR/DataLayout.h" | |
23 #include "llvm/IR/IRBuilder.h" | |
24 #include "llvm/IR/Instruction.h" | |
25 #include "llvm/IR/Instructions.h" | |
26 #include "llvm/IR/Module.h" | |
27 #include "llvm/Pass.h" | |
28 #include "llvm/Support/MathExtras.h" | |
29 #include "llvm/Transforms/NaCl.h" | |
30 | |
31 using namespace llvm; | |
32 | |
33 namespace { | |
34 class FixVectorLoadStoreAlignment : public BasicBlockPass { | |
35 public: | |
36 static char ID; // Pass identification, replacement for typeid | |
37 FixVectorLoadStoreAlignment() : BasicBlockPass(ID), M(0), TD(0) { | |
38 initializeFixVectorLoadStoreAlignmentPass( | |
39 *PassRegistry::getPassRegistry()); | |
40 } | |
41 virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
42 AU.addRequired<DataLayout>(); | |
43 BasicBlockPass::getAnalysisUsage(AU); | |
44 } | |
45 virtual bool doInitialization(Module &Mod) { | |
46 M = &Mod; | |
47 return false; // Unchanged. | |
48 } | |
49 virtual bool runOnBasicBlock(BasicBlock &BB); | |
50 | |
51 private: | |
52 typedef SmallVector<Instruction *, 8> Instructions; | |
53 const Module *M; | |
54 const DataLayout *TD; | |
jvoung (off chromium)
2014/04/04 23:20:21
DL instead of TD
| |
55 | |
56 /// Some sub-classes of Instruction have a non-virtual function | |
57 /// indicating which operand is the pointer operand. This template | |
58 /// function returns the pointer operand's type, and required that | |
Jim Stichnoth
2014/04/04 23:08:17
required --> requires
JF
2014/04/15 01:52:27
Done.
| |
59 /// InstTy have a getPointerOperand function. | |
60 template <typename InstTy> | |
61 static PointerType *pointerOperandType(const InstTy *I) { | |
62 return cast<PointerType>(I->getPointerOperand()->getType()); | |
63 } | |
64 | |
65 /// Similar to pointerOperandType, this template function checks | |
66 /// whether the pointer operand is a pointer to a vector type. | |
67 template <typename InstTy> | |
68 static bool pointerOperandIsVectorPointer(const Instruction *I) { | |
69 return pointerOperandType(cast<InstTy>(I))->getElementType()->isVectorTy(); | |
70 } | |
71 | |
72 /// Returns true if one of the Instruction's operands is a pointer to | |
73 /// a vector type. This is more general than the above and assumes we | |
74 /// don't know which Instruction type is provided. | |
75 static bool hasVectorPointerOperand(const Instruction *I) { | |
76 for (User::const_op_iterator IB = I->op_begin(), IE = I->op_end(); IB != IE; | |
77 ++IB) | |
78 if (PointerType *PtrTy = dyn_cast<PointerType>((*IB)->getType())) | |
79 if (isa<VectorType>(PtrTy->getElementType())) | |
80 return true; | |
81 return false; | |
82 } | |
83 | |
84 void findVectorLoadStore(const BasicBlock &BB, Instructions &Loads, | |
85 Instructions &Stores) const; | |
86 void fixVectorLoadStoreAlignment(BasicBlock &BB, const Instructions &Loads, | |
87 const Instructions &Stores) const; | |
88 }; | |
89 } | |
Jim Stichnoth
2014/04/04 23:08:17
I prefer end-of-namespace comments (here and elsew
JF
2014/04/15 01:52:27
Done here and in other files.
| |
90 | |
91 char FixVectorLoadStoreAlignment::ID = 0; | |
92 INITIALIZE_PASS(FixVectorLoadStoreAlignment, "fix-vector-load-store-alignment", | |
93 "Replace vector load/store by loads/stores of each element", | |
94 false, false) | |
95 | |
96 void FixVectorLoadStoreAlignment::findVectorLoadStore( | |
97 const BasicBlock &BB, Instructions &Loads, Instructions &Stores) const { | |
98 for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; | |
99 ++BBI) { | |
100 Instruction *I = const_cast<Instruction *>(&*BBI); | |
101 switch (I->getOpcode()) { | |
102 case Instruction::Load: | |
103 if (pointerOperandIsVectorPointer<LoadInst>(I)) { | |
104 if (cast<LoadInst>(I)->isAtomic()) | |
105 report_fatal_error("unhandled: atomic vector store"); | |
106 Loads.push_back(I); | |
107 } | |
108 break; | |
109 case Instruction::Store: | |
110 if (pointerOperandIsVectorPointer<StoreInst>(I)) { | |
111 if (cast<StoreInst>(I)->isAtomic()) | |
112 report_fatal_error("unhandled: atomic vector store"); | |
113 Stores.push_back(I); | |
114 } | |
115 break; | |
116 case Instruction::Alloca: | |
117 case Instruction::GetElementPtr: | |
jvoung (off chromium)
2014/04/04 23:20:21
GetElementPtr is just arithmetic so doesn't touch
JF
2014/04/15 01:52:27
Hmm, I'm not sure why I had this there, I'll remov
| |
118 case Instruction::Fence: | |
119 case Instruction::VAArg: | |
jvoung (off chromium)
2014/04/04 23:20:21
Any more detail on why these are left as-is?
For
JF
2014/04/15 01:52:27
I added a comment, it's based on mayReadOrWriteMem
| |
120 // Leave these memory operations as-is, even when they deal with | |
121 // vectors. | |
122 break; | |
123 case Instruction::Call: | |
124 case Instruction::Invoke: | |
125 // Call/invoke don't touch memory per-se, leave them as-is. | |
126 break; | |
127 case Instruction::AtomicCmpXchg: | |
128 if (pointerOperandIsVectorPointer<AtomicCmpXchgInst>(I)) | |
129 report_fatal_error( | |
130 "unhandled: atomic compare and exchange operation on vector"); | |
131 break; | |
132 case Instruction::AtomicRMW: | |
133 if (pointerOperandIsVectorPointer<AtomicRMWInst>(I)) | |
134 report_fatal_error("unhandled: atomic RMW operation on vector"); | |
135 break; | |
136 default: | |
137 if (I->mayReadOrWriteMemory() && hasVectorPointerOperand(I)) | |
138 report_fatal_error( | |
jvoung (off chromium)
2014/04/04 23:20:21
Print the instruction for (a bit more) developer f
JF
2014/04/15 01:52:27
Done.
| |
139 "unexpected: vector operations which may read/write memory"); | |
140 break; | |
141 } | |
142 } | |
143 } | |
144 | |
145 void FixVectorLoadStoreAlignment::fixVectorLoadStoreAlignment( | |
146 BasicBlock &BB, const Instructions &Loads, | |
147 const Instructions &Stores) const { | |
148 for (Instructions::const_iterator IB = Loads.begin(), IE = Loads.end(); | |
149 IB != IE; ++IB) { | |
150 LoadInst *VecLoad = cast<LoadInst>(*IB); | |
jvoung (off chromium)
2014/04/04 23:20:21
copydebug?
JF
2014/04/15 01:52:27
Same as before on IRBuilder.
| |
151 VectorType *LoadedVecTy = | |
152 cast<VectorType>(pointerOperandType(VecLoad)->getElementType()); | |
153 Type *ElemTy = LoadedVecTy->getElementType(); | |
154 | |
155 // The base of the vector is as aligned as the vector load (where | |
156 // zero means ABI alignment for the vector), whereas subsequent | |
157 // elements are as aligned as the base+offset can be. | |
158 unsigned BaseAlign = VecLoad->getAlignment() | |
159 ? VecLoad->getAlignment() | |
160 : TD->getABITypeAlignment(LoadedVecTy); | |
161 unsigned ElemAllocSize = TD->getTypeAllocSize(ElemTy); | |
162 | |
163 // Fill in the vector element by element. | |
164 IRBuilder<> IRB(VecLoad); | |
165 Value *Loaded = UndefValue::get(LoadedVecTy); | |
166 Value *Base = | |
167 IRB.CreateBitCast(VecLoad->getPointerOperand(), ElemTy->getPointerTo()); | |
168 | |
169 for (unsigned Elem = 0, NumElems = LoadedVecTy->getNumElements(); | |
170 Elem != NumElems; ++Elem) { | |
171 unsigned Align = MinAlign(BaseAlign, ElemAllocSize * Elem); | |
172 Value *GEP = IRB.CreateConstInBoundsGEP1_32(Base, Elem); | |
173 LoadInst *LoadedElem = | |
174 IRB.CreateAlignedLoad(GEP, Align, VecLoad->isVolatile()); | |
175 LoadedElem->setSynchScope(VecLoad->getSynchScope()); | |
176 Loaded = IRB.CreateInsertElement( | |
177 Loaded, LoadedElem, | |
178 ConstantInt::get(Type::getInt32Ty(M->getContext()), Elem)); | |
179 } | |
180 | |
181 VecLoad->replaceAllUsesWith(Loaded); | |
182 VecLoad->eraseFromParent(); | |
183 } | |
184 | |
185 for (Instructions::const_iterator IB = Stores.begin(), IE = Stores.end(); | |
186 IB != IE; ++IB) { | |
187 StoreInst *VecStore = cast<StoreInst>(*IB); | |
188 Value *StoredVec = VecStore->getValueOperand(); | |
189 VectorType *StoredVecTy = cast<VectorType>(StoredVec->getType()); | |
190 Type *ElemTy = StoredVecTy->getElementType(); | |
191 | |
192 unsigned BaseAlign = VecStore->getAlignment() | |
193 ? VecStore->getAlignment() | |
194 : TD->getABITypeAlignment(StoredVecTy); | |
195 unsigned ElemAllocSize = TD->getTypeAllocSize(ElemTy); | |
196 | |
197 // Fill in the vector element by element. | |
198 IRBuilder<> IRB(VecStore); | |
199 Value *Base = | |
200 IRB.CreateBitCast(VecStore->getPointerOperand(), ElemTy->getPointerTo()) ; | |
Jim Stichnoth
2014/04/04 23:08:17
line longer than 80 chars
JF
2014/04/15 01:52:27
Done.
| |
201 | |
202 for (unsigned Elem = 0, NumElems = StoredVecTy->getNumElements(); | |
203 Elem != NumElems; ++Elem) { | |
204 unsigned Align = MinAlign(BaseAlign, ElemAllocSize * Elem); | |
205 Value *GEP = IRB.CreateConstInBoundsGEP1_32(Base, Elem); | |
206 Value *ElemToStore = IRB.CreateExtractElement( | |
207 StoredVec, ConstantInt::get(Type::getInt32Ty(M->getContext()), Elem)); | |
208 StoreInst *StoredElem = IRB.CreateAlignedStore(ElemToStore, GEP, Align, | |
209 VecStore->isVolatile()); | |
210 StoredElem->setSynchScope(VecStore->getSynchScope()); | |
211 } | |
212 | |
213 VecStore->eraseFromParent(); | |
214 } | |
215 } | |
216 | |
217 bool FixVectorLoadStoreAlignment::runOnBasicBlock(BasicBlock &BB) { | |
218 bool Changed = false; | |
219 if (!TD) | |
220 TD = &getAnalysis<DataLayout>(); | |
221 Instructions Loads; | |
222 Instructions Stores; | |
223 findVectorLoadStore(BB, Loads, Stores); | |
224 if (!(Loads.empty() && Stores.empty())) { | |
225 Changed = true; | |
226 fixVectorLoadStoreAlignment(BB, Loads, Stores); | |
227 } | |
228 return Changed; | |
229 } | |
230 | |
231 BasicBlockPass *llvm::createFixVectorLoadStoreAlignmentPass() { | |
232 return new FixVectorLoadStoreAlignment(); | |
233 } | |
OLD | NEW |