From 711d5b68e07a24c07ff2f514b32fe526c065791f Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 16 Jul 2009 13:47:59 +0000 Subject: [PATCH] Add address computation stuff git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75935 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 66 +++++++++++++++++++++- lib/Target/SystemZ/SystemZInstrInfo.td | 20 ++++++- test/CodeGen/SystemZ/05-LoadAddr.ll | 12 ++++ 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/SystemZ/05-LoadAddr.ll diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index 96fcfc291b4..c2b85377ff9 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() { diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index f5e76cbf3dc..089420eb40a 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -162,11 +162,17 @@ def riaddr : Operand, // rriaddr := reg + reg + imm def rriaddr : Operand, - ComplexPattern { + ComplexPattern { + let PrintMethod = "printRRIAddrOperand"; + let MIOperandInfo = (ops ADDR64:$base, ADDR64:$index, i32imm:$disp); +} +def laaddr : Operand, + ComplexPattern { let PrintMethod = "printRRIAddrOperand"; let MIOperandInfo = (ops ADDR64:$base, ADDR64:$index, i32imm:$disp); } + //===----------------------------------------------------------------------===// // Control Flow Instructions... // @@ -176,6 +182,18 @@ let isReturn = 1, isTerminator = 1 in { def RET : Pseudo<(outs), (ins), "br\t%r14", [(SystemZretflag)]>; } + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions. +// + +let isReMaterializable = 1 in +// FIXME: Provide imm12 variant +def LA64r : Pseudo<(outs GR64:$dst), (ins laaddr:$src), + "lay\t{$dst, $src}", + [(set GR64:$dst, laaddr:$src)]>; + + //===----------------------------------------------------------------------===// // Move Instructions diff --git a/test/CodeGen/SystemZ/05-LoadAddr.ll b/test/CodeGen/SystemZ/05-LoadAddr.ll new file mode 100644 index 00000000000..90f01c1d49e --- /dev/null +++ b/test/CodeGen/SystemZ/05-LoadAddr.ll @@ -0,0 +1,12 @@ + + + .text + .align 4 + .globl foo + .type foo,@function +foo: +.BB1_0: # entry + sllg %r1, %r3, 3 + lay %r2, 8(%r1,%r2) + br %r14 + .size foo, .-foo -- 2.34.1