diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/CodeGen/CallingConvLower.h | 7 | ||||
| -rw-r--r-- | llvm/include/llvm/Target/TargetLowering.h | 12 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 60 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.h | 6 | 
6 files changed, 111 insertions, 0 deletions
diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h index 5e730fc12cc..45a2757d378 100644 --- a/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -183,6 +183,13 @@ public:    void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,                       CCAssignFn Fn); +  /// CheckReturn - Analyze the return values of a function, returning +  /// true if the return can be performed without sret-demotion, and +  /// false otherwise. +  bool CheckReturn(const SmallVectorImpl<EVT> &OutTys, +                   const SmallVectorImpl<ISD::ArgFlagsTy> &ArgsFlags, +                   CCAssignFn Fn); +    /// AnalyzeCallOperands - Analyze the outgoing arguments to a call,    /// incorporating info about the passed values into this state.    void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index 8bc39d0b2ce..1526a0de0c5 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -1167,6 +1167,18 @@ public:      return SDValue();    // this is here to silence compiler errors    } +  /// CanLowerReturn - This hook should be implemented to check whether the +  /// return values described by the Outs array can fit into the return +  /// registers.  If false is returned, an sret-demotion is performed. +  /// +  virtual bool CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, +               const SmallVectorImpl<EVT> &OutTys, +               const SmallVectorImpl<ISD::ArgFlagsTy> &ArgsFlags, +               SelectionDAG &DAG) +  { +    // Return true by default to get preexisting behavior. +    return true; +  }    /// LowerReturn - This hook must be implemented to lower outgoing    /// return values, described by the Outs array, into the specified    /// DAG. The implementation should return the resulting token chain diff --git a/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp b/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp index fbe40b67863..38839c44131 100644 --- a/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp @@ -77,6 +77,21 @@ CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,    }  } +/// CheckReturn - Analyze the return values of a function, returning true if +/// the return can be performed without sret-demotion, and false otherwise. +bool CCState::CheckReturn(const SmallVectorImpl<EVT> &OutTys, +                          const SmallVectorImpl<ISD::ArgFlagsTy> &ArgsFlags, +                          CCAssignFn Fn) { +  // Determine which register each value should be copied into. +  for (unsigned i = 0, e = OutTys.size(); i != e; ++i) { +    EVT VT = OutTys[i]; +    ISD::ArgFlagsTy ArgFlags = ArgsFlags[i]; +    if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) +      return false; +  } +  return true; +} +  /// AnalyzeReturn - Analyze the returned values of a return,  /// incorporating info about the result values into this state.  void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index c0d2a4d39a3..1ff1cd30f24 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -947,6 +947,58 @@ SDValue SelectionDAGLowering::getValue(const Value *V) {    return RFV.getCopyFromRegs(DAG, getCurDebugLoc(), Chain, NULL);  } +/// Get the EVTs and ArgFlags collections that represent the return type +/// of the given function.  This does not require a DAG or a return value, and +/// is suitable for use before any DAGs for the function are constructed. +static void getReturnInfo(const Function* F, SmallVectorImpl<EVT> &OutVTs, +                   SmallVectorImpl<ISD::ArgFlagsTy> &OutFlags, +                   TargetLowering &TLI) { +  const Type* ReturnType = F->getReturnType(); + +  SmallVector<EVT, 4> ValueVTs; +  ComputeValueVTs(TLI, ReturnType, ValueVTs); +  unsigned NumValues = ValueVTs.size(); +  if ( NumValues == 0 ) return; + +  for (unsigned j = 0, f = NumValues; j != f; ++j) { +    EVT VT = ValueVTs[j]; +    ISD::NodeType ExtendKind = ISD::ANY_EXTEND; +     +    if (F->paramHasAttr(0, Attribute::SExt)) +      ExtendKind = ISD::SIGN_EXTEND; +    else if (F->paramHasAttr(0, Attribute::ZExt)) +      ExtendKind = ISD::ZERO_EXTEND; + +    // FIXME: C calling convention requires the return type to be promoted to +    // at least 32-bit. But this is not necessary for non-C calling +    // conventions. The frontend should mark functions whose return values +    // require promoting with signext or zeroext attributes. +    if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { +      EVT MinVT = TLI.getRegisterType(F->getContext(), MVT::i32); +      if (VT.bitsLT(MinVT)) +        VT = MinVT; +    } + +    unsigned NumParts = TLI.getNumRegisters(F->getContext(), VT); +    EVT PartVT = TLI.getRegisterType(F->getContext(), VT); +    // 'inreg' on function refers to return value +    ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); +    if (F->paramHasAttr(0, Attribute::InReg)) +      Flags.setInReg(); + +    // Propagate extension type if any +    if (F->paramHasAttr(0, Attribute::SExt)) +      Flags.setSExt(); +    else if (F->paramHasAttr(0, Attribute::ZExt)) +      Flags.setZExt(); + +    for (unsigned i = 0; i < NumParts; ++i) +    { +      OutVTs.push_back(PartVT); +      OutFlags.push_back(Flags); +    } +  } +}  void SelectionDAGLowering::visitRet(ReturnInst &I) {    SDValue Chain = getControlRoot(); @@ -5758,6 +5810,14 @@ void SelectionDAGISel::LowerArguments(BasicBlock *LLVMBB) {    DebugLoc dl = SDL->getCurDebugLoc();    const TargetData *TD = TLI.getTargetData(); +  // Check whether the function can return without sret-demotion. +  SmallVector<EVT, 4> OutVTs; +  SmallVector<ISD::ArgFlagsTy, 4> OutsFlags; +  getReturnInfo(&F, OutVTs, OutsFlags, TLI); +  // For now, assert and bail out if it can't. +  assert(TLI.CanLowerReturn(F.getCallingConv(), F.isVarArg(), OutVTs, OutsFlags, +         DAG) && "Cannot fit return value in registers!"); +    // Set up the incoming argument description vector.    SmallVector<ISD::InputArg, 16> Ins;    unsigned Idx = 1; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 86ec9f2f17a..3b11ef4e369 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1087,6 +1087,17 @@ unsigned X86TargetLowering::getFunctionAlignment(const Function *F) const {  #include "X86GenCallingConv.inc" +bool  +X86TargetLowering::CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, +                        const SmallVectorImpl<EVT> &OutTys, +                        const SmallVectorImpl<ISD::ArgFlagsTy> &ArgsFlags, +                        SelectionDAG &DAG) { +  SmallVector<CCValAssign, 16> RVLocs; +  CCState CCInfo(CallConv, isVarArg, getTargetMachine(), +                 RVLocs, *DAG.getContext()); +  return CCInfo.CheckReturn(OutTys, ArgsFlags, RetCC_X86); +} +  SDValue  X86TargetLowering::LowerReturn(SDValue Chain,                                 CallingConv::ID CallConv, bool isVarArg, diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 7b59b81f81a..0755284a9e2 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -699,6 +699,12 @@ namespace llvm {                    const SmallVectorImpl<ISD::OutputArg> &Outs,                    DebugLoc dl, SelectionDAG &DAG); +    virtual bool +      CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, +                     const SmallVectorImpl<EVT> &OutTys, +                     const SmallVectorImpl<ISD::ArgFlagsTy> &ArgsFlags, +                     SelectionDAG &DAG); +      void ReplaceATOMIC_BINARY_64(SDNode *N, SmallVectorImpl<SDValue> &Results,                                   SelectionDAG &DAG, unsigned NewOp);  | 

