Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp

Issue 221693002: PNaCl: Add support for GCC/LLVM vector extensions (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Remove TODOs that were done. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698