aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Vectorize
diff options
context:
space:
mode:
authorArnold Schwaighofer <aschwaighofer@apple.com>2013-02-07 19:05:21 +0000
committerArnold Schwaighofer <aschwaighofer@apple.com>2013-02-07 19:05:21 +0000
commit96a6555b5706af59e408bb190c3685f0f15bc2a9 (patch)
treec2721d5873ca5fcef45ce6250fd9413e9ff91e40 /lib/Transforms/Vectorize
parent35b1423ee67a6ec7052016dda486e6ee4a118db4 (diff)
Loop Vectorizer: Refactor Memory Cost Computation
We don't want too many classes in a pass and the classes obscure the details. I was going a little overboard with object modeling here. Replace classes by generic code that handles both loads and stores. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174646 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Vectorize')
-rw-r--r--lib/Transforms/Vectorize/LoopVectorize.cpp232
1 files changed, 52 insertions, 180 deletions
diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp
index 7d696a72dd..7e97c8fb69 100644
--- a/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -560,11 +560,6 @@ public:
/// \return information about the register usage of the loop.
RegisterUsage calculateRegisterUsage();
- /// A helper function for converting Scalar types to vector types.
- /// If the incoming type is void, we return void. If the VF is 1, we return
- /// the scalar type.
- static Type* ToVectorTy(Type *Scalar, unsigned VF);
-
private:
/// Returns the expected execution cost. The unit of the cost does
/// not matter because we use the 'cost' units to compare different
@@ -576,6 +571,11 @@ private:
/// width. Vector width of one means scalar.
unsigned getInstructionCost(Instruction *I, unsigned VF);
+ /// A helper function for converting Scalar types to vector types.
+ /// If the incoming type is void, we return void. If the VF is 1, we return
+ /// the scalar type.
+ static Type* ToVectorTy(Type *Scalar, unsigned VF);
+
/// Returns whether the instruction is a load or store and will be a emitted
/// as a vector operation.
bool isConsecutiveLoadOrStore(Instruction *I);
@@ -594,177 +594,6 @@ private:
DataLayout *DL;
};
-/// A helper class to compute the cost of a memory operation (load or store).
-class MemoryCostComputation {
-public:
- /// \brief This function computes the cost of a memory instruction, either of
- /// a load or of a store.
- /// \param Inst a pointer to a LoadInst or a StoreInst.
- /// \param VF the vector factor to use.
- /// \param TTI the target transform information used to obtain costs.
- /// \param Legality the legality class used by this function to obtain the
- /// access strid of the memory operation.
- /// \returns the estimated cost of the memory instruction.
- static unsigned computeCost(Value *Inst, unsigned VF,
- const TargetTransformInfo &TTI,
- LoopVectorizationLegality *Legality) {
- if (StoreInst *Store = dyn_cast<StoreInst>(Inst))
- return StoreCost(Store, VF, TTI, Legality).cost();
-
- return LoadCost(cast<LoadInst>(Inst), VF, TTI, Legality).cost();
- }
-
-private:
- /// An helper class to compute the cost of vectorize memory instruction. It is
- /// subclassed by load and store cost computation classes who fill the fields
- /// with values that require knowing about the concrete Load/StoreInst class.
- class MemoryOpCost {
- public:
- /// \return the cost of vectorizing the memory access instruction.
- unsigned cost() {
- if (VectorFactor == 1)
- return TTI.getMemoryOpCost(Opcode, VectorTy, Alignment, AddressSpace);
-
- if ((Stride = Legality->isConsecutivePtr(PointerOperand)))
- return costOfWideMemInst();
-
- return costOfScalarizedMemInst();
- }
-
- protected:
- /// The pointer operand of the memory instruction.
- Value *PointerOperand;
- /// The scalar type of the memory access.
- Type *ScalarTy;
- /// The vector type of the memory access.
- Type *VectorTy;
- /// The vector factor by which we vectorize.
- unsigned VectorFactor;
- /// The stride of the memory access.
- int Stride;
- /// The alignment of the memory operation.
- unsigned Alignment;
- /// The address space of the memory operation.
- unsigned AddressSpace;
- /// The opcode of the memory instruction.
- unsigned Opcode;
- /// Are we looking at a load or store instruction.
- bool IsLoadInst;
- const TargetTransformInfo &TTI;
- LoopVectorizationLegality *Legality;
-
- /// Constructs a helper class to compute the cost of a memory instruction.
- /// \param VF the vector factor (the length of the vector).
- /// \param TI the target transform information used by this class to obtain
- /// costs.
- /// \param L the legality class used by this class to obtain the access
- /// stride of the memory operation.
- MemoryOpCost(unsigned VF, const TargetTransformInfo &TI,
- LoopVectorizationLegality *L) :
- VectorFactor(VF), TTI(TI), Legality(L) {
- }
-
- private:
- /// \return the cost if the memory instruction is scalarized.
- unsigned costOfScalarizedMemInst() {
- unsigned Cost = 0;
- Cost += costOfExtractFromPointerVector();
- Cost += costOfExtractFromValueVector();
- Cost += VectorFactor * TTI.getMemoryOpCost(Opcode, ScalarTy, Alignment,
- AddressSpace);
- Cost += costOfInsertIntoValueVector();
- return Cost;
- }
-
- /// \return the cost of extracting the pointers out of the pointer vector.
- unsigned costOfExtractFromPointerVector() {
- Type *PtrTy = getVectorizedPointerOperandType();
- return costOfVectorInstForAllElems(Instruction::ExtractElement, PtrTy);
- }
-
- /// \return the cost for extracting values out of the value vector if the
- /// memory instruction is a store and zero otherwise.
- unsigned costOfExtractFromValueVector() {
- if (IsLoadInst)
- return 0;
-
- return costOfVectorInstForAllElems(Instruction::ExtractElement, VectorTy);
- }
-
- /// \return the cost of insert values into the value vector if the memory
- /// instruction was a load and zero otherwise.
- unsigned costOfInsertIntoValueVector() {
- if (!IsLoadInst)
- return 0;
-
- return costOfVectorInstForAllElems(Instruction::InsertElement, VectorTy);
- }
-
- /// \return the cost of a vector memory instruction.
- unsigned costOfWideMemInst() {
- unsigned Cost = TTI.getMemoryOpCost(Opcode, VectorTy, Alignment,
- AddressSpace);
- // Reverse stride.
- if (Stride < 0)
- Cost += TTI.getShuffleCost(TargetTransformInfo::SK_Reverse, VectorTy,
- 0);
- return Cost;
- }
-
- /// Helper function to compute the cost of one insert- or extractelement
- /// instruction per vector element.
- /// \param VecOpcode the vector instruction opcode (Can be either
- /// InsertElement or an ExtractElement).
- /// \param Ty the vector type the vector instruction operates on.
- /// \return the cost of an vector instruction applied to each vector
- /// element.
- unsigned costOfVectorInstForAllElems(unsigned VecOpcode, Type *Ty) {
- unsigned Cost = 0;
- for (unsigned i = 0; i < VectorFactor; ++i)
- Cost += TTI.getVectorInstrCost(VecOpcode, Ty, i);
- return Cost;
- }
-
- /// \return a vectorized type for the pointer operand.
- Type * getVectorizedPointerOperandType() {
- Type *PointerOpTy = PointerOperand->getType();
- return LoopVectorizationCostModel::ToVectorTy(PointerOpTy, VectorFactor);
- }
- };
-
- /// Implementation of the abstract memory cost base class. Sets field of base
- /// class whose value depends on the LoadInst.
- class LoadCost : public MemoryOpCost {
- public:
- LoadCost(LoadInst *Load, unsigned VF, const TargetTransformInfo &TI,
- LoopVectorizationLegality *L) : MemoryOpCost(VF, TI, L) {
- PointerOperand = Load->getPointerOperand();
- ScalarTy = Load->getType();
- VectorTy = LoopVectorizationCostModel::ToVectorTy(ScalarTy, VF);
- Alignment = Load->getAlignment();
- AddressSpace = Load->getPointerAddressSpace();
- Opcode = Load->getOpcode();
- IsLoadInst = true;
- }
- };
-
- /// Implementation of the abstract memory cost base class. Sets field of base
- /// class whose value depends on the StoreInst.
- class StoreCost : public MemoryOpCost {
- public:
- StoreCost(StoreInst *Store, unsigned VF, const TargetTransformInfo &TI,
- LoopVectorizationLegality *L) : MemoryOpCost(VF, TI, L) {
- PointerOperand = Store->getPointerOperand();
- ScalarTy = Store->getValueOperand()->getType();
- VectorTy = LoopVectorizationCostModel::ToVectorTy(ScalarTy, VF);
- Alignment = Store->getAlignment();
- AddressSpace = Store->getPointerAddressSpace();
- Opcode = Store->getOpcode();
- IsLoadInst = false;
- }
- };
-};
-
/// The LoopVectorize Pass.
struct LoopVectorize : public LoopPass {
/// Pass identification, replacement for typeid
@@ -3268,11 +3097,54 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, unsigned VF) {
VectorTy = ToVectorTy(ValTy, VF);
return TTI.getCmpSelInstrCost(I->getOpcode(), VectorTy);
}
- case Instruction::Load:
- case Instruction::Store: {
- return MemoryCostComputation::computeCost(I, VF, TTI, Legal);
- }
+ case Instruction::Store:
+ case Instruction::Load: {
+ StoreInst *SI = dyn_cast<StoreInst>(I);
+ LoadInst *LI = dyn_cast<LoadInst>(I);
+ Type *ValTy = (SI ? SI->getValueOperand()->getType() :
+ LI->getType());
+ VectorTy = ToVectorTy(ValTy, VF);
+
+ unsigned Alignment = SI ? SI->getAlignment() : LI->getAlignment();
+ unsigned AS = SI ? SI->getPointerAddressSpace() :
+ LI->getPointerAddressSpace();
+ Value *Ptr = SI ? SI->getPointerOperand() : LI->getPointerOperand();
+ if (VF == 1)
+ return TTI.getMemoryOpCost(I->getOpcode(), VectorTy, Alignment, AS);
+
+ // Scalarized loads/stores.
+ int Stride = Legal->isConsecutivePtr(Ptr);
+ bool Reverse = Stride < 0;
+ if (0 == Stride) {
+ unsigned Cost = 0;
+ // The cost of extracting from the value vector and pointer vector.
+ Type *PtrTy = ToVectorTy(Ptr->getType(), VF);
+ for (unsigned i = 0; i < VF; ++i) {
+ // The cost of extracting the pointer operand.
+ Cost += TTI.getVectorInstrCost(Instruction::ExtractElement, PtrTy, i);
+ // In case of STORE, the cost of ExtractElement from the vector.
+ // In case of LOAD, the cost of InsertElement into the returned
+ // vector.
+ Cost += TTI.getVectorInstrCost(SI ? Instruction::ExtractElement :
+ Instruction::InsertElement,
+ VectorTy, i);
+ }
+
+ // The cost of the scalar stores.
+ Cost += VF * TTI.getMemoryOpCost(I->getOpcode(), ValTy->getScalarType(),
+ Alignment, AS);
+ return Cost;
+ }
+
+ // Wide load/stores.
+ unsigned Cost = TTI.getMemoryOpCost(I->getOpcode(), VectorTy,
+ Alignment, AS);
+ if (Reverse)
+ Cost += TTI.getShuffleCost(TargetTransformInfo::SK_Reverse,
+ VectorTy, 0);
+ return Cost;
+ }
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPToUI: