diff options
-rw-r--r-- | lib/Target/SystemZ/SystemZISelLowering.cpp | 13 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZISelLowering.h | 4 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.td | 10 | ||||
-rw-r--r-- | test/CodeGen/SystemZ/09-Globals.ll | 23 |
4 files changed, 48 insertions, 2 deletions
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 62bd46b..415ab72 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -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; } } diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h index 51c3321..22db9c7 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.h +++ b/lib/Target/SystemZ/SystemZISelLowering.h @@ -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); diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index f58021c..c6169b3 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -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 index 0000000..22cc033 --- /dev/null +++ b/test/CodeGen/SystemZ/09-Globals.ll @@ -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 +} |