Add an initial hack at legalizing GlobalAddress into the appropriate nodes
authorChris Lattner <sabre@nondot.org>
Thu, 17 Nov 2005 07:30:41 +0000 (07:30 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 17 Nov 2005 07:30:41 +0000 (07:30 +0000)
on Darwin to remove smarts from the isel.  This is currently disabled by
default (uncomment setOperationAction(ISD::GlobalAddress to enable it).
tblgen needs to become smarter about tglobaladdr nodes and bigger patterns
needed to be added to the .td file.  However, we can currently emit stuff like
this:  :)

        li r2, lo16(L_x$non_lazy_ptr)
        lis r3, ha16(L_x$non_lazy_ptr)
        lwzx r2, r3, r2

The obvious improvements will follow.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24390 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelDAGToDAG.cpp
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h
lib/Target/PowerPC/PPCInstrInfo.td

index cc7a59aa977cc1b4709548858c285ca96e0e37fb..7c5c808878b13a7d5340b71a0b1e801dcb8f1990 100644 (file)
@@ -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
index d196c10fae772d8a83a299261e43376973703088..437e4369bf07e3375709d922a4bbb74905125942 100644 (file)
@@ -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();
 }
index f44f192e6934855dbd5c438093734238b6299794..d68ac14a85061fae8c4a973656e63f6b29efc5cf 100644 (file)
@@ -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,
     };
   }  
   
index 54acd9b5961c46a9c03f0b280c13ac3d78ec5727..c549fddfa26ec80294c2317f9c95af0c4e7e9f95 100644 (file)
@@ -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),