Lower addresses of globals
authorAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:57:27 +0000 (13:57 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Thu, 16 Jul 2009 13:57:27 +0000 (13:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75960 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SystemZ/SystemZISelLowering.cpp
lib/Target/SystemZ/SystemZISelLowering.h
lib/Target/SystemZ/SystemZInstrInfo.td
test/CodeGen/SystemZ/09-Globals.ll [new file with mode: 0644]

index 62bd46b011cd9f686d8dfd449ca19d3932d33592..415ab724dce84685413503f26a93032e303ab6cb 100644 (file)
@@ -65,6 +65,7 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
   setOperationAction(ISD::BRCOND,           MVT::Other, Expand);
   setOperationAction(ISD::BR_CC,            MVT::i32, Custom);
   setOperationAction(ISD::BR_CC,            MVT::i64, Custom);
+  setOperationAction(ISD::GlobalAddress,    MVT::i64, Custom);
 
   // FIXME: Can we lower these 2 efficiently?
   setOperationAction(ISD::SETCC,            MVT::i32, Expand);
@@ -87,6 +88,7 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
   case ISD::CALL:             return LowerCALL(Op, DAG);
   case ISD::BR_CC:            return LowerBR_CC(Op, DAG);
   case ISD::SELECT_CC:        return LowerSELECT_CC(Op, DAG);
+  case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);
   default:
     assert(0 && "unimplemented operand");
     return SDValue();
@@ -511,6 +513,16 @@ SDValue SystemZTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
   return DAG.getNode(SystemZISD::SELECT, dl, VTs, &Ops[0], Ops.size());
 }
 
+SDValue SystemZTargetLowering::LowerGlobalAddress(SDValue Op,
+                                                  SelectionDAG &DAG) {
+  DebugLoc dl = Op.getDebugLoc();
+  GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+  SDValue GA = DAG.getTargetGlobalAddress(GV, getPointerTy());
+
+  // FIXME: Verify stuff for constant globals entries
+  return DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), GA);
+}
+
 
 const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
   switch (Opcode) {
@@ -520,6 +532,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case SystemZISD::CMP:                return "SystemZISD::CMP";
   case SystemZISD::UCMP:               return "SystemZISD::UCMP";
   case SystemZISD::SELECT:             return "SystemZISD::SELECT";
+  case SystemZISD::PCRelativeWrapper:  return "SystemZISD::PCRelativeWrapper";
   default: return NULL;
   }
 }
index 51c33216583d48802adb13157cc6441f9d9d7314..22db9c7e3c2e6fba297dc00afe18005f7617f071 100644 (file)
@@ -32,6 +32,9 @@ namespace llvm {
       /// instruction, which includes a bunch of information.
       CALL,
 
+      /// PCRelativeWrapper - PC relative address
+      PCRelativeWrapper,
+
       /// CMP, UCMP - Compare instruction
       CMP,
       UCMP,
@@ -66,6 +69,7 @@ namespace llvm {
     SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
     SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
     SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
+    SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
 
     SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
     SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC);
index f58021cf737ce591e896e43dea9ca8750e7cecae..c6169b316d09331cc03238a67fbd7bb8bf6858cd 100644 (file)
@@ -24,7 +24,7 @@ class SDTCisI64<int OpNum> : SDTCisVT<OpNum, i64>;
 //===----------------------------------------------------------------------===//
 // Type Profiles.
 //===----------------------------------------------------------------------===//
-def SDT_SystemZCall         : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+def SDT_SystemZCall         : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
 def SDT_SystemZCallSeqStart : SDCallSeqStart<[SDTCisI64<0>]>;
 def SDT_SystemZCallSeqEnd   : SDCallSeqEnd<[SDTCisI64<0>, SDTCisI64<1>]>;
 def SDT_CmpTest             : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
@@ -34,7 +34,8 @@ def SDT_BrCond              : SDTypeProfile<0, 2,
 def SDT_SelectCC            : SDTypeProfile<1, 3,
                                            [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
                                             SDTCisI8<3>]>;
-
+def SDT_Address             : SDTypeProfile<1, 1,
+                                            [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
 
 //===----------------------------------------------------------------------===//
 // SystemZ Specific Node Definitions.
@@ -54,6 +55,7 @@ def SystemZucmp    : SDNode<"SystemZISD::UCMP", SDT_CmpTest, [SDNPOutFlag]>;
 def SystemZbrcond  : SDNode<"SystemZISD::BRCOND", SDT_BrCond,
                             [SDNPHasChain, SDNPInFlag]>;
 def SystemZselect  : SDNode<"SystemZISD::SELECT", SDT_SelectCC, [SDNPInFlag]>;
+def SystemZpcrelwrapper : SDNode<"SystemZISD::PCRelativeWrapper", SDT_Address, []>;
 
 //===----------------------------------------------------------------------===//
 // Instruction Pattern Stuff.
@@ -315,6 +317,10 @@ let isReMaterializable = 1 in
 def LA64r  : Pseudo<(outs GR64:$dst), (ins laaddr:$src),
                     "lay\t{$dst, $src}",
                     [(set GR64:$dst, laaddr:$src)]>;
+def LA64rm : Pseudo<(outs GR64:$dst), (ins i64imm:$src),
+                    "larl\t{$dst, $src}",
+                    [(set GR64:$dst,
+                          (SystemZpcrelwrapper tglobaladdr:$src))]>;
 
 let neverHasSideEffects = 1 in
 def NOP : Pseudo<(outs), (ins), "# no-op", []>;
diff --git a/test/CodeGen/SystemZ/09-Globals.ll b/test/CodeGen/SystemZ/09-Globals.ll
new file mode 100644 (file)
index 0000000..22cc033
--- /dev/null
@@ -0,0 +1,23 @@
+; RUN: llvm-as < %s | llc | grep larl | count 3
+
+target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128"
+target triple = "s390x-linux"
+@bar = common global i64 0, align 8            ; <i64*> [#uses=3]
+
+define i64 @foo() nounwind readonly {
+entry:
+       %tmp = load i64* @bar           ; <i64> [#uses=1]
+       ret i64 %tmp
+}
+
+define i64* @foo2() nounwind readnone {
+entry:
+       ret i64* @bar
+}
+
+define i64* @foo3(i64 %idx) nounwind readnone {
+entry:
+       %add.ptr.sum = add i64 %idx, 1          ; <i64> [#uses=1]
+       %add.ptr2 = getelementptr i64* @bar, i64 %add.ptr.sum           ; <i64*> [#uses=1]
+       ret i64* %add.ptr2
+}