aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2009-07-16 13:47:59 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2009-07-16 13:47:59 +0000
commit3de52b7bdd1a86a1a2d6a35b3f003dd65e99539c (patch)
tree72a941d2f41a6a9538e328cea8188e4698bd523a /lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
parent56260d1553a6b3c28766e032b2132a2ff0bfd78c (diff)
downloadexternal_llvm-3de52b7bdd1a86a1a2d6a35b3f003dd65e99539c.zip
external_llvm-3de52b7bdd1a86a1a2d6a35b3f003dd65e99539c.tar.gz
external_llvm-3de52b7bdd1a86a1a2d6a35b3f003dd65e99539c.tar.bz2
Add address computation stuff
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75935 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZISelDAGToDAG.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZISelDAGToDAG.cpp66
1 files changed, 63 insertions, 3 deletions
diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
index 96fcfc2..c2b8537 100644
--- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
+++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
@@ -107,6 +107,9 @@ namespace {
private:
bool SelectAddrRRI(SDValue Op, SDValue Addr,
SDValue &Base, SDValue &Index, SDValue &Disp);
+ bool SelectLAAddr(SDValue Op, SDValue Addr,
+ SDValue &Base, SDValue &Index, SDValue &Disp);
+
SDNode *Select(SDValue Op);
bool SelectAddrRI(const SDValue& Op, SDValue& Addr,
SDValue &Base, SDValue &Disp);
@@ -369,8 +372,24 @@ bool SystemZDAGToDAGISel::SelectAddrRRI(SDValue Op, SDValue Addr,
SystemZRRIAddressMode AM;
bool Done = false;
- // FIXME: Should we better use lay instruction for non-single uses?
-
+ if (!Addr.hasOneUse()) {
+ unsigned Opcode = Addr.getOpcode();
+ if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) {
+ // If we are able to fold N into addressing mode, then we'll allow it even
+ // if N has multiple uses. In general, addressing computation is used as
+ // addresses by all of its uses. But watch out for CopyToReg uses, that
+ // means the address computation is liveout. It will be computed by a LA
+ // so we want to avoid computing the address twice.
+ for (SDNode::use_iterator UI = Addr.getNode()->use_begin(),
+ UE = Addr.getNode()->use_end(); UI != UE; ++UI) {
+ if (UI->getOpcode() == ISD::CopyToReg) {
+ MatchAddressBase(Addr, AM);
+ Done = true;
+ break;
+ }
+ }
+ }
+ }
if (!Done && MatchAddress(Addr, AM))
return false;
@@ -388,11 +407,52 @@ bool SystemZDAGToDAGISel::SelectAddrRRI(SDValue Op, SDValue Addr,
else
Base = CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy());
Index = AM.IndexReg;
- Disp = Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32);
+ Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32);
return true;
}
+/// SelectLAAddr - it calls SelectAddr and determines if the maximal addressing
+/// mode it matches can be cost effectively emitted as an LA/LAY instruction.
+bool SystemZDAGToDAGISel::SelectLAAddr(SDValue Op, SDValue Addr,
+ SDValue &Base, SDValue &Index, SDValue &Disp) {
+ SystemZRRIAddressMode AM;
+
+ if (MatchAddress(Addr, AM))
+ return false;
+
+ MVT VT = Addr.getValueType();
+ unsigned Complexity = 0;
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase)
+ if (AM.Base.Reg.getNode())
+ Complexity = 1;
+ else
+ AM.Base.Reg = CurDAG->getRegister(0, VT);
+ else if (AM.BaseType == SystemZRRIAddressMode::FrameIndexBase)
+ Complexity = 4;
+
+ if (AM.IndexReg.getNode())
+ Complexity += 1;
+ else
+ AM.IndexReg = CurDAG->getRegister(0, VT);
+
+ if (AM.Disp && (AM.Base.Reg.getNode() || AM.IndexReg.getNode()))
+ Complexity += 1;
+
+ if (Complexity > 2) {
+ if (AM.BaseType == SystemZRRIAddressMode::RegBase)
+ Base = AM.Base.Reg;
+ else
+ Base = CurDAG->getTargetFrameIndex(AM.Base.FrameIndex,
+ TLI.getPointerTy());
+ Index = AM.IndexReg;
+ Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32);
+ return true;
+ }
+
+ return false;
+}
+
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void SystemZDAGToDAGISel::InstructionSelect() {