Add address computation stuff
authorAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:47:59 +0000 (13:47 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:47:59 +0000 (13:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75935 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
lib/Target/SystemZ/SystemZInstrInfo.td
test/CodeGen/SystemZ/05-LoadAddr.ll [new file with mode: 0644]

index 96fcfc291b4f5229e7c6c1c7d50c610646a6bd57..c2b85377ff90e0d6c5ed82b29e769cc9009d71f8 100644 (file)
@@ -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() {
index f5e76cbf3dc8fc9d86a7ae315f613a527e93bcd6..089420eb40a6cd52808427964991cdfe474d0e15 100644 (file)
@@ -162,11 +162,17 @@ def riaddr : Operand<i64>,
 
 // rriaddr := reg + reg + imm
 def rriaddr : Operand<i64>,
-              ComplexPattern<i64, 3, "SelectAddrRRI", []> {
+              ComplexPattern<i64, 3, "SelectAddrRRI", [], []> {
+  let PrintMethod = "printRRIAddrOperand";
+  let MIOperandInfo = (ops ADDR64:$base, ADDR64:$index, i32imm:$disp);
+}
+def laaddr : Operand<i64>,
+             ComplexPattern<i64, 3, "SelectLAAddr", [add, sub, or, frameindex], []> {
   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 (file)
index 0000000..90f01c1
--- /dev/null
@@ -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