When lowering direct calls, lower them to use a targetglobaladress directly
[oota-llvm.git] / lib / Target / PowerPC / PPCISelLowering.cpp
index 23d796600c70a9f8e7f0b82118dac76b32320d45..d196c10fae772d8a83a299261e43376973703088 100644 (file)
@@ -1,4 +1,4 @@
-//===-- PPC32ISelLowering.cpp - PPC32 DAG Lowering Implementation ---------===//
+//===-- PPCISelLowering.cpp - PPC DAG Lowering Implementation -------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,12 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the PPC32ISelLowering class.
+// This file implements the PPCISelLowering class.
 //
 //===----------------------------------------------------------------------===//
 
-#include "PPC32ISelLowering.h"
-#include "PPC32TargetMachine.h"
+#include "PPCISelLowering.h"
+#include "PPCTargetMachine.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/Function.h"
 using namespace llvm;
 
-PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM)
+PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
   : TargetLowering(TM) {
     
   // Fold away setcc operations if possible.
   setSetCCIsExpensive();
+  setPow2DivIsCheap();
   
   // Use _setjmp/_longjmp instead of setjmp/longjmp.
   setUseUnderscoreSetJmpLongJmp(true);
     
   // Set up the register classes.
-  addRegisterClass(MVT::i32, PPC32::GPRCRegisterClass);
-  addRegisterClass(MVT::f32, PPC32::FPRCRegisterClass);
-  addRegisterClass(MVT::f64, PPC32::FPRCRegisterClass);
+  addRegisterClass(MVT::i32, PPC::GPRCRegisterClass);
+  addRegisterClass(MVT::f32, PPC::F4RCRegisterClass);
+  addRegisterClass(MVT::f64, PPC::F8RCRegisterClass);
   
   // PowerPC has no intrinsics for these particular operations
   setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
@@ -76,18 +77,10 @@ PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM)
   setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
   
-  // PowerPC wants to expand i64 shifts itself.
-  setOperationAction(ISD::SHL, MVT::i64, Custom);
-  setOperationAction(ISD::SRL, MVT::i64, Custom);
-  setOperationAction(ISD::SRA, MVT::i64, Custom);
-
   // PowerPC does not have BRCOND* which requires SetCC
   setOperationAction(ISD::BRCOND,       MVT::Other, Expand);
   setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
   
-  // PowerPC does not have FP_TO_UINT
-  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
-  
   // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores.
   setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
 
@@ -98,11 +91,27 @@ PPC32TargetLowering::PPC32TargetLowering(TargetMachine &TM)
   // PowerPC does not have truncstore for i1.
   setOperationAction(ISD::TRUNCSTORE, MVT::i1, Promote);
   
-  // 64 bit PowerPC implementations have instructions to facilitate conversion
-  // between i64 and fp.
   if (TM.getSubtarget<PPCSubtarget>().is64Bit()) {
+    // They also have instructions for converting between i64 and fp.
     setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
     setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
+    // 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.
+    setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
+  }
+
+  if (TM.getSubtarget<PPCSubtarget>().has64BitRegs()) {
+    // 64 bit PowerPC implementations can support i64 types directly
+    addRegisterClass(MVT::i64, PPC::G8RCRegisterClass);
+    // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
+    setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
+  } else {
+    // 32 bit PowerPC wants to expand i64 shifts itself.
+    setOperationAction(ISD::SHL, MVT::i64, Custom);
+    setOperationAction(ISD::SRL, MVT::i64, Custom);
+    setOperationAction(ISD::SRA, MVT::i64, Custom);
   }
   
   setSetCCResultContents(ZeroOrOneSetCCResult);
@@ -125,18 +134,22 @@ static bool isFloatingPointZero(SDOperand Op) {
 
 /// LowerOperation - Provide custom lowering hooks for some operations.
 ///
-SDOperand PPC32TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   switch (Op.getOpcode()) {
   default: assert(0 && "Wasn't expecting to be able to lower this!"); 
   case ISD::FP_TO_SINT: {
     assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType()));
+    SDOperand Src = Op.getOperand(0);
+    if (Src.getValueType() == MVT::f32)
+      Src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Src);
+    
     switch (Op.getValueType()) {
     default: assert(0 && "Unhandled FP_TO_SINT type in custom expander!");
     case MVT::i32:
-      Op = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Op.getOperand(0));
+      Op = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Src);
       break;
     case MVT::i64:
-      Op = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Op.getOperand(0));
+      Op = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Src);
       break;
     }
    
@@ -193,34 +206,47 @@ SDOperand PPC32TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
         std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt
       case ISD::SETUGE:
       case ISD::SETGE:
+        if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits
+          LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS);
         return DAG.getNode(PPCISD::FSEL, ResVT, LHS, TV, FV);
       case ISD::SETUGT:
       case ISD::SETGT:
         std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt
       case ISD::SETULE:
       case ISD::SETLE:
+        if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits
+          LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS);
         return DAG.getNode(PPCISD::FSEL, ResVT,
-                           DAG.getNode(ISD::FNEG, ResVT, LHS), TV, FV);
+                           DAG.getNode(ISD::FNEG, MVT::f64, LHS), TV, FV);
       }
     
+    SDOperand Cmp;
     switch (CC) {
     default: assert(0 && "Invalid FSEL condition"); abort();
     case ISD::SETULT:
     case ISD::SETLT:
-      return DAG.getNode(PPCISD::FSEL, ResVT,
-                         DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS), FV, TV);
+      Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS);
+      if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits
+        Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
+      return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV);
     case ISD::SETUGE:
     case ISD::SETGE:
-      return DAG.getNode(PPCISD::FSEL, ResVT,
-                         DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS), TV, FV);
+      Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS);
+      if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits
+        Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
+      return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV);
     case ISD::SETUGT:
     case ISD::SETGT:
-      return DAG.getNode(PPCISD::FSEL, ResVT,
-                         DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS), FV, TV);
+      Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS);
+      if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits
+        Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
+      return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV);
     case ISD::SETULE:
     case ISD::SETLE:
-      return DAG.getNode(PPCISD::FSEL, ResVT,
-                         DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS), TV, FV);
+      Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS);
+      if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits
+        Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
+      return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV);
     }
     break;
   }
@@ -307,7 +333,7 @@ SDOperand PPC32TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
 }
 
 std::vector<SDOperand>
-PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
+PPCTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
   //
   // add beautiful description of PPC stack frame format, or at least some docs
   //
@@ -349,7 +375,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
       ObjSize = 4;
       if (!ArgLive) break;
       if (GPR_remaining > 0) {
-        unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass);
+        unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
         MF.addLiveIn(GPR[GPR_idx], VReg);
         argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
         if (ObjectVT != MVT::i32) {
@@ -367,7 +393,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
       if (!ArgLive) break;
       if (GPR_remaining > 0) {
         SDOperand argHi, argLo;
-        unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass);
+        unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
         MF.addLiveIn(GPR[GPR_idx], VReg);
         argHi = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
         // If we have two or more remaining argument registers, then both halves
@@ -375,7 +401,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
         // have to come off the stack.  This can happen when an i64 is preceded
         // by 28 bytes of arguments.
         if (GPR_remaining > 1) {
-          unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass);
+          unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
           MF.addLiveIn(GPR[GPR_idx+1], VReg);
           argLo = DAG.getCopyFromReg(argHi, VReg, MVT::i32);
         } else {
@@ -396,7 +422,11 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
       ObjSize = (ObjectVT == MVT::f64) ? 8 : 4;
       if (!ArgLive) break;
       if (FPR_remaining > 0) {
-        unsigned VReg = RegMap->createVirtualRegister(&PPC32::FPRCRegClass);
+        unsigned VReg;
+        if (ObjectVT == MVT::f32)
+          VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass);
+        else
+          VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass);
         MF.addLiveIn(FPR[FPR_idx], VReg);
         argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, ObjectVT);
         --FPR_remaining;
@@ -445,7 +475,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
     // result of va_next.
     std::vector<SDOperand> MemOps;
     for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) {
-      unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass);
+      unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
       MF.addLiveIn(GPR[GPR_idx], VReg);
       SDOperand Val = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
       SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
@@ -482,11 +512,11 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
 }
 
 std::pair<SDOperand, SDOperand>
-PPC32TargetLowering::LowerCallTo(SDOperand Chain,
-                                 const Type *RetTy, bool isVarArg,
-                                 unsigned CallingConv, bool isTailCall,
-                                 SDOperand Callee, ArgListTy &Args,
-                                 SelectionDAG &DAG) {
+PPCTargetLowering::LowerCallTo(SDOperand Chain,
+                               const Type *RetTy, bool isVarArg,
+                               unsigned CallingConv, bool isTailCall,
+                               SDOperand Callee, ArgListTy &Args,
+                               SelectionDAG &DAG) {
   // args_to_use will accumulate outgoing args for the ISD::CALL case in
   // SelectExpr to use to put the arguments in the appropriate registers.
   std::vector<SDOperand> args_to_use;
@@ -661,6 +691,11 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
     RetVals.push_back(ActualRetTyVT);
   RetVals.push_back(MVT::Other);
   
+  // If the callee is a GlobalAddress node (quite common, every direct call is)
+  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
+  
   SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
                                             Chain, Callee, args_to_use), 0);
   Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
@@ -679,8 +714,21 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
   return std::make_pair(RetVal, Chain);
 }
 
-SDOperand PPC32TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
-                                            Value *VAListV, SelectionDAG &DAG) {
+SDOperand PPCTargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
+                                           SelectionDAG &DAG) {
+  if (Op.getValueType() == MVT::i64) {
+    SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, 
+                               DAG.getConstant(1, MVT::i32));
+    SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
+                               DAG.getConstant(0, MVT::i32));
+    return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
+  } else {
+    return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
+  }
+}
+
+SDOperand PPCTargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
+                                          Value *VAListV, SelectionDAG &DAG) {
   // vastart just stores the address of the VarArgsFrameIndex slot into the
   // memory location argument.
   SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
@@ -689,9 +737,9 @@ SDOperand PPC32TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
 }
 
 std::pair<SDOperand,SDOperand>
-PPC32TargetLowering::LowerVAArg(SDOperand Chain,
-                                SDOperand VAListP, Value *VAListV,
-                                const Type *ArgTy, SelectionDAG &DAG) {
+PPCTargetLowering::LowerVAArg(SDOperand Chain,
+                              SDOperand VAListP, Value *VAListV,
+                              const Type *ArgTy, SelectionDAG &DAG) {
   MVT::ValueType ArgVT = getValueType(ArgTy);
   
   SDOperand VAList =
@@ -713,7 +761,7 @@ PPC32TargetLowering::LowerVAArg(SDOperand Chain,
 }
 
 
-std::pair<SDOperand, SDOperand> PPC32TargetLowering::
+std::pair<SDOperand, SDOperand> PPCTargetLowering::
 LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
                         SelectionDAG &DAG) {
   assert(0 && "LowerFrameReturnAddress unimplemented");
@@ -721,10 +769,11 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
 }
 
 MachineBasicBlock *
-PPC32TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
-                                             MachineBasicBlock *BB) {
+PPCTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
+                                           MachineBasicBlock *BB) {
   assert((MI->getOpcode() == PPC::SELECT_CC_Int ||
-          MI->getOpcode() == PPC::SELECT_CC_FP) &&
+          MI->getOpcode() == PPC::SELECT_CC_F4 ||
+          MI->getOpcode() == PPC::SELECT_CC_F8) &&
          "Unexpected instr type to insert");
   
   // To "insert" a SELECT_CC instruction, we actually have to insert the diamond