diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2009-07-16 13:47:59 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2009-07-16 13:47:59 +0000 |
commit | 3de52b7bdd1a86a1a2d6a35b3f003dd65e99539c (patch) | |
tree | 72a941d2f41a6a9538e328cea8188e4698bd523a /lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | |
parent | 56260d1553a6b3c28766e032b2132a2ff0bfd78c (diff) | |
download | external_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.cpp | 66 |
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() { |