Make LABEL a builtin opcode.
[oota-llvm.git] / lib / Target / PowerPC / PPCISelLowering.cpp
index e39040acfb7b2074205099b9389b86047f4dc715..097ca91a30b237c76a6da4de85579b646799f173 100644 (file)
@@ -36,12 +36,11 @@ static cl::opt<bool> EnablePPCPreinc("enable-ppc-preinc");
 PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   : TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()) {
     
-  // Fold away setcc operations if possible.
-  setSetCCIsExpensive();
   setPow2DivIsCheap();
   
   // Use _setjmp/_longjmp instead of setjmp/longjmp.
-  setUseUnderscoreSetJmpLongJmp(true);
+  setUseUnderscoreSetJmp(true);
+  setUseUnderscoreLongJmp(true);
     
   // Set up the register classes.
   addRegisterClass(MVT::i32, PPC::GPRCRegisterClass);
@@ -148,7 +147,7 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
   // FIXME - use subtarget debug flags
   if (!TM.getSubtarget<PPCSubtarget>().isDarwin())
-    setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand);
+    setOperationAction(ISD::LABEL, MVT::Other, Expand);
   
   // We want to legalize GlobalAddress and ConstantPool nodes into the 
   // appropriate instructions to materialize the address.
@@ -170,7 +169,7 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   setOperationAction(ISD::VACOPY            , MVT::Other, Expand);
   setOperationAction(ISD::VAEND             , MVT::Other, Expand);
   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); 
-  setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
+  setOperationAction(ISD::STACKRESTORE      , MVT::Other, Custom);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64  , Custom);
 
@@ -180,8 +179,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   if (TM.getSubtarget<PPCSubtarget>().has64BitSupport()) {
     // They also have instructions for converting between i64 and fp.
     setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
+    setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
     setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
-    
+    setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
+    setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
     // FIXME: disable this lowered code.  This generates 64-bit register values,
     // and we don't model the fact that the top part is clobbered by calls.  We
     // need to flag these together so that the value isn't live across a call.
@@ -308,6 +310,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case PPCISD::VPERM:         return "PPCISD::VPERM";
   case PPCISD::Hi:            return "PPCISD::Hi";
   case PPCISD::Lo:            return "PPCISD::Lo";
+  case PPCISD::DYNALLOC:      return "PPCISD::DYNALLOC";
   case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg";
   case PPCISD::SRL:           return "PPCISD::SRL";
   case PPCISD::SRA:           return "PPCISD::SRA";
@@ -1012,8 +1015,7 @@ static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
   
   Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
   
-  if (!GV->hasWeakLinkage() && !GV->hasLinkOnceLinkage() &&
-      (!GV->isExternal() || GV->hasNotBeenReadFromBytecode()))
+  if (!TM.getSubtarget<PPCSubtarget>().hasLazyResolverStub(GV))
     return Lo;
   
   // If the global is weak or external, we have to go through the lazy
@@ -1123,6 +1125,7 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
     bool needsLoad = false;
     MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
     unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
+    unsigned ArgSize = ObjSize;
 
     unsigned CurArgOffset = ArgOffset;
     switch (ObjectVT) {
@@ -1138,6 +1141,7 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
         ++GPR_idx;
       } else {
         needsLoad = true;
+        ArgSize = PtrByteSize;
       }
       break;
     case MVT::i64:  // PPC64
@@ -1203,7 +1207,8 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
       // If the argument is actually used, emit a load from the right stack
       // slot.
       if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
-        int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
+        int FI = MFI->CreateFixedObject(ObjSize,
+                                        CurArgOffset + (ArgSize - ObjSize));
         SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
         ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
       } else {
@@ -1267,8 +1272,6 @@ static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).Val;
 }
 
-#include <iostream>
-
 static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Chain = Op.getOperand(0);
   bool isVarArg       = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
@@ -1376,6 +1379,12 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
       break;
     case MVT::f32:
     case MVT::f64:
+      if (isVarArg && isPPC64) {
+        // Float varargs need to be promoted to double.
+        if (Arg.getValueType() == MVT::f32)
+          Arg = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Arg);
+      }
+    
       if (FPR_idx != NumFPRs) {
         RegsToPass.push_back(std::make_pair(FPR[FPR_idx++], Arg));
 
@@ -1389,7 +1398,7 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
             MemOpChains.push_back(Load.getValue(1));
             RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
           }
-          if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64{
+          if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64){
             SDOperand ConstFour = DAG.getConstant(4, PtrOff.getValueType());
             PtrOff = DAG.getNode(ISD::ADD, PtrVT, PtrOff, ConstFour);
             SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff, NULL, 0);
@@ -1599,6 +1608,32 @@ static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
 }
 
+static SDOperand LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
+                                   const PPCSubtarget &Subtarget) {
+  // When we pop the dynamic allocation we need to restore the SP link.
+  
+  // Get the corect type for pointers.
+  MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
+
+  // Construct the stack pointer operand.
+  bool IsPPC64 = Subtarget.isPPC64();
+  unsigned SP = IsPPC64 ? PPC::X1 : PPC::R1;
+  SDOperand StackPtr = DAG.getRegister(SP, PtrVT);
+
+  // Get the operands for the STACKRESTORE.
+  SDOperand Chain = Op.getOperand(0);
+  SDOperand SaveSP = Op.getOperand(1);
+  
+  // Load the old link SP.
+  SDOperand LoadLinkSP = DAG.getLoad(PtrVT, Chain, StackPtr, NULL, 0);
+  
+  // Restore the stack pointer.
+  Chain = DAG.getCopyToReg(LoadLinkSP.getValue(1), SP, SaveSP);
+  
+  // Store the old link SP.
+  return DAG.getStore(Chain, LoadLinkSP, StackPtr, NULL, 0);
+}
+
 static SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG,
                                          const PPCSubtarget &Subtarget) {
   MachineFunction &MF = DAG.getMachineFunction();
@@ -1957,13 +1992,17 @@ static bool isConstantSplat(const uint64_t Bits128[2],
 static SDOperand BuildSplatI(int Val, unsigned SplatSize, MVT::ValueType VT,
                              SelectionDAG &DAG) {
   assert(Val >= -16 && Val <= 15 && "vsplti is out of range!");
-  
-  // Force vspltis[hw] -1 to vspltisb -1.
-  if (Val == -1) SplatSize = 1;
-  
+
   static const MVT::ValueType VTys[] = { // canonical VT to use for each size.
     MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32
   };
+
+  MVT::ValueType ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1];
+  
+  // Force vspltis[hw] -1 to vspltisb -1 to canonicalize.
+  if (Val == -1)
+    SplatSize = 1;
+  
   MVT::ValueType CanonicalVT = VTys[SplatSize-1];
   
   // Build a canonical splat for this value.
@@ -1972,7 +2011,7 @@ static SDOperand BuildSplatI(int Val, unsigned SplatSize, MVT::ValueType VT,
   Ops.assign(MVT::getVectorNumElements(CanonicalVT), Elt);
   SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT,
                               &Ops[0], Ops.size());
-  return DAG.getNode(ISD::BIT_CONVERT, VT, Res);
+  return DAG.getNode(ISD::BIT_CONVERT, ReqVT, Res);
 }
 
 /// BuildIntrinsicOp - Return a binary operator intrinsic node with the
@@ -2085,6 +2124,7 @@ static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
       -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7,
       -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16
     };
+    
     for (unsigned idx = 0; idx < sizeof(SplatCsts)/sizeof(SplatCsts[0]); ++idx){
       // Indirect through the SplatCsts array so that we favor 'vsplti -1' for
       // cases which are ambiguous (e.g. formation of 0x8000_0000).  'vsplti -1'
@@ -2096,43 +2136,47 @@ static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
       
       // vsplti + shl self.
       if (SextVal == (i << (int)TypeShiftAmt)) {
-        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG);
         static const unsigned IIDs[] = { // Intrinsic to use for each size.
           Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0,
           Intrinsic::ppc_altivec_vslw
         };
-        return BuildIntrinsicOp(IIDs[SplatSize-1], Op, Op, DAG);
+        Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG);
+        return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
       }
       
       // vsplti + srl self.
       if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
-        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG);
         static const unsigned IIDs[] = { // Intrinsic to use for each size.
           Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0,
           Intrinsic::ppc_altivec_vsrw
         };
-        return BuildIntrinsicOp(IIDs[SplatSize-1], Op, Op, DAG);
+        Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG);
+        return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
       }
       
       // vsplti + sra self.
       if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) {
-        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG);
         static const unsigned IIDs[] = { // Intrinsic to use for each size.
           Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0,
           Intrinsic::ppc_altivec_vsraw
         };
-        return BuildIntrinsicOp(IIDs[SplatSize-1], Op, Op, DAG);
+        Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG);
+        return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
       }
       
       // vsplti + rol self.
       if (SextVal == (int)(((unsigned)i << TypeShiftAmt) |
                            ((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) {
-        Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG);
+        SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG);
         static const unsigned IIDs[] = { // Intrinsic to use for each size.
           Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0,
           Intrinsic::ppc_altivec_vrlw
         };
-        return BuildIntrinsicOp(IIDs[SplatSize-1], Op, Op, DAG);
+        Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG);
+        return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res);
       }
 
       // t = vsplti c, result = vsldoi t, t, 1
@@ -2156,15 +2200,17 @@ static SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG) {
     
     // Odd, in range [17,31]:  (vsplti C)-(vsplti -16).
     if (SextVal >= 0 && SextVal <= 31) {
-      SDOperand LHS = BuildSplatI(SextVal-16, SplatSize, Op.getValueType(),DAG);
-      SDOperand RHS = BuildSplatI(-16, SplatSize, Op.getValueType(), DAG);
-      return DAG.getNode(ISD::SUB, Op.getValueType(), LHS, RHS);
+      SDOperand LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG);
+      SDOperand RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG);
+      LHS = DAG.getNode(ISD::SUB, Op.getValueType(), LHS, RHS);
+      return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), LHS);
     }
     // Odd, in range [-31,-17]:  (vsplti C)+(vsplti -16).
     if (SextVal >= -31 && SextVal <= 0) {
-      SDOperand LHS = BuildSplatI(SextVal+16, SplatSize, Op.getValueType(),DAG);
-      SDOperand RHS = BuildSplatI(-16, SplatSize, Op.getValueType(), DAG);
-      return DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS);
+      SDOperand LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG);
+      SDOperand RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG);
+      LHS = DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS);
+      return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), LHS);
     }
   }
     
@@ -2569,6 +2615,7 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
       return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
   case ISD::CALL:               return LowerCALL(Op, DAG);
   case ISD::RET:                return LowerRET(Op, DAG);
+  case ISD::STACKRESTORE:       return LowerSTACKRESTORE(Op, DAG, PPCSubTarget);
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,
                                                                PPCSubTarget);