OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |