diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index dc023c8c1f0..e0d67409071 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -875,6 +875,16 @@ public: /// scale of the target addressing mode for load / store of the given type. virtual bool isLegalAddressScale(int64_t S, const Type *Ty) const; + /// isLegalAddressScaleAndImm - Return true if S works for IsLegalAddressScale + /// and V works for isLegalAddressImmediate _and_ both can be applied + /// simultaneously to the same instruction. + virtual bool isLegalAddressScaleAndImm(int64_t S, int64_t V, + const Type* Ty) const; + /// isLegalAddressScaleAndImm - Return true if S works for IsLegalAddressScale + /// and GV works for isLegalAddressImmediate _and_ both can be applied + /// simultaneously to the same instruction. + virtual bool isLegalAddressScaleAndImm(int64_t S, GlobalValue *GV) const; + //===--------------------------------------------------------------------===// // Div utility functions // diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 8df7d8da399..83bca7570f0 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1958,6 +1958,22 @@ bool TargetLowering::isLegalAddressScale(int64_t S, const Type *Ty) const { return false; } +/// isLegalAddressScaleAndImm - Return true if S works for IsLegalAddressScale +/// and V works for isLegalAddressImmediate _and_ both can be applied +/// simultaneously to the same instruction. +bool TargetLowering::isLegalAddressScaleAndImm(int64_t S, int64_t V, + const Type* Ty) const { + return false; +} + +/// isLegalAddressScaleAndImm - Return true if S works for IsLegalAddressScale +/// and GV works for isLegalAddressImmediate _and_ both can be applied +/// simultaneously to the same instruction. +bool TargetLowering::isLegalAddressScaleAndImm(int64_t S, + GlobalValue *GV) const { + + return false; +} // Magic for divide replacement diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index bd7fa5cf6c7..17a41c5aaaa 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1379,6 +1379,24 @@ bool ARMTargetLowering::isLegalAddressScale(int64_t S, const Type *Ty) const { } } +/// isLegalAddressScaleAndImm - Return true if S works for IsLegalAddressScale +/// and V works for isLegalAddressImmediate _and_ both can be applied +/// simultaneously to the same instruction. +bool ARMTargetLowering::isLegalAddressScaleAndImm(int64_t S, int64_t V, + const Type* Ty) const { + if (V == 0) + return isLegalAddressScale(S, Ty); + return false; +} + +/// isLegalAddressScaleAndImm - Return true if S works for IsLegalAddressScale +/// and GV works for isLegalAddressImmediate _and_ both can be applied +/// simultaneously to the same instruction. +bool ARMTargetLowering::isLegalAddressScaleAndImm(int64_t S, + GlobalValue *GV) const { + return false; +} + static bool getIndexedAddressParts(SDNode *Ptr, MVT::ValueType VT, bool isSEXTLoad, SDOperand &Base, SDOperand &Offset, bool &isInc, diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index dc146ba0d5b..1675e9cffef 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -100,6 +100,17 @@ namespace llvm { /// type. virtual bool isLegalAddressScale(int64_t S, const Type *Ty) const; + /// isLegalAddressScaleAndImm - Return true if S works for + /// IsLegalAddressScale and V works for isLegalAddressImmediate _and_ + /// both can be applied simultaneously to the same instruction. + virtual bool isLegalAddressScaleAndImm(int64_t S, int64_t V, + const Type *Ty) const; + + /// isLegalAddressScaleAndImm - Return true if S works for + /// IsLegalAddressScale and GV works for isLegalAddressImmediate _and_ + /// both can be applied simultaneously to the same instruction. + virtual bool isLegalAddressScaleAndImm(int64_t S, GlobalValue *GV) const; + /// getPreIndexedAddressParts - returns true by value, base pointer and /// offset pointer and addressing mode by reference if the node's address /// can be legally represented as pre-indexed load / store address. diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 43531340938..4ace17f7a4a 100644 --- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -883,9 +883,16 @@ static bool isZero(SCEVHandle &V) { /// bool LoopStrengthReduce::ValidStride(int64_t Scale, const std::vector& UsersToProcess) { - for (unsigned i=0, e = UsersToProcess.size(); i!=e; ++i) - if (!TLI->isLegalAddressScale(Scale, UsersToProcess[i].Inst->getType())) + int64_t Imm; + for (unsigned i=0, e = UsersToProcess.size(); i!=e; ++i) { + if (SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) + Imm = SC->getValue()->getSExtValue(); + else + Imm = 0; + if (!TLI->isLegalAddressScaleAndImm(Scale, Imm, + UsersToProcess[i].Inst->getType())) return false; + } return true; } @@ -968,22 +975,6 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride, SCEVHandle CommonExprs = RemoveCommonExpressionsFromUseBases(UsersToProcess); - // Check if it is possible to reuse a IV with stride that is factor of this - // stride. And the multiple is a number that can be encoded in the scale - // field of the target addressing mode. - PHINode *NewPHI = NULL; - Value *IncV = NULL; - IVExpr ReuseIV; - unsigned RewriteFactor = CheckForIVReuse(Stride, ReuseIV, - CommonExprs->getType(), - UsersToProcess); - if (RewriteFactor != 0) { - DOUT << "BASED ON IV of STRIDE " << *ReuseIV.Stride - << " and BASE " << *ReuseIV.Base << " :\n"; - NewPHI = ReuseIV.PHI; - IncV = ReuseIV.IncV; - } - // Next, figure out what we can represent in the immediate fields of // instructions. If we can represent anything there, move it to the imm // fields of the BasedUsers. We do this so that it increases the commonality @@ -1011,6 +1002,23 @@ void LoopStrengthReduce::StrengthReduceStridedIVUsers(const SCEVHandle &Stride, } } + // Check if it is possible to reuse a IV with stride that is factor of this + // stride. And the multiple is a number that can be encoded in the scale + // field of the target addressing mode. And we will have a valid + // instruction after this substition, including the immediate field, if any. + PHINode *NewPHI = NULL; + Value *IncV = NULL; + IVExpr ReuseIV; + unsigned RewriteFactor = CheckForIVReuse(Stride, ReuseIV, + CommonExprs->getType(), + UsersToProcess); + if (RewriteFactor != 0) { + DOUT << "BASED ON IV of STRIDE " << *ReuseIV.Stride + << " and BASE " << *ReuseIV.Base << " :\n"; + NewPHI = ReuseIV.PHI; + IncV = ReuseIV.IncV; + } + // Now that we know what we need to do, insert the PHI node itself. // DOUT << "INSERTING IV of STRIDE " << *Stride << " and BASE "