[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp X86ISelLowering.h

Evan Cheng evan.cheng at apple.com
Wed May 24 17:59:42 PDT 2006



Changes in directory llvm/lib/Target/X86:

X86ISelLowering.cpp updated: 1.211 -> 1.212
X86ISelLowering.h updated: 1.65 -> 1.66
---
Log message:

Switch X86 over to a call-selection model where the lowering code creates
the copyto/fromregs instead of making the X86ISD::CALL selection code create
them.


---
Diffs of the changes:  (+391 -421)

 X86ISelLowering.cpp |  792 +++++++++++++++++++++++++---------------------------
 X86ISelLowering.h   |   20 -
 2 files changed, 391 insertions(+), 421 deletions(-)


Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.211 llvm/lib/Target/X86/X86ISelLowering.cpp:1.212
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.211	Tue May 23 18:20:42 2006
+++ llvm/lib/Target/X86/X86ISelLowering.cpp	Wed May 24 19:59:30 2006
@@ -358,29 +358,6 @@
   allowUnalignedMemoryAccesses = true; // x86 supports it!
 }
 
-std::pair<SDOperand, SDOperand>
-X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
-                               bool isVarArg, unsigned CallingConv,
-                               bool isTailCall,
-                               SDOperand Callee, ArgListTy &Args,
-                               SelectionDAG &DAG) {
-  assert((!isVarArg || CallingConv == CallingConv::C || 
-          CallingConv == CallingConv::CSRet) &&
-         "Only CCC/CSRet takes varargs!");
-
-  // 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(), getPointerTy());
-  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
-    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
-
-  if (CallingConv == CallingConv::Fast && EnableFastCC)
-    return LowerFastCCCallTo(Chain, RetTy, isTailCall, Callee, Args, DAG);
-  return  LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, CallingConv,
-                         Callee, Args, DAG);
-}
-
 //===----------------------------------------------------------------------===//
 //                    C Calling Convention implementation
 //===----------------------------------------------------------------------===//
@@ -516,150 +493,134 @@
   return DAG.getNode(ISD::MERGE_VALUES, RetVTs, ArgValues);
 }
 
-std::pair<SDOperand, SDOperand>
-X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
-                                  bool isVarArg, bool isTailCall,
-                                  unsigned CallingConv,
-                                  SDOperand Callee, ArgListTy &Args,
-                                  SelectionDAG &DAG) {
-  // Count how many bytes are to be pushed on the stack.
-  unsigned NumBytes = 0;
+
+SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG) {
+  SDOperand Chain     = Op.getOperand(0);
+  unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+  bool isVarArg       = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
+  bool isTailCall     = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
+  SDOperand Callee    = Op.getOperand(4);
+  MVT::ValueType RetVT= Op.Val->getValueType(0);
+  unsigned NumOps     = (Op.getNumOperands() - 5) / 2;
 
   // Keep track of the number of XMM regs passed so far.
   unsigned NumXMMRegs = 0;
-  unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
+  static const unsigned XMMArgRegs[] = {
+    X86::XMM0, X86::XMM1, X86::XMM2
+  };
 
-  std::vector<SDOperand> RegValuesToPass;
-  if (Args.empty()) {
-    // Save zero bytes.
-    Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(0, getPointerTy()));
-  } else {
-    for (unsigned i = 0, e = Args.size(); i != e; ++i)
-      switch (getValueType(Args[i].second)) {
-      default: assert(0 && "Unknown value type!");
-      case MVT::i1:
-      case MVT::i8:
-      case MVT::i16:
-      case MVT::i32:
-      case MVT::f32:
-        NumBytes += 4;
-        break;
-      case MVT::i64:
-      case MVT::f64:
-        NumBytes += 8;
-        break;
-      case MVT::Vector:
-        if (NumXMMRegs < 3)
-          ++NumXMMRegs;
-        else
-          NumBytes += 16;
-        break;
-      }
+  // Count how many bytes are to be pushed on the stack.
+  unsigned NumBytes = 0;
+  for (unsigned i = 0; i != NumOps; ++i) {
+    SDOperand Arg = Op.getOperand(5+2*i);
 
-    Chain = DAG.getCALLSEQ_START(Chain,
-                                 DAG.getConstant(NumBytes, getPointerTy()));
+    switch (Arg.getValueType()) {
+    default: assert(0 && "Unexpected ValueType for argument!");
+    case MVT::i8:
+    case MVT::i16:
+    case MVT::i32:
+    case MVT::f32:
+      NumBytes += 4;
+      break;
+    case MVT::i64:
+    case MVT::f64:
+      NumBytes += 8;
+      break;
+    case MVT::v16i8:
+    case MVT::v8i16:
+    case MVT::v4i32:
+    case MVT::v2i64:
+    case MVT::v4f32:
+    case MVT::v2f64: {
+      if (NumXMMRegs < 3)
+        ++NumXMMRegs;
+      else
+        NumBytes += 16;
+      break;
+    }
+    }
+  }
 
-    // Arguments go on the stack in reverse order, as specified by the ABI.
-    unsigned ArgOffset = 0;
-    NumXMMRegs = 0;
-    SDOperand StackPtr = DAG.getRegister(X86::ESP, MVT::i32);
-    std::vector<SDOperand> Stores;
-    for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-      switch (getValueType(Args[i].second)) {
-      default: assert(0 && "Unexpected ValueType for argument!");
-      case MVT::i1:
-      case MVT::i8:
-      case MVT::i16:
-        // Promote the integer to 32 bits.  If the input type is signed use a
-        // sign extend, otherwise use a zero extend.
-        if (Args[i].second->isSigned())
-          Args[i].first =DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Args[i].first);
-        else
-          Args[i].first =DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Args[i].first);
+  Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));
 
-        // FALL THROUGH
-      case MVT::i32:
-      case MVT::f32: {
-        SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-        PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-        Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                     Args[i].first, PtrOff,
-                                     DAG.getSrcValue(NULL)));
-        ArgOffset += 4;
-        break;
-      }
-      case MVT::i64:
-      case MVT::f64: {
+  // Arguments go on the stack in reverse order, as specified by the ABI.
+  unsigned ArgOffset = 0;
+  NumXMMRegs = 0;
+  std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
+  std::vector<SDOperand> MemOpChains;
+  SDOperand StackPtr = DAG.getRegister(X86::ESP, getPointerTy());
+  for (unsigned i = 0; i != NumOps; ++i) {
+    SDOperand Arg = Op.getOperand(5+2*i);
+
+    switch (Arg.getValueType()) {
+    default: assert(0 && "Unexpected ValueType for argument!");
+    case MVT::i8:
+    case MVT::i16:
+      // Promote the integer to 32 bits.  If the input type is signed use a
+      // sign extend, otherwise use a zero extend.
+      unsigned ExtOp =
+        dyn_cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue() ?
+        ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+      Arg = DAG.getNode(ExtOp, MVT::i32, Arg);
+      // Fallthrough
+
+    case MVT::i32:
+    case MVT::f32: {
+      SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+      PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+      MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                        Arg, PtrOff, DAG.getSrcValue(NULL)));
+      ArgOffset += 4;
+      break;
+    }
+    case MVT::i64:
+    case MVT::f64: {
+      SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+      PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+      MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                        Arg, PtrOff, DAG.getSrcValue(NULL)));
+      ArgOffset += 8;
+      break;
+    }
+    case MVT::v16i8:
+    case MVT::v8i16:
+    case MVT::v4i32:
+    case MVT::v2i64:
+    case MVT::v4f32:
+    case MVT::v2f64: {
+      if (NumXMMRegs < 3) {
+        RegsToPass.push_back(std::make_pair(XMMArgRegs[NumXMMRegs], Arg));
+        NumXMMRegs++;
+      } else {
         SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-        PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-        Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                     Args[i].first, PtrOff,
-                                     DAG.getSrcValue(NULL)));
-        ArgOffset += 8;
-        break;
-      }
-      case MVT::Vector:
-        if (NumXMMRegs < 3) {
-          RegValuesToPass.push_back(Args[i].first);
-          NumXMMRegs++;
-        } else {
-          SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-          PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-          Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff,
-                                       DAG.getSrcValue(NULL)));
-          ArgOffset += 16;
-        }
+        PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+        MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                          Arg, PtrOff, DAG.getSrcValue(NULL)));
+        ArgOffset += 16;
       }
     }
-  if (!Stores.empty())
-    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
+    }
   }
 
-  std::vector<MVT::ValueType> RetVals;
-  MVT::ValueType RetTyVT = getValueType(RetTy);
-  RetVals.push_back(MVT::Other);
-
-  // The result values produced have to be legal.  Promote the result.
-  switch (RetTyVT) {
-  case MVT::isVoid: break;
-  default:
-    RetVals.push_back(RetTyVT);
-    break;
-  case MVT::i1:
-  case MVT::i8:
-  case MVT::i16:
-    RetVals.push_back(MVT::i32);
-    break;
-  case MVT::f32:
-    if (X86ScalarSSE)
-      RetVals.push_back(MVT::f32);
-    else
-      RetVals.push_back(MVT::f64);
-    break;
-  case MVT::i64:
-    RetVals.push_back(MVT::i32);
-    RetVals.push_back(MVT::i32);
-    break;
-  }
+  if (!MemOpChains.empty())
+    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOpChains);
 
   // Build a sequence of copy-to-reg nodes chained together with token chain
   // and flag operands which copy the outgoing args into registers.
   SDOperand InFlag;
-  for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
-    unsigned CCReg = XMMArgRegs[i];
-    SDOperand RegToPass = RegValuesToPass[i];
-    assert(RegToPass.getValueType() == MVT::Vector);
-    unsigned NumElems =
-      cast<ConstantSDNode>(*(RegToPass.Val->op_end()-2))->getValue();
-    MVT::ValueType EVT = cast<VTSDNode>(*(RegToPass.Val->op_end()-1))->getVT();
-    MVT::ValueType PVT = getVectorType(EVT, NumElems);
-    SDOperand CCRegNode = DAG.getRegister(CCReg, PVT);
-    RegToPass = DAG.getNode(ISD::VBIT_CONVERT, PVT, RegToPass);
-    Chain = DAG.getCopyToReg(Chain, CCRegNode, RegToPass, InFlag);
+  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+    Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
+                             InFlag);
     InFlag = Chain.getValue(1);
   }
 
+  // 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(), getPointerTy());
+  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
+
   std::vector<MVT::ValueType> NodeTys;
   NodeTys.push_back(MVT::Other);   // Returns a chain
   NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
@@ -669,8 +630,8 @@
   if (InFlag.Val)
     Ops.push_back(InFlag);
 
-  // FIXME: Do not generate X86ISD::TAILCALL for now.
-  Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops);
+  Chain = DAG.getNode(isTailCall ? X86ISD::TAILCALL : X86ISD::CALL,
+                      NodeTys, Ops);
   InFlag = Chain.getValue(1);
 
   // Create the CALLSEQ_END node.
@@ -683,95 +644,109 @@
   
   NodeTys.clear();
   NodeTys.push_back(MVT::Other);   // Returns a chain
-  NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
+  if (RetVT != MVT::Other)
+    NodeTys.push_back(MVT::Flag);  // Returns a flag for retval copy to use.
   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);
-  InFlag = Chain.getValue(1);
+  if (RetVT != MVT::Other)
+    InFlag = Chain.getValue(1);
   
-  SDOperand RetVal;
-  if (RetTyVT != MVT::isVoid) {
-    switch (RetTyVT) {
-    default: assert(0 && "Unknown value type to return!");
-    case MVT::i1:
-    case MVT::i8:
-      RetVal = DAG.getCopyFromReg(Chain, X86::AL, MVT::i8, InFlag);
-      Chain = RetVal.getValue(1);
-      if (RetTyVT == MVT::i1) 
-        RetVal = DAG.getNode(ISD::TRUNCATE, MVT::i1, RetVal);
-      break;
-    case MVT::i16:
-      RetVal = DAG.getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag);
-      Chain = RetVal.getValue(1);
-      break;
-    case MVT::i32:
-      RetVal = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag);
-      Chain = RetVal.getValue(1);
-      break;
-    case MVT::i64: {
-      SDOperand Lo = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag);
-      SDOperand Hi = DAG.getCopyFromReg(Lo.getValue(1), X86::EDX, MVT::i32, 
-                                        Lo.getValue(2));
-      RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
-      Chain = Hi.getValue(1);
-      break;
+  std::vector<SDOperand> ResultVals;
+  NodeTys.clear();
+  switch (RetVT) {
+  default: assert(0 && "Unknown value type to return!");
+  case MVT::Other: break;
+  case MVT::i8:
+    Chain = DAG.getCopyFromReg(Chain, X86::AL, MVT::i8, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    NodeTys.push_back(MVT::i8);
+    break;
+  case MVT::i16:
+    Chain = DAG.getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    NodeTys.push_back(MVT::i16);
+    break;
+  case MVT::i32:
+    if (Op.Val->getValueType(1) == MVT::i32) {
+      Chain = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag).getValue(1);
+      ResultVals.push_back(Chain.getValue(0));
+      Chain = DAG.getCopyFromReg(Chain, X86::EDX, MVT::i32,
+                                 Chain.getValue(2)).getValue(1);
+      ResultVals.push_back(Chain.getValue(0));
+      NodeTys.push_back(MVT::i32);
+    } else {
+      Chain = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag).getValue(1);
+      ResultVals.push_back(Chain.getValue(0));
     }
-    case MVT::f32:
-    case MVT::f64: {
-      std::vector<MVT::ValueType> Tys;
-      Tys.push_back(MVT::f64);
+    NodeTys.push_back(MVT::i32);
+    break;
+  case MVT::v16i8:
+  case MVT::v8i16:
+  case MVT::v4i32:
+  case MVT::v2i64:
+  case MVT::v4f32:
+  case MVT::v2f64:
+  case MVT::Vector:
+    Chain = DAG.getCopyFromReg(Chain, X86::XMM0, RetVT, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    NodeTys.push_back(RetVT);
+    break;
+  case MVT::f32:
+  case MVT::f64: {
+    std::vector<MVT::ValueType> Tys;
+    Tys.push_back(MVT::f64);
+    Tys.push_back(MVT::Other);
+    Tys.push_back(MVT::Flag);
+    std::vector<SDOperand> Ops;
+    Ops.push_back(Chain);
+    Ops.push_back(InFlag);
+    SDOperand RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, Ops);
+    Chain  = RetVal.getValue(1);
+    InFlag = RetVal.getValue(2);
+    if (X86ScalarSSE) {
+      // FIXME: Currently the FST is flagged to the FP_GET_RESULT. This
+      // shouldn't be necessary except that RFP cannot be live across
+      // multiple blocks. When stackifier is fixed, they can be uncoupled.
+      MachineFunction &MF = DAG.getMachineFunction();
+      int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+      SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
+      Tys.clear();
       Tys.push_back(MVT::Other);
-      Tys.push_back(MVT::Flag);
-      std::vector<SDOperand> Ops;
+      Ops.clear();
       Ops.push_back(Chain);
+      Ops.push_back(RetVal);
+      Ops.push_back(StackSlot);
+      Ops.push_back(DAG.getValueType(RetVT));
       Ops.push_back(InFlag);
-      RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, Ops);
-      Chain  = RetVal.getValue(1);
-      InFlag = RetVal.getValue(2);
-      if (X86ScalarSSE) {
-        // FIXME: Currently the FST is flagged to the FP_GET_RESULT. This
-        // shouldn't be necessary except that RFP cannot be live across
-        // multiple blocks. When stackifier is fixed, they can be uncoupled.
-        MachineFunction &MF = DAG.getMachineFunction();
-        int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
-        SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
-        Tys.clear();
-        Tys.push_back(MVT::Other);
-        Ops.clear();
-        Ops.push_back(Chain);
-        Ops.push_back(RetVal);
-        Ops.push_back(StackSlot);
-        Ops.push_back(DAG.getValueType(RetTyVT));
-        Ops.push_back(InFlag);
-        Chain = DAG.getNode(X86ISD::FST, Tys, Ops);
-        RetVal = DAG.getLoad(RetTyVT, Chain, StackSlot,
-                             DAG.getSrcValue(NULL));
-        Chain = RetVal.getValue(1);
-      }
-
-      if (RetTyVT == MVT::f32 && !X86ScalarSSE)
-        // FIXME: we would really like to remember that this FP_ROUND
-        // operation is okay to eliminate if we allow excess FP precision.
-        RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
-      break;
-    }
-    case MVT::Vector: {
-      const PackedType *PTy = cast<PackedType>(RetTy);
-      MVT::ValueType EVT;
-      MVT::ValueType LVT;
-      unsigned NumRegs = getPackedTypeBreakdown(PTy, EVT, LVT);
-      assert(NumRegs == 1 && "Unsupported type!");
-      RetVal = DAG.getCopyFromReg(Chain, X86::XMM0, EVT, InFlag);
+      Chain = DAG.getNode(X86ISD::FST, Tys, Ops);
+      RetVal = DAG.getLoad(RetVT, Chain, StackSlot,
+                           DAG.getSrcValue(NULL));
       Chain = RetVal.getValue(1);
-      break;
-    }
     }
+
+    if (RetVT == MVT::f32 && !X86ScalarSSE)
+      // FIXME: we would really like to remember that this FP_ROUND
+      // operation is okay to eliminate if we allow excess FP precision.
+      RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
+    ResultVals.push_back(RetVal);
+    NodeTys.push_back(RetVT);
+    break;
+  }
   }
 
-  return std::make_pair(RetVal, Chain);
+  // If the function returns void, just return the chain.
+  if (ResultVals.empty())
+    return Chain;
+  
+  // Otherwise, merge everything together with a MERGE_VALUES node.
+  NodeTys.push_back(MVT::Other);
+  ResultVals.push_back(Chain);
+  SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals);
+  return Res.getValue(Op.ResNo);
 }
 
 //===----------------------------------------------------------------------===//
@@ -894,7 +869,10 @@
   // used).
   unsigned NumIntRegs = 0;
   unsigned NumXMMRegs = 0;  // XMM regs used for parameter passing.
-  unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
+
+  static const unsigned XMMArgRegs[] = {
+    X86::XMM0, X86::XMM1, X86::XMM2
+  };
   
   for (unsigned i = 0; i < NumArgs; ++i) {
     MVT::ValueType ObjectVT = Op.getValue(i).getValueType();
@@ -1018,10 +996,15 @@
   return DAG.getNode(ISD::MERGE_VALUES, RetVTs, ArgValues);
 }
 
-std::pair<SDOperand, SDOperand>
-X86TargetLowering::LowerFastCCCallTo(SDOperand Chain, const Type *RetTy,
-                                     bool isTailCall, SDOperand Callee,
-                                     ArgListTy &Args, SelectionDAG &DAG) {
+ SDOperand X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG) {
+  SDOperand Chain     = Op.getOperand(0);
+  unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+  bool isVarArg       = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
+  bool isTailCall     = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
+  SDOperand Callee    = Op.getOperand(4);
+  MVT::ValueType RetVT= Op.Val->getValueType(0);
+  unsigned NumOps     = (Op.getNumOperands() - 5) / 2;
+
   // Count how many bytes are to be pushed on the stack.
   unsigned NumBytes = 0;
 
@@ -1029,11 +1012,22 @@
   // 0 (neither EAX or EDX used), 1 (EAX is used) or 2 (EAX and EDX are both
   // used).
   unsigned NumIntRegs = 0;
+  unsigned NumXMMRegs = 0;  // XMM regs used for parameter passing.
 
-  for (unsigned i = 0, e = Args.size(); i != e; ++i)
-    switch (getValueType(Args[i].second)) {
+  static const unsigned GPRArgRegs[][2] = {
+    { X86::AL,  X86::DL },
+    { X86::AX,  X86::DX },
+    { X86::EAX, X86::EDX }
+  };
+  static const unsigned XMMArgRegs[] = {
+    X86::XMM0, X86::XMM1, X86::XMM2
+  };
+
+  for (unsigned i = 0; i != NumOps; ++i) {
+    SDOperand Arg = Op.getOperand(5+2*i);
+
+    switch (Arg.getValueType()) {
     default: assert(0 && "Unknown value type!");
-    case MVT::i1:
     case MVT::i8:
     case MVT::i16:
     case MVT::i32:
@@ -1041,25 +1035,26 @@
         ++NumIntRegs;
         break;
       }
-      // fall through
     case MVT::f32:
       NumBytes += 4;
       break;
-    case MVT::i64:
-      if (NumIntRegs+2 <= FASTCC_NUM_INT_ARGS_INREGS) {
-        NumIntRegs += 2;
-        break;
-      } else if (NumIntRegs+1 <= FASTCC_NUM_INT_ARGS_INREGS) {
-        NumIntRegs = FASTCC_NUM_INT_ARGS_INREGS;
-        NumBytes += 4;
-        break;
-      }
-
-      // fall through
     case MVT::f64:
       NumBytes += 8;
       break;
+    case MVT::v16i8:
+    case MVT::v8i16:
+    case MVT::v4i32:
+    case MVT::v2i64:
+    case MVT::v4f32:
+    case MVT::v2f64: {
+      if (NumXMMRegs < 3)
+        NumXMMRegs++;
+      else
+        NumBytes += 16;
+      break;
     }
+    }
+  }
 
   // Make sure the instruction takes 8n+4 bytes to make sure the start of the
   // arguments and the arguments after the retaddr has been pushed are aligned.
@@ -1070,128 +1065,81 @@
 
   // Arguments go on the stack in reverse order, as specified by the ABI.
   unsigned ArgOffset = 0;
-  SDOperand StackPtr = DAG.getRegister(X86::ESP, MVT::i32);
   NumIntRegs = 0;
-  std::vector<SDOperand> Stores;
-  std::vector<SDOperand> RegValuesToPass;
-  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-    switch (getValueType(Args[i].second)) {
+  std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
+  std::vector<SDOperand> MemOpChains;
+  SDOperand StackPtr = DAG.getRegister(X86::ESP, getPointerTy());
+  for (unsigned i = 0; i != NumOps; ++i) {
+    SDOperand Arg = Op.getOperand(5+2*i);
+
+    switch (Arg.getValueType()) {
     default: assert(0 && "Unexpected ValueType for argument!");
-    case MVT::i1:
-      Args[i].first = DAG.getNode(ISD::ANY_EXTEND, MVT::i8, Args[i].first);
-      // Fall through.
     case MVT::i8:
     case MVT::i16:
     case MVT::i32:
       if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
-        RegValuesToPass.push_back(Args[i].first);
+        RegsToPass.push_back(
+              std::make_pair(GPRArgRegs[Arg.getValueType()-MVT::i8][NumIntRegs],
+                             Arg));
         ++NumIntRegs;
         break;
       }
       // Fall through
     case MVT::f32: {
       SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-      PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-      Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                   Args[i].first, PtrOff,
-                                   DAG.getSrcValue(NULL)));
+      PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+      MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                        Arg, PtrOff, DAG.getSrcValue(NULL)));
       ArgOffset += 4;
       break;
     }
-    case MVT::i64:
-       // Can pass (at least) part of it in regs?
-      if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
-        SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
-                                   Args[i].first, DAG.getConstant(1, MVT::i32));
-        SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
-                                   Args[i].first, DAG.getConstant(0, MVT::i32));
-        RegValuesToPass.push_back(Lo);
-        ++NumIntRegs;
-        
-        // Pass both parts in regs?
-        if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
-          RegValuesToPass.push_back(Hi);
-          ++NumIntRegs;
-        } else {
-          // Pass the high part in memory.
-          SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-          PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-          Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Hi, PtrOff, DAG.getSrcValue(NULL)));
-          ArgOffset += 4;
-        }
-        break;
-      }
-      // Fall through
-    case MVT::f64:
+    case MVT::f64: {
       SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
-      PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-      Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                   Args[i].first, PtrOff,
-                                   DAG.getSrcValue(NULL)));
+      PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+      MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                        Arg, PtrOff, DAG.getSrcValue(NULL)));
       ArgOffset += 8;
       break;
     }
+    case MVT::v16i8:
+    case MVT::v8i16:
+    case MVT::v4i32:
+    case MVT::v2i64:
+    case MVT::v4f32:
+    case MVT::v2f64: {
+      if (NumXMMRegs < 3) {
+        RegsToPass.push_back(std::make_pair(XMMArgRegs[NumXMMRegs], Arg));
+        NumXMMRegs++;
+      } else {
+        SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+        PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+        MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                          Arg, PtrOff, DAG.getSrcValue(NULL)));
+        ArgOffset += 16;
+      }
+    }
+    }
   }
-  if (!Stores.empty())
-    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
 
-  // Make sure the instruction takes 8n+4 bytes to make sure the start of the
-  // arguments and the arguments after the retaddr has been pushed are aligned.
-  if ((ArgOffset & 7) == 0)
-    ArgOffset += 4;
-
-  std::vector<MVT::ValueType> RetVals;
-  MVT::ValueType RetTyVT = getValueType(RetTy);
-
-  RetVals.push_back(MVT::Other);
-
-  // The result values produced have to be legal.  Promote the result.
-  switch (RetTyVT) {
-  case MVT::isVoid: break;
-  default:
-    RetVals.push_back(RetTyVT);
-    break;
-  case MVT::i1:
-  case MVT::i8:
-  case MVT::i16:
-    RetVals.push_back(MVT::i32);
-    break;
-  case MVT::f32:
-    if (X86ScalarSSE)
-      RetVals.push_back(MVT::f32);
-    else
-      RetVals.push_back(MVT::f64);
-    break;
-  case MVT::i64:
-    RetVals.push_back(MVT::i32);
-    RetVals.push_back(MVT::i32);
-    break;
-  }
+  if (!MemOpChains.empty())
+    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOpChains);
 
   // Build a sequence of copy-to-reg nodes chained together with token chain
   // and flag operands which copy the outgoing args into registers.
   SDOperand InFlag;
-  for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
-    unsigned CCReg;
-    SDOperand RegToPass = RegValuesToPass[i];
-    switch (RegToPass.getValueType()) {
-    default: assert(0 && "Bad thing to pass in regs");
-    case MVT::i8:
-      CCReg = (i == 0) ? X86::AL  : X86::DL;
-      break;
-    case MVT::i16:
-      CCReg = (i == 0) ? X86::AX  : X86::DX;
-      break;
-    case MVT::i32:
-      CCReg = (i == 0) ? X86::EAX : X86::EDX;
-      break;
-    }
-
-    Chain = DAG.getCopyToReg(Chain, CCReg, RegToPass, InFlag);
+  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+    Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
+                             InFlag);
     InFlag = Chain.getValue(1);
   }
 
+  // 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(), getPointerTy());
+  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
+
   std::vector<MVT::ValueType> NodeTys;
   NodeTys.push_back(MVT::Other);   // Returns a chain
   NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
@@ -1208,85 +1156,110 @@
 
   NodeTys.clear();
   NodeTys.push_back(MVT::Other);   // Returns a chain
-  NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
+  if (RetVT != MVT::Other)
+    NodeTys.push_back(MVT::Flag);  // Returns a flag for retval copy to use.
   Ops.clear();
   Ops.push_back(Chain);
-  Ops.push_back(DAG.getConstant(ArgOffset, getPointerTy()));
-  Ops.push_back(DAG.getConstant(ArgOffset, getPointerTy()));
+  Ops.push_back(DAG.getConstant(NumBytes, getPointerTy()));
+  Ops.push_back(DAG.getConstant(NumBytes, getPointerTy()));
   Ops.push_back(InFlag);
   Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, Ops);
-  InFlag = Chain.getValue(1);
+  if (RetVT != MVT::Other)
+    InFlag = Chain.getValue(1);
   
-  SDOperand RetVal;
-  if (RetTyVT != MVT::isVoid) {
-    switch (RetTyVT) {
-    default: assert(0 && "Unknown value type to return!");
-    case MVT::i1:
-    case MVT::i8:
-      RetVal = DAG.getCopyFromReg(Chain, X86::AL, MVT::i8, InFlag);
-      Chain = RetVal.getValue(1);
-      if (RetTyVT == MVT::i1) 
-        RetVal = DAG.getNode(ISD::TRUNCATE, MVT::i1, RetVal);
-      break;
-    case MVT::i16:
-      RetVal = DAG.getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag);
-      Chain = RetVal.getValue(1);
-      break;
-    case MVT::i32:
-      RetVal = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag);
-      Chain = RetVal.getValue(1);
-      break;
-    case MVT::i64: {
-      SDOperand Lo = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag);
-      SDOperand Hi = DAG.getCopyFromReg(Lo.getValue(1), X86::EDX, MVT::i32, 
-                                        Lo.getValue(2));
-      RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
-      Chain = Hi.getValue(1);
-      break;
+  std::vector<SDOperand> ResultVals;
+  NodeTys.clear();
+  switch (RetVT) {
+  default: assert(0 && "Unknown value type to return!");
+  case MVT::Other: break;
+  case MVT::i8:
+    Chain = DAG.getCopyFromReg(Chain, X86::AL, MVT::i8, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    NodeTys.push_back(MVT::i8);
+    break;
+  case MVT::i16:
+    Chain = DAG.getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    NodeTys.push_back(MVT::i16);
+    break;
+  case MVT::i32:
+    if (Op.Val->getValueType(1) == MVT::i32) {
+      Chain = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag).getValue(1);
+      ResultVals.push_back(Chain.getValue(0));
+      Chain = DAG.getCopyFromReg(Chain, X86::EDX, MVT::i32,
+                                 Chain.getValue(2)).getValue(1);
+      ResultVals.push_back(Chain.getValue(0));
+      NodeTys.push_back(MVT::i32);
+    } else {
+      Chain = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag).getValue(1);
+      ResultVals.push_back(Chain.getValue(0));
     }
-    case MVT::f32:
-    case MVT::f64: {
-      std::vector<MVT::ValueType> Tys;
-      Tys.push_back(MVT::f64);
+    NodeTys.push_back(MVT::i32);
+    break;
+  case MVT::v16i8:
+  case MVT::v8i16:
+  case MVT::v4i32:
+  case MVT::v2i64:
+  case MVT::v4f32:
+  case MVT::v2f64:
+  case MVT::Vector:
+    Chain = DAG.getCopyFromReg(Chain, X86::XMM0, RetVT, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    NodeTys.push_back(RetVT);
+    break;
+  case MVT::f32:
+  case MVT::f64: {
+    std::vector<MVT::ValueType> Tys;
+    Tys.push_back(MVT::f64);
+    Tys.push_back(MVT::Other);
+    Tys.push_back(MVT::Flag);
+    std::vector<SDOperand> Ops;
+    Ops.push_back(Chain);
+    Ops.push_back(InFlag);
+    SDOperand RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, Ops);
+    Chain  = RetVal.getValue(1);
+    InFlag = RetVal.getValue(2);
+    if (X86ScalarSSE) {
+      // FIXME: Currently the FST is flagged to the FP_GET_RESULT. This
+      // shouldn't be necessary except that RFP cannot be live across
+      // multiple blocks. When stackifier is fixed, they can be uncoupled.
+      MachineFunction &MF = DAG.getMachineFunction();
+      int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+      SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
+      Tys.clear();
       Tys.push_back(MVT::Other);
-      Tys.push_back(MVT::Flag);
-      std::vector<SDOperand> Ops;
+      Ops.clear();
       Ops.push_back(Chain);
+      Ops.push_back(RetVal);
+      Ops.push_back(StackSlot);
+      Ops.push_back(DAG.getValueType(RetVT));
       Ops.push_back(InFlag);
-      RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, Ops);
-      Chain  = RetVal.getValue(1);
-      InFlag = RetVal.getValue(2);
-      if (X86ScalarSSE) {
-        // FIXME: Currently the FST is flagged to the FP_GET_RESULT. This
-        // shouldn't be necessary except that RFP cannot be live across
-        // multiple blocks. When stackifier is fixed, they can be uncoupled.
-        MachineFunction &MF = DAG.getMachineFunction();
-        int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
-        SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
-        Tys.clear();
-        Tys.push_back(MVT::Other);
-        Ops.clear();
-        Ops.push_back(Chain);
-        Ops.push_back(RetVal);
-        Ops.push_back(StackSlot);
-        Ops.push_back(DAG.getValueType(RetTyVT));
-        Ops.push_back(InFlag);
-        Chain = DAG.getNode(X86ISD::FST, Tys, Ops);
-        RetVal = DAG.getLoad(RetTyVT, Chain, StackSlot,
-                             DAG.getSrcValue(NULL));
-        Chain = RetVal.getValue(1);
-      }
-
-      if (RetTyVT == MVT::f32 && !X86ScalarSSE)
-        // FIXME: we would really like to remember that this FP_ROUND
-        // operation is okay to eliminate if we allow excess FP precision.
-        RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
-      break;
-    }
+      Chain = DAG.getNode(X86ISD::FST, Tys, Ops);
+      RetVal = DAG.getLoad(RetVT, Chain, StackSlot,
+                           DAG.getSrcValue(NULL));
+      Chain = RetVal.getValue(1);
     }
+
+    if (RetVT == MVT::f32 && !X86ScalarSSE)
+      // FIXME: we would really like to remember that this FP_ROUND
+      // operation is okay to eliminate if we allow excess FP precision.
+      RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
+    ResultVals.push_back(RetVal);
+    NodeTys.push_back(RetVT);
+    break;
+  }
   }
 
-  return std::make_pair(RetVal, Chain);
+
+  // If the function returns void, just return the chain.
+  if (ResultVals.empty())
+    return Chain;
+  
+  // Otherwise, merge everything together with a MERGE_VALUES node.
+  NodeTys.push_back(MVT::Other);
+  ResultVals.push_back(Chain);
+  SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals);
+  return Res.getValue(Op.ResNo);
 }
 
 SDOperand X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) {
@@ -3344,6 +3317,14 @@
   return Result;
 }
 
+SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
+  unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+  if (CallingConv == CallingConv::Fast && EnableFastCC)
+    return LowerFastCCCallTo(Op, DAG);
+  else
+    return LowerCCCCallTo(Op, DAG);
+}
+
 SDOperand X86TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Copy;
     
@@ -3860,6 +3841,7 @@
   case ISD::SELECT:             return LowerSELECT(Op, DAG);
   case ISD::BRCOND:             return LowerBRCOND(Op, DAG);
   case ISD::JumpTable:          return LowerJumpTable(Op, DAG);
+  case ISD::CALL:               return LowerCALL(Op, DAG);
   case ISD::RET:                return LowerRET(Op, DAG);
   case ISD::FORMAL_ARGUMENTS:   return LowerFORMAL_ARGUMENTS(Op, DAG);
   case ISD::MEMSET:             return LowerMEMSET(Op, DAG);


Index: llvm/lib/Target/X86/X86ISelLowering.h
diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.65 llvm/lib/Target/X86/X86ISelLowering.h:1.66
--- llvm/lib/Target/X86/X86ISelLowering.h:1.65	Wed May 24 12:04:04 2006
+++ llvm/lib/Target/X86/X86ISelLowering.h	Wed May 24 19:59:30 2006
@@ -282,13 +282,6 @@
     ///
     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
 
-    /// LowerCallTo - This hook lowers an abstract call to a function into an
-    /// actual call.
-    virtual std::pair<SDOperand, SDOperand>
-    LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
-                bool isTailCall, SDOperand Callee, ArgListTy &Args,
-                SelectionDAG &DAG);
-
     virtual std::pair<SDOperand, SDOperand>
     LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
                             SelectionDAG &DAG);
@@ -343,17 +336,11 @@
 
     // C Calling Convention implementation.
     SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG);
-    std::pair<SDOperand, SDOperand>
-    LowerCCCCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
-                   bool isTailCall, unsigned CallingConv,
-                   SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
+    SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG);
 
     // Fast Calling Convention implementation.
-    SDOperand
-    LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG);
-    std::pair<SDOperand, SDOperand>
-    LowerFastCCCallTo(SDOperand Chain, const Type *RetTy, bool isTailCall,
-                      SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
+    SDOperand LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG);
 
     SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG);
@@ -374,6 +361,7 @@
     SDOperand LowerMEMSET(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerREADCYCLCECOUNTER(SDOperand Op, SelectionDAG &DAG);






More information about the llvm-commits mailing list