| Index: lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp
|
| diff --git a/lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp b/lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp
|
| index 6bb55ac5731f7076933e37d779d8dc84ebc2c883..8a15b8d88d309afdb748e5e87f23b1802c5e4310 100644
|
| --- a/lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp
|
| +++ b/lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp
|
| @@ -7,15 +7,18 @@
|
| //
|
| //===----------------------------------------------------------------------===//
|
| //
|
| -// Replace all vector load/store instructions by loads/stores of each
|
| -// individual element since different architectures have different
|
| -// faults on unaligned memory access. This pass pessimizes all vector
|
| -// memory accesses. It's expected that backends with more liberal
|
| -// alignment restrictions recognize this pattern and reconstruct the
|
| -// original vector load/store.
|
| +// Fix vector load/store alignment by:
|
| +// - Leaving as-is if the alignment is equal to the vector's element width.
|
| +// - Reducing the alignment to vector's element width if it's greater and the
|
| +// current alignment is a factor of the element alignment.
|
| +// - Scalarizing if the alignment is smaller than the element-wise alignment.
|
| //
|
| -// Volatile load/store are broken up as allowed by C/C++, and atomic
|
| -// accesses cause errors at compile-time.
|
| +// Volatile vector load/store are handled the same, and can therefore be broken
|
| +// up as allowed by C/C++.
|
| +//
|
| +// TODO(jfb) Atomic accesses cause errors at compile-time. This could be
|
| +// implemented as a call to the C++ runtime, since 128-bit atomics
|
| +// aren't usually lock-free.
|
| //
|
| //===----------------------------------------------------------------------===//
|
|
|
| @@ -81,37 +84,65 @@ private:
|
| return false;
|
| }
|
|
|
| - void findVectorLoadStore(const BasicBlock &BB, Instructions &Loads,
|
| - Instructions &Stores) const;
|
| - void fixVectorLoadStoreAlignment(BasicBlock &BB, const Instructions &Loads,
|
| - const Instructions &Stores) const;
|
| + /// Vectors are expected to be element-aligned. If they are, leave as-is; if
|
| + /// the alignment is too much then narrow the alignment (when possible);
|
| + /// otherwise return false.
|
| + template <typename InstTy>
|
| + static bool tryFixVectorAlignment(const DataLayout *DL, Instruction *I) {
|
| + InstTy *LoadStore = cast<InstTy>(I);
|
| + VectorType *VecTy =
|
| + cast<VectorType>(pointerOperandType(LoadStore)->getElementType());
|
| + Type *ElemTy = VecTy->getElementType();
|
| + uint64_t ElemBitSize = DL->getTypeSizeInBits(ElemTy);
|
| + uint64_t ElemByteSize = ElemBitSize / CHAR_BIT;
|
| + uint64_t CurrentByteAlign = LoadStore->getAlignment();
|
| + bool isABIAligned = CurrentByteAlign == 0;
|
| + uint64_t VecABIByteAlign = DL->getABITypeAlignment(VecTy);
|
| + CurrentByteAlign = isABIAligned ? VecABIByteAlign : CurrentByteAlign;
|
| +
|
| + if (CHAR_BIT * ElemByteSize != ElemBitSize)
|
| + return false; // Minimum byte-size elements.
|
| + if (MinAlign(ElemByteSize, CurrentByteAlign) == ElemByteSize) {
|
| + // Element-aligned, or compatible over-aligned. Keep element-aligned.
|
| + LoadStore->setAlignment(ElemByteSize);
|
| + return true;
|
| + }
|
| + return false; // Under-aligned.
|
| + }
|
| +
|
| + void visitVectorLoadStore(BasicBlock &BB, Instructions &Loads,
|
| + Instructions &Stores) const;
|
| + void scalarizeVectorLoadStore(BasicBlock &BB, const Instructions &Loads,
|
| + const Instructions &Stores) const;
|
| };
|
| } // anonymous namespace
|
|
|
| char FixVectorLoadStoreAlignment::ID = 0;
|
| INITIALIZE_PASS(FixVectorLoadStoreAlignment, "fix-vector-load-store-alignment",
|
| - "Replace vector load/store by loads/stores of each element",
|
| + "Ensure vector load/store have element-size alignment",
|
| false, false)
|
|
|
| -void FixVectorLoadStoreAlignment::findVectorLoadStore(
|
| - const BasicBlock &BB, Instructions &Loads, Instructions &Stores) const {
|
| - for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE;
|
| +void FixVectorLoadStoreAlignment::visitVectorLoadStore(
|
| + BasicBlock &BB, Instructions &Loads, Instructions &Stores) const {
|
| + for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE;
|
| ++BBI) {
|
| - Instruction *I = const_cast<Instruction *>(&*BBI);
|
| + Instruction *I = &*BBI;
|
| // The following list of instructions is based on mayReadOrWriteMemory.
|
| switch (I->getOpcode()) {
|
| case Instruction::Load:
|
| if (pointerOperandIsVectorPointer<LoadInst>(I)) {
|
| if (cast<LoadInst>(I)->isAtomic())
|
| report_fatal_error("unhandled: atomic vector store");
|
| - Loads.push_back(I);
|
| + if (!tryFixVectorAlignment<LoadInst>(DL, I))
|
| + Loads.push_back(I);
|
| }
|
| break;
|
| case Instruction::Store:
|
| if (pointerOperandIsVectorPointer<StoreInst>(I)) {
|
| if (cast<StoreInst>(I)->isAtomic())
|
| report_fatal_error("unhandled: atomic vector store");
|
| - Stores.push_back(I);
|
| + if (!tryFixVectorAlignment<StoreInst>(DL, I))
|
| + Stores.push_back(I);
|
| }
|
| break;
|
| case Instruction::Alloca:
|
| @@ -144,7 +175,7 @@ void FixVectorLoadStoreAlignment::findVectorLoadStore(
|
| }
|
| }
|
|
|
| -void FixVectorLoadStoreAlignment::fixVectorLoadStoreAlignment(
|
| +void FixVectorLoadStoreAlignment::scalarizeVectorLoadStore(
|
| BasicBlock &BB, const Instructions &Loads,
|
| const Instructions &Stores) const {
|
| for (Instructions::const_iterator IB = Loads.begin(), IE = Loads.end();
|
| @@ -222,10 +253,10 @@ bool FixVectorLoadStoreAlignment::runOnBasicBlock(BasicBlock &BB) {
|
| DL = &getAnalysis<DataLayout>();
|
| Instructions Loads;
|
| Instructions Stores;
|
| - findVectorLoadStore(BB, Loads, Stores);
|
| + visitVectorLoadStore(BB, Loads, Stores);
|
| if (!(Loads.empty() && Stores.empty())) {
|
| Changed = true;
|
| - fixVectorLoadStoreAlignment(BB, Loads, Stores);
|
| + scalarizeVectorLoadStore(BB, Loads, Stores);
|
| }
|
| return Changed;
|
| }
|
|
|