mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-16 08:29:08 +00:00
Add code to check at SelectionDAGISel::LowerArguments time to see if return values can be lowered to registers. Coming soon, code to perform sret-demotion if return values cannot be lowered to registers
llvm-svn: 86324
This commit is contained in:
parent
df21edc554
commit
91ceaa85a2
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user