diff options
author | Evan Cheng <evan.cheng@apple.com> | 2008-05-12 19:56:52 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2008-05-12 19:56:52 +0000 |
commit | ad4196b44ae714a6b95e238d9d96303df74b0429 (patch) | |
tree | 9dbef7c7cebd46d6fb39d7e76a72c0ebd98520aa /lib/CodeGen/SelectionDAG/TargetLowering.cpp | |
parent | c1b7f52fbeb2b637b1cdb1d5e81b3f2b090b8770 (diff) |
Refactor isConsecutiveLoad from X86 to TargetLowering so DAG combiner can make use of it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50991 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/TargetLowering.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 7dab5aa109..e57813dfe7 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -19,6 +19,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/GlobalVariable.h" #include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" @@ -1478,6 +1479,73 @@ TargetLowering::SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1, return SDOperand(); } +/// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the +/// node is a GlobalAddress + offset. +bool TargetLowering::isGAPlusOffset(SDNode *N, GlobalValue* &GA, + int64_t &Offset) const { + if (isa<GlobalAddressSDNode>(N)) { + GA = cast<GlobalAddressSDNode>(N)->getGlobal(); + return true; + } + + if (N->getOpcode() == ISD::ADD) { + SDOperand N1 = N->getOperand(0); + SDOperand N2 = N->getOperand(1); + if (isGAPlusOffset(N1.Val, GA, Offset)) { + ConstantSDNode *V = dyn_cast<ConstantSDNode>(N2); + if (V) { + Offset += V->getSignExtended(); + return true; + } + } else if (isGAPlusOffset(N2.Val, GA, Offset)) { + ConstantSDNode *V = dyn_cast<ConstantSDNode>(N1); + if (V) { + Offset += V->getSignExtended(); + return true; + } + } + } + return false; +} + + +/// isConsecutiveLoad - Return true if LD (which must be a LoadSDNode) is +/// loading 'Bytes' bytes from a location that is 'Dist' units away from the +/// location that the 'Base' load is loading from. +bool TargetLowering::isConsecutiveLoad(SDNode *LD, SDNode *Base, + unsigned Bytes, int Dist, + MachineFrameInfo *MFI) const { + if (LD->getOperand(0).Val != Base->getOperand(0).Val) + return false; + MVT::ValueType VT = LD->getValueType(0); + if (MVT::getSizeInBits(VT) / 8 != Bytes) + return false; + + SDOperand Loc = LD->getOperand(1); + SDOperand BaseLoc = Base->getOperand(1); + if (Loc.getOpcode() == ISD::FrameIndex) { + if (BaseLoc.getOpcode() != ISD::FrameIndex) + return false; + int FI = cast<FrameIndexSDNode>(Loc)->getIndex(); + int BFI = cast<FrameIndexSDNode>(BaseLoc)->getIndex(); + int FS = MFI->getObjectSize(FI); + int BFS = MFI->getObjectSize(BFI); + if (FS != BFS || FS != (int)Bytes) return false; + return MFI->getObjectOffset(FI) == (MFI->getObjectOffset(BFI) + Dist*Bytes); + } + + GlobalValue *GV1 = NULL; + GlobalValue *GV2 = NULL; + int64_t Offset1 = 0; + int64_t Offset2 = 0; + bool isGA1 = isGAPlusOffset(Loc.Val, GV1, Offset1); + bool isGA2 = isGAPlusOffset(BaseLoc.Val, GV2, Offset2); + if (isGA1 && isGA2 && GV1 == GV2) + return Offset1 == (Offset2 + Dist*Bytes); + return false; +} + + SDOperand TargetLowering:: PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { // Default implementation: no optimization. |