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

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

Issue 321733002: PNaCl SIMD: allow element-aligned vector load/store (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: s/,/./ Created 6 years, 6 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
« no previous file with comments | « lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp ('k') | lib/Transforms/NaCl/StripAttributes.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- FixVectorLoadStoreAlignment.cpp - Vector load/store alignment ------===// 1 //===- FixVectorLoadStoreAlignment.cpp - Vector load/store alignment ------===//
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 // Replace all vector load/store instructions by loads/stores of each 10 // Fix vector load/store alignment by:
11 // individual element since different architectures have different 11 // - Leaving as-is if the alignment is equal to the vector's element width.
12 // faults on unaligned memory access. This pass pessimizes all vector 12 // - Reducing the alignment to vector's element width if it's greater and the
13 // memory accesses. It's expected that backends with more liberal 13 // current alignment is a factor of the element alignment.
14 // alignment restrictions recognize this pattern and reconstruct the 14 // - Scalarizing if the alignment is smaller than the element-wise alignment.
15 // original vector load/store.
16 // 15 //
17 // Volatile load/store are broken up as allowed by C/C++, and atomic 16 // Volatile vector load/store are handled the same, and can therefore be broken
18 // accesses cause errors at compile-time. 17 // up as allowed by C/C++.
18 //
19 // TODO(jfb) Atomic accesses cause errors at compile-time. This could be
20 // implemented as a call to the C++ runtime, since 128-bit atomics
21 // aren't usually lock-free.
19 // 22 //
20 //===----------------------------------------------------------------------===// 23 //===----------------------------------------------------------------------===//
21 24
22 #include "llvm/IR/DataLayout.h" 25 #include "llvm/IR/DataLayout.h"
23 #include "llvm/IR/IRBuilder.h" 26 #include "llvm/IR/IRBuilder.h"
24 #include "llvm/IR/Instruction.h" 27 #include "llvm/IR/Instruction.h"
25 #include "llvm/IR/Instructions.h" 28 #include "llvm/IR/Instructions.h"
26 #include "llvm/IR/Module.h" 29 #include "llvm/IR/Module.h"
27 #include "llvm/Pass.h" 30 #include "llvm/Pass.h"
28 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/Debug.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 /// don't know which Instruction type is provided. 77 /// don't know which Instruction type is provided.
75 static bool hasVectorPointerOperand(const Instruction *I) { 78 static bool hasVectorPointerOperand(const Instruction *I) {
76 for (User::const_op_iterator IB = I->op_begin(), IE = I->op_end(); IB != IE; 79 for (User::const_op_iterator IB = I->op_begin(), IE = I->op_end(); IB != IE;
77 ++IB) 80 ++IB)
78 if (PointerType *PtrTy = dyn_cast<PointerType>((*IB)->getType())) 81 if (PointerType *PtrTy = dyn_cast<PointerType>((*IB)->getType()))
79 if (isa<VectorType>(PtrTy->getElementType())) 82 if (isa<VectorType>(PtrTy->getElementType()))
80 return true; 83 return true;
81 return false; 84 return false;
82 } 85 }
83 86
84 void findVectorLoadStore(const BasicBlock &BB, Instructions &Loads, 87 /// Vectors are expected to be element-aligned. If they are, leave as-is; if
85 Instructions &Stores) const; 88 /// the alignment is too much then narrow the alignment (when possible);
86 void fixVectorLoadStoreAlignment(BasicBlock &BB, const Instructions &Loads, 89 /// otherwise return false.
87 const Instructions &Stores) const; 90 template <typename InstTy>
91 static bool tryFixVectorAlignment(const DataLayout *DL, Instruction *I) {
92 InstTy *LoadStore = cast<InstTy>(I);
93 VectorType *VecTy =
94 cast<VectorType>(pointerOperandType(LoadStore)->getElementType());
95 Type *ElemTy = VecTy->getElementType();
96 uint64_t ElemBitSize = DL->getTypeSizeInBits(ElemTy);
97 uint64_t ElemByteSize = ElemBitSize / CHAR_BIT;
98 uint64_t CurrentByteAlign = LoadStore->getAlignment();
99 bool isABIAligned = CurrentByteAlign == 0;
100 uint64_t VecABIByteAlign = DL->getABITypeAlignment(VecTy);
101 CurrentByteAlign = isABIAligned ? VecABIByteAlign : CurrentByteAlign;
102
103 if (CHAR_BIT * ElemByteSize != ElemBitSize)
104 return false; // Minimum byte-size elements.
105 if (MinAlign(ElemByteSize, CurrentByteAlign) == ElemByteSize) {
106 // Element-aligned, or compatible over-aligned. Keep element-aligned.
107 LoadStore->setAlignment(ElemByteSize);
108 return true;
109 }
110 return false; // Under-aligned.
111 }
112
113 void visitVectorLoadStore(BasicBlock &BB, Instructions &Loads,
114 Instructions &Stores) const;
115 void scalarizeVectorLoadStore(BasicBlock &BB, const Instructions &Loads,
116 const Instructions &Stores) const;
88 }; 117 };
89 } // anonymous namespace 118 } // anonymous namespace
90 119
91 char FixVectorLoadStoreAlignment::ID = 0; 120 char FixVectorLoadStoreAlignment::ID = 0;
92 INITIALIZE_PASS(FixVectorLoadStoreAlignment, "fix-vector-load-store-alignment", 121 INITIALIZE_PASS(FixVectorLoadStoreAlignment, "fix-vector-load-store-alignment",
93 "Replace vector load/store by loads/stores of each element", 122 "Ensure vector load/store have element-size alignment",
94 false, false) 123 false, false)
95 124
96 void FixVectorLoadStoreAlignment::findVectorLoadStore( 125 void FixVectorLoadStoreAlignment::visitVectorLoadStore(
97 const BasicBlock &BB, Instructions &Loads, Instructions &Stores) const { 126 BasicBlock &BB, Instructions &Loads, Instructions &Stores) const {
98 for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; 127 for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE;
99 ++BBI) { 128 ++BBI) {
100 Instruction *I = const_cast<Instruction *>(&*BBI); 129 Instruction *I = &*BBI;
101 // The following list of instructions is based on mayReadOrWriteMemory. 130 // The following list of instructions is based on mayReadOrWriteMemory.
102 switch (I->getOpcode()) { 131 switch (I->getOpcode()) {
103 case Instruction::Load: 132 case Instruction::Load:
104 if (pointerOperandIsVectorPointer<LoadInst>(I)) { 133 if (pointerOperandIsVectorPointer<LoadInst>(I)) {
105 if (cast<LoadInst>(I)->isAtomic()) 134 if (cast<LoadInst>(I)->isAtomic())
106 report_fatal_error("unhandled: atomic vector store"); 135 report_fatal_error("unhandled: atomic vector store");
107 Loads.push_back(I); 136 if (!tryFixVectorAlignment<LoadInst>(DL, I))
137 Loads.push_back(I);
108 } 138 }
109 break; 139 break;
110 case Instruction::Store: 140 case Instruction::Store:
111 if (pointerOperandIsVectorPointer<StoreInst>(I)) { 141 if (pointerOperandIsVectorPointer<StoreInst>(I)) {
112 if (cast<StoreInst>(I)->isAtomic()) 142 if (cast<StoreInst>(I)->isAtomic())
113 report_fatal_error("unhandled: atomic vector store"); 143 report_fatal_error("unhandled: atomic vector store");
114 Stores.push_back(I); 144 if (!tryFixVectorAlignment<StoreInst>(DL, I))
145 Stores.push_back(I);
115 } 146 }
116 break; 147 break;
117 case Instruction::Alloca: 148 case Instruction::Alloca:
118 case Instruction::Fence: 149 case Instruction::Fence:
119 case Instruction::VAArg: 150 case Instruction::VAArg:
120 // Leave these memory operations as-is, even when they deal with 151 // Leave these memory operations as-is, even when they deal with
121 // vectors. 152 // vectors.
122 break; 153 break;
123 case Instruction::Call: 154 case Instruction::Call:
124 case Instruction::Invoke: 155 case Instruction::Invoke:
(...skipping 12 matching lines...) Expand all
137 if (I->mayReadOrWriteMemory() && hasVectorPointerOperand(I)) { 168 if (I->mayReadOrWriteMemory() && hasVectorPointerOperand(I)) {
138 errs() << "Not handled: " << *I << '\n'; 169 errs() << "Not handled: " << *I << '\n';
139 report_fatal_error( 170 report_fatal_error(
140 "unexpected: vector operations which may read/write memory"); 171 "unexpected: vector operations which may read/write memory");
141 } 172 }
142 break; 173 break;
143 } 174 }
144 } 175 }
145 } 176 }
146 177
147 void FixVectorLoadStoreAlignment::fixVectorLoadStoreAlignment( 178 void FixVectorLoadStoreAlignment::scalarizeVectorLoadStore(
148 BasicBlock &BB, const Instructions &Loads, 179 BasicBlock &BB, const Instructions &Loads,
149 const Instructions &Stores) const { 180 const Instructions &Stores) const {
150 for (Instructions::const_iterator IB = Loads.begin(), IE = Loads.end(); 181 for (Instructions::const_iterator IB = Loads.begin(), IE = Loads.end();
151 IB != IE; ++IB) { 182 IB != IE; ++IB) {
152 LoadInst *VecLoad = cast<LoadInst>(*IB); 183 LoadInst *VecLoad = cast<LoadInst>(*IB);
153 VectorType *LoadedVecTy = 184 VectorType *LoadedVecTy =
154 cast<VectorType>(pointerOperandType(VecLoad)->getElementType()); 185 cast<VectorType>(pointerOperandType(VecLoad)->getElementType());
155 Type *ElemTy = LoadedVecTy->getElementType(); 186 Type *ElemTy = LoadedVecTy->getElementType();
156 187
157 // The base of the vector is as aligned as the vector load (where 188 // The base of the vector is as aligned as the vector load (where
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 VecStore->eraseFromParent(); 246 VecStore->eraseFromParent();
216 } 247 }
217 } 248 }
218 249
219 bool FixVectorLoadStoreAlignment::runOnBasicBlock(BasicBlock &BB) { 250 bool FixVectorLoadStoreAlignment::runOnBasicBlock(BasicBlock &BB) {
220 bool Changed = false; 251 bool Changed = false;
221 if (!DL) 252 if (!DL)
222 DL = &getAnalysis<DataLayout>(); 253 DL = &getAnalysis<DataLayout>();
223 Instructions Loads; 254 Instructions Loads;
224 Instructions Stores; 255 Instructions Stores;
225 findVectorLoadStore(BB, Loads, Stores); 256 visitVectorLoadStore(BB, Loads, Stores);
226 if (!(Loads.empty() && Stores.empty())) { 257 if (!(Loads.empty() && Stores.empty())) {
227 Changed = true; 258 Changed = true;
228 fixVectorLoadStoreAlignment(BB, Loads, Stores); 259 scalarizeVectorLoadStore(BB, Loads, Stores);
229 } 260 }
230 return Changed; 261 return Changed;
231 } 262 }
232 263
233 BasicBlockPass *llvm::createFixVectorLoadStoreAlignmentPass() { 264 BasicBlockPass *llvm::createFixVectorLoadStoreAlignmentPass() {
234 return new FixVectorLoadStoreAlignment(); 265 return new FixVectorLoadStoreAlignment();
235 } 266 }
OLDNEW
« no previous file with comments | « lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp ('k') | lib/Transforms/NaCl/StripAttributes.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698