aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp5
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp30
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h11
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td8
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),