diff options
-rw-r--r-- | lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 5 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 30 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.h | 11 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstrInfo.td | 8 |
4 files changed, 52 insertions, 2 deletions
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index cc7a59aa97..7c5c808878 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -872,7 +872,8 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) { case ISD::SETCC: return SelectSETCC(Op); case ISD::CALL: return SelectCALL(Op); case ISD::TAILCALL: return SelectCALL(Op); - + case PPCISD::GlobalBaseReg: return getGlobalBaseReg(); + case ISD::FrameIndex: { int FI = cast<FrameIndexSDNode>(N)->getIndex(); if (N->hasOneUse()) { @@ -898,6 +899,7 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) { } return CurDAG->getTargetNode(PPC::LA, MVT::i32, Tmp, CPI); } +#if 1 case ISD::GlobalAddress: { GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal(); SDOperand Tmp; @@ -912,6 +914,7 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) { else return CurDAG->getTargetNode(PPC::LA, MVT::i32, Tmp, GA); } +#endif case ISD::FADD: { MVT::ValueType Ty = N->getValueType(0); if (!NoExcessFPPrecision) { // Match FMA ops diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index d196c10fae..437e4369bf 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -91,6 +91,10 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) // PowerPC does not have truncstore for i1. setOperationAction(ISD::TRUNCSTORE, MVT::i1, Promote); + // We want to legalize GlobalAddress into the appropriate instructions to + // materialize the address. + //setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + if (TM.getSubtarget<PPCSubtarget>().is64Bit()) { // They also have instructions for converting between i64 and fp. setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); @@ -98,7 +102,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote); } else { - // PowerPC does not have FP_TO_UINT on 32 bit implementations. + // PowerPC does not have FP_TO_UINT on 32-bit implementations. setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); } @@ -328,6 +332,30 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { Tmp4, Tmp6, ISD::SETLE); return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi); } + case ISD::GlobalAddress: { + // Only lower GlobalAddress on Darwin. + if (!getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) break; + GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); + SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); + SDOperand Zero = DAG.getConstant(0, MVT::i32); + + SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero); + if (PICEnabled) { + // With PIC, the first instruction is actually "GR+hi(&G)". + Hi = DAG.getNode(ISD::ADD, MVT::i32, + DAG.getTargetNode(PPCISD::GlobalBaseReg, MVT::i32), Hi); + } + + SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero); + Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo); + + if (!GV->hasWeakLinkage() && !GV->isExternal()) + return Lo; + + // If the global is weak or external, we have to go through the lazy + // resolution stub. + return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Lo, DAG.getSrcValue(0)); + } } return SDOperand(); } diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index f44f192e69..d68ac14a85 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -38,6 +38,17 @@ namespace llvm { /// operand, producing an f64 value containing the integer representation /// of that FP value. FCTIDZ, FCTIWZ, + + /// Hi/Lo - These represent the high and low 16-bit parts of a global + /// address respectively. These nodes have two operands, the first of + /// which must be a TargetGlobalAddress, and the second of which must be a + /// Constant. Selected naively, these turn into 'lis G+C' and 'li G+C', + /// though these are usually folded into other nodes. + Hi, Lo, + + /// GlobalBaseReg - On Darwin, this node represents the result of the mflr + /// at function entry, used for PIC code. + GlobalBaseReg, }; } diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 54acd9b596..c549fddfa2 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -27,6 +27,9 @@ def PPCfsel : SDNode<"PPCISD::FSEL", SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisFP<0>, SDTCisVT<1, f64>]>, []>; +def PPChi : SDNode<"PPCISD::Hi", SDTIntBinOp, []>; +def PPClo : SDNode<"PPCISD::Lo", SDTIntBinOp, []>; + //===----------------------------------------------------------------------===// // PowerPC specific transformation functions and pattern fragments. // @@ -782,6 +785,11 @@ def : Pat<(srl GPRC:$in, imm:$imm), def : Pat<(srl G8RC:$in, imm:$imm), (RLDICL G8RC:$in, (SRL64 imm:$imm), imm:$imm)>; +// Hi and Lo for Darwin Global Addresses. +def : Pat<(PPChi tglobaladdr:$in, (i32 0)), (LIS node:$in)>; +def : Pat<(PPClo tglobaladdr:$in, (i32 0)), (LI node:$in)>; + + // Same as above, but using a temporary. FIXME: implement temporaries :) /* def : Pattern<(xor GPRC:$in, imm:$imm), |