Several changes:
[oota-llvm.git] / lib / Target / X86 / X86ISelLowering.cpp
index 7bd01b09cce8ae6ea89f1bafa4526ed1b4d03a16..0482dad4aae9b0c3571a13a4f1f4747e3516e574 100644 (file)
@@ -205,7 +205,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1   , Expand);
   setOperationAction(ISD::FP_ROUND_INREG   , MVT::f32  , Expand);
   setOperationAction(ISD::FREM             , MVT::f64  , Expand);
-
+  setOperationAction(ISD::FLT_ROUNDS       , MVT::i32  , Custom);
+  
   setOperationAction(ISD::CTPOP            , MVT::i8   , Expand);
   setOperationAction(ISD::CTTZ             , MVT::i8   , Expand);
   setOperationAction(ISD::CTLZ             , MVT::i8   , Expand);
@@ -650,6 +651,17 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
 }
 
 
+/// getPICJumpTableRelocaBase - Returns relocation base for the given PIC
+/// jumptable.
+SDOperand X86TargetLowering::getPICJumpTableRelocBase(SDOperand Table,
+                                                      SelectionDAG &DAG) const {
+  if (usesGlobalOffsetTable())
+    return DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, getPointerTy());
+  if (!Subtarget->isPICStyleRIPRel())
+    return DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy());
+  return Table;
+}
+
 //===----------------------------------------------------------------------===//
 //               Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
@@ -1120,14 +1132,12 @@ SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
     // This is common for Darwin/X86, Linux & Mingw32 targets.
     NumBytesForCalleeToPush = isSRet ? 4 : 0;
   }
-  
-  NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
-  Ops.clear();
-  Ops.push_back(Chain);
-  Ops.push_back(DAG.getConstant(NumBytes, getPointerTy()));
-  Ops.push_back(DAG.getConstant(NumBytesForCalleeToPush, getPointerTy()));
-  Ops.push_back(InFlag);
-  Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size());
+
+  Chain = DAG.getCALLSEQ_END(Chain,
+                             DAG.getConstant(NumBytes, getPointerTy()),
+                             DAG.getConstant(NumBytesForCalleeToPush,
+                                             getPointerTy()),
+                             InFlag);
   InFlag = Chain.getValue(1);
 
   // Handle result values, copying them out of physregs into vregs that we
@@ -1248,7 +1258,7 @@ X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
 
     SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
     SDOperand  SizeNode = DAG.getConstant(Size, MVT::i32);
-    SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1);
+    SDOperand AlwaysInline = DAG.getConstant(1, MVT::i32);
 
     return DAG.getMemcpy(Chain, PtrOff, Arg, SizeNode, AlignNode,
                          AlwaysInline);
@@ -1466,7 +1476,7 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(SDOperand Call,
   if ((NumOps == 1 && 
        (Ret.getOperand(0) == SDOperand(Call.Val,1) ||
         Ret.getOperand(0) == SDOperand(Call.Val,0))) ||
-      (NumOps == 2 &&
+      (NumOps > 1 &&
        Ret.getOperand(0) == SDOperand(Call.Val,Call.Val->getNumValues()-1) &&
        Ret.getOperand(1) == SDOperand(Call.Val,0))) {
     MachineFunction &MF = DAG.getMachineFunction();
@@ -1632,9 +1642,10 @@ SDOperand X86TargetLowering::LowerX86_TailCallTo(SDOperand Op,
  
         SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
         SDOperand  SizeNode = DAG.getConstant(Size, MVT::i32);
-        // Copy relative to framepointer.
-        MemOpChains2.push_back(DAG.getNode(ISD::MEMCPY, MVT::Other, Chain, FIN,
-                                           PtrOff, SizeNode, AlignNode));
+        SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1);
+
+        MemOpChains2.push_back(DAG.getMemcpy(Chain, FIN, PtrOff, SizeNode, 
+                                             AlignNode,AlwaysInline));
       } else {
         SDOperand LoadedArg = DAG.getLoad(VA.getValVT(), Chain, PtrOff, NULL,0);
         // Store relative to framepointer.
@@ -3907,22 +3918,22 @@ SDOperand X86TargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
   return Result;
 }
 
-SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+std::pair<SDOperand,SDOperand> X86TargetLowering::
+FP_TO_SINTHelper(SDOperand Op, SelectionDAG &DAG) {
   assert(Op.getValueType() <= MVT::i64 && Op.getValueType() >= MVT::i16 &&
          "Unknown FP_TO_SINT to lower!");
-  SDOperand Result;
 
   // These are really Legal.
   if (Op.getValueType() == MVT::i32 && 
       X86ScalarSSEf32 && Op.getOperand(0).getValueType() == MVT::f32)
-    return Result;
+    return std::make_pair(SDOperand(), SDOperand());
   if (Op.getValueType() == MVT::i32 && 
       X86ScalarSSEf64 && Op.getOperand(0).getValueType() == MVT::f64)
-    return Result;
+    return std::make_pair(SDOperand(), SDOperand());
   if (Subtarget->is64Bit() &&
       Op.getValueType() == MVT::i64 &&
       Op.getOperand(0).getValueType() != MVT::f80)
-    return Result;
+    return std::make_pair(SDOperand(), SDOperand());
 
   // We lower FP->sint64 into FISTP64, followed by a load, all to a temporary
   // stack slot.
@@ -3932,10 +3943,10 @@ SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
   SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
   unsigned Opc;
   switch (Op.getValueType()) {
-    default: assert(0 && "Invalid FP_TO_SINT to lower!");
-    case MVT::i16: Opc = X86ISD::FP_TO_INT16_IN_MEM; break;
-    case MVT::i32: Opc = X86ISD::FP_TO_INT32_IN_MEM; break;
-    case MVT::i64: Opc = X86ISD::FP_TO_INT64_IN_MEM; break;
+  default: assert(0 && "Invalid FP_TO_SINT to lower!");
+  case MVT::i16: Opc = X86ISD::FP_TO_INT16_IN_MEM; break;
+  case MVT::i32: Opc = X86ISD::FP_TO_INT32_IN_MEM; break;
+  case MVT::i64: Opc = X86ISD::FP_TO_INT64_IN_MEM; break;
   }
 
   SDOperand Chain = DAG.getEntryNode();
@@ -3958,20 +3969,33 @@ SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Ops[] = { Chain, Value, StackSlot };
   SDOperand FIST = DAG.getNode(Opc, MVT::Other, Ops, 3);
 
-  // Load the result.  If this is an i64 load on an x86-32 host, expand the
-  // load.
-  if (Op.getValueType() != MVT::i64 || Subtarget->is64Bit())
-    return DAG.getLoad(Op.getValueType(), FIST, StackSlot, NULL, 0);
-  
-  SDOperand Lo = DAG.getLoad(MVT::i32, FIST, StackSlot, NULL, 0);
-  StackSlot = DAG.getNode(ISD::ADD, StackSlot.getValueType(), StackSlot,
-                          DAG.getConstant(StackSlot.getValueType(), 4));
-  SDOperand Hi = DAG.getLoad(MVT::i32, FIST, StackSlot, NULL, 0);
-  
+  return std::make_pair(FIST, StackSlot);
+}
+
+SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+  assert((Op.getValueType() != MVT::i64 || Subtarget->is64Bit()) &&
+         "This FP_TO_SINT must be expanded!");
+
+  std::pair<SDOperand,SDOperand> Vals = FP_TO_SINTHelper(Op, DAG);
+  SDOperand FIST = Vals.first, StackSlot = Vals.second;
+  if (FIST.Val == 0) return SDOperand();
   
-  return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
+  // Load the result.
+  return DAG.getLoad(Op.getValueType(), FIST, StackSlot, NULL, 0);
 }
 
+SDNode *X86TargetLowering::ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG) {
+  std::pair<SDOperand,SDOperand> Vals = FP_TO_SINTHelper(SDOperand(N, 0), DAG);
+  SDOperand FIST = Vals.first, StackSlot = Vals.second;
+  if (FIST.Val == 0) return 0;
+  
+  // Return an i64 load from the stack slot.
+  SDOperand Res = DAG.getLoad(MVT::i64, FIST, StackSlot, NULL, 0);
+
+  // Use a MERGE_VALUES node to drop the chain result value.
+  return DAG.getNode(ISD::MERGE_VALUES, MVT::i64, Res).Val;
+}  
+
 SDOperand X86TargetLowering::LowerFABS(SDOperand Op, SelectionDAG &DAG) {
   MVT::ValueType VT = Op.getValueType();
   MVT::ValueType EltVT = VT;
@@ -4481,55 +4505,6 @@ SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
   return Chain;
 }
 
-SDOperand X86TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) {
-  SDOperand ChainOp = Op.getOperand(0);
-  SDOperand DestOp = Op.getOperand(1);
-  SDOperand SourceOp = Op.getOperand(2);
-  SDOperand CountOp = Op.getOperand(3);
-  SDOperand AlignOp = Op.getOperand(4);
-  SDOperand AlwaysInlineOp = Op.getOperand(5);
-
-  bool AlwaysInline = (bool)cast<ConstantSDNode>(AlwaysInlineOp)->getValue();
-  unsigned Align = (unsigned)cast<ConstantSDNode>(AlignOp)->getValue();
-  if (Align == 0) Align = 1;
-
-  // If size is unknown, call memcpy.
-  ConstantSDNode *I = dyn_cast<ConstantSDNode>(CountOp);
-  if (!I) {
-    assert(!AlwaysInline && "Cannot inline copy of unknown size");
-    return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
-  }
-
-  // If not DWORD aligned or if size is more than threshold, then call memcpy.
-  // The libc version is likely to be faster for the following cases. It can
-  // use the address value and run time information about the CPU.
-  // With glibc 2.6.1 on a core 2, coping an array of 100M longs was 30% faster
-  unsigned Size = I->getValue();
-  if (AlwaysInline ||
-      (Size <= Subtarget->getMaxInlineSizeThreshold() &&
-       (Align & 3) == 0))
-    return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG);
-  return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
-}
-
-SDOperand X86TargetLowering::LowerMEMCPYCall(SDOperand Chain,
-                                             SDOperand Dest,
-                                             SDOperand Source,
-                                             SDOperand Count,
-                                             SelectionDAG &DAG) {
-  MVT::ValueType IntPtr = getPointerTy();
-  TargetLowering::ArgListTy Args;
-  TargetLowering::ArgListEntry Entry;
-  Entry.Ty = getTargetData()->getIntPtrType();
-  Entry.Node = Dest; Args.push_back(Entry);
-  Entry.Node = Source; Args.push_back(Entry);
-  Entry.Node = Count; Args.push_back(Entry);
-  std::pair<SDOperand,SDOperand> CallResult =
-      LowerCallTo(Chain, Type::VoidTy, false, false, CallingConv::C, false,
-                  DAG.getExternalSymbol("memcpy", IntPtr), Args, DAG);
-  return CallResult.second;
-}
-
 SDOperand X86TargetLowering::LowerMEMCPYInline(SDOperand Chain,
                                                SDOperand Dest,
                                                SDOperand Source,
@@ -4625,32 +4600,36 @@ SDOperand X86TargetLowering::LowerMEMCPYInline(SDOperand Chain,
   return Chain;
 }
 
-SDOperand
-X86TargetLowering::LowerREADCYCLCECOUNTER(SDOperand Op, SelectionDAG &DAG) {
+/// Expand the result of: i64,outchain = READCYCLECOUNTER inchain
+SDNode *X86TargetLowering::ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG){
   SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
-  SDOperand TheOp = Op.getOperand(0);
-  SDOperand rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheOp, 1);
+  SDOperand TheChain = N->getOperand(0);
+  SDOperand rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheChain, 1);
   if (Subtarget->is64Bit()) {
-    SDOperand Copy1 = 
-      DAG.getCopyFromReg(rd, X86::RAX, MVT::i64, rd.getValue(1));
-    SDOperand Copy2 = DAG.getCopyFromReg(Copy1.getValue(1), X86::RDX,
-                                         MVT::i64, Copy1.getValue(2));
-    SDOperand Tmp = DAG.getNode(ISD::SHL, MVT::i64, Copy2,
+    SDOperand rax = DAG.getCopyFromReg(rd, X86::RAX, MVT::i64, rd.getValue(1));
+    SDOperand rdx = DAG.getCopyFromReg(rax.getValue(1), X86::RDX,
+                                       MVT::i64, rax.getValue(2));
+    SDOperand Tmp = DAG.getNode(ISD::SHL, MVT::i64, rdx,
                                 DAG.getConstant(32, MVT::i8));
     SDOperand Ops[] = {
-      DAG.getNode(ISD::OR, MVT::i64, Copy1, Tmp), Copy2.getValue(1)
+      DAG.getNode(ISD::OR, MVT::i64, rax, Tmp), rdx.getValue(1)
     };
     
     Tys = DAG.getVTList(MVT::i64, MVT::Other);
-    return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2);
+    return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2).Val;
   }
   
-  SDOperand Copy1 = DAG.getCopyFromReg(rd, X86::EAX, MVT::i32, rd.getValue(1));
-  SDOperand Copy2 = DAG.getCopyFromReg(Copy1.getValue(1), X86::EDX,
-                                       MVT::i32, Copy1.getValue(2));
-  SDOperand Ops[] = { Copy1, Copy2, Copy2.getValue(1) };
-  Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
-  return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 3);
+  SDOperand eax = DAG.getCopyFromReg(rd, X86::EAX, MVT::i32, rd.getValue(1));
+  SDOperand edx = DAG.getCopyFromReg(eax.getValue(1), X86::EDX,
+                                       MVT::i32, eax.getValue(2));
+  // Use a buildpair to merge the two 32-bit values into a 64-bit one. 
+  SDOperand Ops[] = { eax, edx };
+  Ops[0] = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Ops, 2);
+
+  // Use a MERGE_VALUES to return the value and chain.
+  Ops[1] = edx.getValue(1);
+  Tys = DAG.getVTList(MVT::i64, MVT::Other);
+  return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2).Val;
 }
 
 SDOperand X86TargetLowering::LowerVASTART(SDOperand Op, SelectionDAG &DAG) {
@@ -4979,6 +4958,66 @@ SDOperand X86TargetLowering::LowerTRAMPOLINE(SDOperand Op,
   }
 }
 
+SDOperand X86TargetLowering::LowerFLT_ROUNDS(SDOperand Op, SelectionDAG &DAG) {
+  /*
+   The rounding mode is in bits 11:10 of FPSR, and has the following
+   settings:
+     00 Round to nearest
+     01 Round to -inf
+     10 Round to +inf
+     11 Round to 0
+
+  FLT_ROUNDS, on the other hand, expects the following:
+    -1 Undefined
+     0 Round to 0
+     1 Round to nearest
+     2 Round to +inf
+     3 Round to -inf
+
+  To perform the conversion, we do:
+    (((((FPSR & 0x800) >> 11) | ((FPSR & 0x400) >> 9)) + 1) & 3)
+  */
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  const TargetMachine &TM = MF.getTarget();
+  const TargetFrameInfo &TFI = *TM.getFrameInfo();
+  unsigned StackAlignment = TFI.getStackAlignment();
+  MVT::ValueType VT = Op.getValueType();
+
+  // Save FP Control Word to stack slot
+  int SSFI = MF.getFrameInfo()->CreateStackObject(2, StackAlignment);
+  SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
+
+  SDOperand Chain = DAG.getNode(X86ISD::FNSTCW16m, MVT::Other,
+                                DAG.getEntryNode(), StackSlot);
+
+  // Load FP Control Word from stack slot
+  SDOperand CWD = DAG.getLoad(MVT::i16, Chain, StackSlot, NULL, 0);
+
+  // Transform as necessary
+  SDOperand CWD1 =
+    DAG.getNode(ISD::SRL, MVT::i16,
+                DAG.getNode(ISD::AND, MVT::i16,
+                            CWD, DAG.getConstant(0x800, MVT::i16)),
+                DAG.getConstant(11, MVT::i8));
+  SDOperand CWD2 =
+    DAG.getNode(ISD::SRL, MVT::i16,
+                DAG.getNode(ISD::AND, MVT::i16,
+                            CWD, DAG.getConstant(0x400, MVT::i16)),
+                DAG.getConstant(9, MVT::i8));
+
+  SDOperand RetVal =
+    DAG.getNode(ISD::AND, MVT::i16,
+                DAG.getNode(ISD::ADD, MVT::i16,
+                            DAG.getNode(ISD::OR, MVT::i16, CWD1, CWD2),
+                            DAG.getConstant(1, MVT::i16)),
+                DAG.getConstant(3, MVT::i16));
+
+
+  return DAG.getNode((MVT::getSizeInBits(VT) < 16 ?
+                      ISD::TRUNCATE : ISD::ZERO_EXTEND), VT, RetVal);
+}
+
 /// LowerOperation - Provide custom lowering hooks for some operations.
 ///
 SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
@@ -5010,7 +5049,6 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::FORMAL_ARGUMENTS:   return LowerFORMAL_ARGUMENTS(Op, DAG);
   case ISD::MEMSET:             return LowerMEMSET(Op, DAG);
   case ISD::MEMCPY:             return LowerMEMCPY(Op, DAG);
-  case ISD::READCYCLECOUNTER:   return LowerREADCYCLCECOUNTER(Op, DAG);
   case ISD::VASTART:            return LowerVASTART(Op, DAG);
   case ISD::VACOPY:             return LowerVACOPY(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
@@ -5021,8 +5059,22 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
   case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
   case ISD::TRAMPOLINE:         return LowerTRAMPOLINE(Op, DAG);
+  case ISD::FLT_ROUNDS:         return LowerFLT_ROUNDS(Op, DAG);
+      
+      
+  // FIXME: REMOVE THIS WHEN LegalizeDAGTypes lands.
+  case ISD::READCYCLECOUNTER:
+    return SDOperand(ExpandREADCYCLECOUNTER(Op.Val, DAG), 0);
+  }
+}
+
+/// ExpandOperation - Provide custom lowering hooks for expanding operations.
+SDNode *X86TargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
+  switch (N->getOpcode()) {
+  default: assert(0 && "Should not custom lower this!");
+  case ISD::FP_TO_SINT:         return ExpandFP_TO_SINT(N, DAG);
+  case ISD::READCYCLECOUNTER:   return ExpandREADCYCLECOUNTER(N, DAG);
   }
-  return SDOperand();
 }
 
 const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
@@ -5068,6 +5120,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::THREAD_POINTER:     return "X86ISD::THREAD_POINTER";
   case X86ISD::EH_RETURN:          return "X86ISD::EH_RETURN";
   case X86ISD::TC_RETURN:          return "X86ISD::TC_RETURN";
+  case X86ISD::FNSTCW16m:          return "X86ISD::FNSTCW16m";
   }
 }
 
@@ -5708,7 +5761,9 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint,
         return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, 0);
       else if (VT == MVT::i8)
         return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::BL, 0);
-        break;
+      else if (VT == MVT::i64)
+        return make_vector<unsigned>(X86::RAX, X86::RDX, X86::RCX, X86::RBX, 0);
+      break;
     }
   }