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

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: Address dschuff's comments. 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/Debug.h"
29 #include "llvm/Support/MathExtras.h"
30 #include "llvm/Transforms/NaCl.h"
31
32 using namespace llvm;
33
34 namespace {
35 class FixVectorLoadStoreAlignment : public BasicBlockPass {
36 public:
37 static char ID; // Pass identification, replacement for typeid
38 FixVectorLoadStoreAlignment() : BasicBlockPass(ID), M(0), DL(0) {
39 initializeFixVectorLoadStoreAlignmentPass(*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 *DL;
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 requires that
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 } // anonymous namespace
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 // The following list of instructions is based on mayReadOrWriteMemory.
102 switch (I->getOpcode()) {
103 case Instruction::Load:
104 if (pointerOperandIsVectorPointer<LoadInst>(I)) {
105 if (cast<LoadInst>(I)->isAtomic())
106 report_fatal_error("unhandled: atomic vector store");
107 Loads.push_back(I);
108 }
109 break;
110 case Instruction::Store:
111 if (pointerOperandIsVectorPointer<StoreInst>(I)) {
112 if (cast<StoreInst>(I)->isAtomic())
113 report_fatal_error("unhandled: atomic vector store");
114 Stores.push_back(I);
115 }
116 break;
117 case Instruction::Alloca:
118 case Instruction::Fence:
119 case Instruction::VAArg:
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 errs() << "Not handled: " << *I << '\n';
139 report_fatal_error(
140 "unexpected: vector operations which may read/write memory");
141 }
142 break;
143 }
144 }
145 }
146
147 void FixVectorLoadStoreAlignment::fixVectorLoadStoreAlignment(
148 BasicBlock &BB, const Instructions &Loads,
149 const Instructions &Stores) const {
150 for (Instructions::const_iterator IB = Loads.begin(), IE = Loads.end();
151 IB != IE; ++IB) {
152 LoadInst *VecLoad = cast<LoadInst>(*IB);
153 VectorType *LoadedVecTy =
154 cast<VectorType>(pointerOperandType(VecLoad)->getElementType());
155 Type *ElemTy = LoadedVecTy->getElementType();
156
157 // The base of the vector is as aligned as the vector load (where
158 // zero means ABI alignment for the vector), whereas subsequent
159 // elements are as aligned as the base+offset can be.
160 unsigned BaseAlign = VecLoad->getAlignment()
161 ? VecLoad->getAlignment()
162 : DL->getABITypeAlignment(LoadedVecTy);
163 unsigned ElemAllocSize = DL->getTypeAllocSize(ElemTy);
164
165 // Fill in the vector element by element.
166 IRBuilder<> IRB(VecLoad);
167 Value *Loaded = UndefValue::get(LoadedVecTy);
168 Value *Base =
169 IRB.CreateBitCast(VecLoad->getPointerOperand(), ElemTy->getPointerTo());
170
171 for (unsigned Elem = 0, NumElems = LoadedVecTy->getNumElements();
172 Elem != NumElems; ++Elem) {
173 unsigned Align = MinAlign(BaseAlign, ElemAllocSize * Elem);
174 Value *GEP = IRB.CreateConstInBoundsGEP1_32(Base, Elem);
175 LoadInst *LoadedElem =
176 IRB.CreateAlignedLoad(GEP, Align, VecLoad->isVolatile());
177 LoadedElem->setSynchScope(VecLoad->getSynchScope());
178 Loaded = IRB.CreateInsertElement(
179 Loaded, LoadedElem,
180 ConstantInt::get(Type::getInt32Ty(M->getContext()), Elem));
181 }
182
183 VecLoad->replaceAllUsesWith(Loaded);
184 VecLoad->eraseFromParent();
185 }
186
187 for (Instructions::const_iterator IB = Stores.begin(), IE = Stores.end();
188 IB != IE; ++IB) {
189 StoreInst *VecStore = cast<StoreInst>(*IB);
190 Value *StoredVec = VecStore->getValueOperand();
191 VectorType *StoredVecTy = cast<VectorType>(StoredVec->getType());
192 Type *ElemTy = StoredVecTy->getElementType();
193
194 unsigned BaseAlign = VecStore->getAlignment()
195 ? VecStore->getAlignment()
196 : DL->getABITypeAlignment(StoredVecTy);
197 unsigned ElemAllocSize = DL->getTypeAllocSize(ElemTy);
198
199 // Fill in the vector element by element.
200 IRBuilder<> IRB(VecStore);
201 Value *Base = IRB.CreateBitCast(VecStore->getPointerOperand(),
202 ElemTy->getPointerTo());
203
204 for (unsigned Elem = 0, NumElems = StoredVecTy->getNumElements();
205 Elem != NumElems; ++Elem) {
206 unsigned Align = MinAlign(BaseAlign, ElemAllocSize * Elem);
207 Value *GEP = IRB.CreateConstInBoundsGEP1_32(Base, Elem);
208 Value *ElemToStore = IRB.CreateExtractElement(
209 StoredVec, ConstantInt::get(Type::getInt32Ty(M->getContext()), Elem));
210 StoreInst *StoredElem = IRB.CreateAlignedStore(ElemToStore, GEP, Align,
211 VecStore->isVolatile());
212 StoredElem->setSynchScope(VecStore->getSynchScope());
213 }
214
215 VecStore->eraseFromParent();
216 }
217 }
218
219 bool FixVectorLoadStoreAlignment::runOnBasicBlock(BasicBlock &BB) {
220 bool Changed = false;
221 if (!DL)
222 DL = &getAnalysis<DataLayout>();
223 Instructions Loads;
224 Instructions Stores;
225 findVectorLoadStore(BB, Loads, Stores);
226 if (!(Loads.empty() && Stores.empty())) {
227 Changed = true;
228 fixVectorLoadStoreAlignment(BB, Loads, Stores);
229 }
230 return Changed;
231 }
232
233 BasicBlockPass *llvm::createFixVectorLoadStoreAlignmentPass() {
234 return new FixVectorLoadStoreAlignment();
235 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698