aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-08-05 01:29:28 +0000
committerDan Gohman <gohman@apple.com>2009-08-05 01:29:28 +0000
commit9178de1d2b1e0787539b83ed54ad505ff13169e8 (patch)
tree8c4b03205992cfc18f04ca67d586796b5d0dd344 /include/llvm
parent32e5ec2ca24e5a8582db12f6fa88fec2e7a6657b (diff)
downloadexternal_llvm-9178de1d2b1e0787539b83ed54ad505ff13169e8.zip
external_llvm-9178de1d2b1e0787539b83ed54ad505ff13169e8.tar.gz
external_llvm-9178de1d2b1e0787539b83ed54ad505ff13169e8.tar.bz2
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL, ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering provides three virtual functions for targets to override: LowerFormalArguments, LowerCall, and LowerRet, which replace the custom lowering done on the special nodes. They provide the same information, but in a more immediately usable format. This also reworks much of the target-independent tail call logic. The decision of whether or not to perform a tail call is now cleanly split between target-independent portions, and the target dependent portion in IsEligibleForTailCallOptimization. This also synchronizes all in-tree targets, to help enable future refactoring and feature work. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78142 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm')
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h22
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h14
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h147
-rw-r--r--include/llvm/Target/TargetLowering.h85
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td1
5 files changed, 119 insertions, 150 deletions
diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h
index 11f6e80..02a2bf5 100644
--- a/include/llvm/CodeGen/CallingConvLower.h
+++ b/include/llvm/CodeGen/CallingConvLower.h
@@ -172,17 +172,20 @@ public:
return UsedRegs[Reg/32] & (1 << (Reg&31));
}
- /// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
+ /// AnalyzeFormalArguments - Analyze an array of argument values,
/// incorporating info about the formals into this state.
- void AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn);
+ void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
+ CCAssignFn Fn);
- /// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
+ /// AnalyzeReturn - Analyze the returned values of a return,
/// incorporating info about the result values into this state.
- void AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn);
+ void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
+ CCAssignFn Fn);
- /// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
- /// about the passed values into this state.
- void AnalyzeCallOperands(CallSDNode *TheCall, 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,
+ CCAssignFn Fn);
/// AnalyzeCallOperands - Same as above except it takes vectors of types
/// and argument flags.
@@ -190,9 +193,10 @@ public:
SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
CCAssignFn Fn);
- /// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
+ /// AnalyzeCallResult - Analyze the return values of a call,
/// incorporating info about the passed values into this state.
- void AnalyzeCallResult(CallSDNode *TheCall, CCAssignFn Fn);
+ void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
+ CCAssignFn Fn);
/// AnalyzeCallResult - Same as above except it's specialized for calls which
/// produce a single value.
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index dc93f12..6d3fdc4 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -319,7 +319,6 @@ public:
SDValue getExternalSymbol(const char *Sym, DebugLoc dl, MVT VT);
SDValue getTargetExternalSymbol(const char *Sym, MVT VT,
unsigned char TargetFlags = 0);
- SDValue getArgFlags(ISD::ArgFlagsTy Flags);
SDValue getValueType(MVT);
SDValue getRegister(unsigned Reg, MVT VT);
SDValue getDbgStopPoint(DebugLoc DL, SDValue Root,
@@ -460,6 +459,12 @@ public:
SDValue N1, SDValue N2, SDValue N3, SDValue N4,
SDValue N5);
+ /// getStackArgumentTokenFactor - Compute a TokenFactor to force all
+ /// the incoming stack arguments to be loaded from the stack. This is
+ /// used in tail call lowering to protect stack arguments from being
+ /// clobbered.
+ SDValue getStackArgumentTokenFactor(SDValue Chain);
+
SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src,
SDValue Size, unsigned Align, bool AlwaysInline,
const Value *DstSV, uint64_t DstSVOff,
@@ -534,13 +539,6 @@ public:
/// getMergeValues - Create a MERGE_VALUES node from the given operands.
SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl);
- /// getCall - Create a CALL node from the given information.
- ///
- SDValue getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs,
- bool IsTailCall, bool isInreg, SDVTList VTs,
- const SDValue *Operands, unsigned NumOperands,
- unsigned NumFixedArgs);
-
/// getLoad - Loads are not normal binary operators: their result type is not
/// determined by their operands, and they produce a value AND a token chain.
///
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 6dc55ff..9749d8f 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -97,7 +97,7 @@ namespace ISD {
AssertSext, AssertZext,
// Various leaf nodes.
- BasicBlock, VALUETYPE, ARG_FLAGS, CONDCODE, Register,
+ BasicBlock, VALUETYPE, CONDCODE, Register,
Constant, ConstantFP,
GlobalAddress, GlobalTLSAddress, FrameIndex,
JumpTable, ConstantPool, ExternalSymbol,
@@ -180,38 +180,6 @@ namespace ISD {
// UNDEF - An undefined node
UNDEF,
- /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node
- /// represents the formal arguments for a function. CC# is a Constant value
- /// indicating the calling convention of the function, and ISVARARG is a
- /// flag that indicates whether the function is varargs or not. This node
- /// has one result value for each incoming argument, plus one for the output
- /// chain. It must be custom legalized. See description of CALL node for
- /// FLAG argument contents explanation.
- ///
- FORMAL_ARGUMENTS,
-
- /// RV1, RV2...RVn, CHAIN = CALL(CHAIN, CALLEE,
- /// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn)
- /// This node represents a fully general function call, before the legalizer
- /// runs. This has one result value for each argument / flag pair, plus
- /// a chain result. It must be custom legalized. Flag argument indicates
- /// misc. argument attributes. Currently:
- /// Bit 0 - signness
- /// Bit 1 - 'inreg' attribute
- /// Bit 2 - 'sret' attribute
- /// Bit 4 - 'byval' attribute
- /// Bit 5 - 'nest' attribute
- /// Bit 6-9 - alignment of byval structures
- /// Bit 10-26 - size of byval structures
- /// Bits 31:27 - argument ABI alignment in the first argument piece and
- /// alignment '1' in other argument pieces.
- ///
- /// CALL nodes use the CallSDNode subclass of SDNode, which
- /// additionally carries information about the calling convention,
- /// whether the call is varargs, and if it's marked as a tail call.
- ///
- CALL,
-
// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by
// a Constant, which is required to be operand #1) half of the integer or
// float value specified as operand #0. This is only for use before
@@ -515,12 +483,6 @@ namespace ISD {
// chain, cc, lhs, rhs, block to branch to if condition is true.
BR_CC,
- // RET - Return from function. The first operand is the chain,
- // and any subsequent operands are pairs of return value and return value
- // attributes (see CALL for description of attributes) for the function.
- // This operation can have variable number of operands.
- RET,
-
// INLINEASM - Represents an inline asm block. This node always has two
// return values: a chain and a flag result. The inputs are as follows:
// Operand #0 : Input chain.
@@ -2234,80 +2196,41 @@ namespace ISD {
/// getRawBits - Represent the flags as a bunch of bits.
uint64_t getRawBits() const { return Flags; }
};
-}
-
-/// ARG_FLAGSSDNode - Leaf node holding parameter flags.
-class ARG_FLAGSSDNode : public SDNode {
- ISD::ArgFlagsTy TheFlags;
- friend class SelectionDAG;
- explicit ARG_FLAGSSDNode(ISD::ArgFlagsTy Flags)
- : SDNode(ISD::ARG_FLAGS, DebugLoc::getUnknownLoc(),
- getSDVTList(MVT::Other)), TheFlags(Flags) {
- }
-public:
- ISD::ArgFlagsTy getArgFlags() const { return TheFlags; }
-
- static bool classof(const ARG_FLAGSSDNode *) { return true; }
- static bool classof(const SDNode *N) {
- return N->getOpcode() == ISD::ARG_FLAGS;
- }
-};
-
-/// CallSDNode - Node for calls -- ISD::CALL.
-class CallSDNode : public SDNode {
- unsigned CallingConv;
- bool IsVarArg;
- bool IsTailCall;
- unsigned NumFixedArgs;
- // We might eventually want a full-blown Attributes for the result; that
- // will expand the size of the representation. At the moment we only
- // need Inreg.
- bool Inreg;
- friend class SelectionDAG;
- CallSDNode(unsigned cc, DebugLoc dl, bool isvararg, bool istailcall,
- bool isinreg, SDVTList VTs, const SDValue *Operands,
- unsigned numOperands, unsigned numFixedArgs)
- : SDNode(ISD::CALL, dl, VTs, Operands, numOperands),
- CallingConv(cc), IsVarArg(isvararg), IsTailCall(istailcall),
- NumFixedArgs(numFixedArgs), Inreg(isinreg) {}
-public:
- unsigned getCallingConv() const { return CallingConv; }
- unsigned isVarArg() const { return IsVarArg; }
- unsigned isTailCall() const { return IsTailCall; }
- unsigned isInreg() const { return Inreg; }
- /// Set this call to not be marked as a tail call. Normally setter
- /// methods in SDNodes are unsafe because it breaks the CSE map,
- /// but we don't include the tail call flag for calls so it's ok
- /// in this case.
- void setNotTailCall() { IsTailCall = false; }
-
- SDValue getChain() const { return getOperand(0); }
- SDValue getCallee() const { return getOperand(1); }
-
- unsigned getNumArgs() const { return (getNumOperands() - 2) / 2; }
- unsigned getNumFixedArgs() const {
- if (isVarArg())
- return NumFixedArgs;
- else
- return getNumArgs();
- }
- SDValue getArg(unsigned i) const { return getOperand(2+2*i); }
- SDValue getArgFlagsVal(unsigned i) const {
- return getOperand(3+2*i);
- }
- ISD::ArgFlagsTy getArgFlags(unsigned i) const {
- return cast<ARG_FLAGSSDNode>(getArgFlagsVal(i).getNode())->getArgFlags();
- }
-
- unsigned getNumRetVals() const { return getNumValues() - 1; }
- MVT getRetValType(unsigned i) const { return getValueType(i); }
+ /// InputArg - This struct carries flags and type information about a
+ /// single incoming (formal) argument or incoming (from the perspective
+ /// of the caller) return value virtual register.
+ ///
+ struct InputArg {
+ ArgFlagsTy Flags;
+ MVT VT;
+ bool Used;
+
+ InputArg() : VT(MVT::Other), Used(false) {}
+ InputArg(ISD::ArgFlagsTy flags, MVT vt, bool used)
+ : Flags(flags), VT(vt), Used(used) {
+ assert(VT.isSimple() &&
+ "InputArg value type must be Simple!");
+ }
+ };
- static bool classof(const CallSDNode *) { return true; }
- static bool classof(const SDNode *N) {
- return N->getOpcode() == ISD::CALL;
- }
-};
+ /// OutputArg - This struct carries flags and a value for a
+ /// single outgoing (actual) argument or outgoing (from the perspective
+ /// of the caller) return value virtual register.
+ ///
+ struct OutputArg {
+ ArgFlagsTy Flags;
+ SDValue Val;
+ bool IsFixed;
+
+ OutputArg() : IsFixed(false) {}
+ OutputArg(ISD::ArgFlagsTy flags, SDValue val, bool isfixed)
+ : Flags(flags), Val(val), IsFixed(isfixed) {
+ assert(Val.getValueType().isSimple() &&
+ "OutputArg value type must be Simple!");
+ }
+ };
+}
/// VTSDNode - This class is used to represent MVT's, which are used
/// to parameterize some operations.
@@ -2491,7 +2414,7 @@ typedef LoadSDNode LargestSDNode;
/// MostAlignedSDNode - The SDNode class with the greatest alignment
/// requirement.
///
-typedef ARG_FLAGSSDNode MostAlignedSDNode;
+typedef GlobalAddressSDNode MostAlignedSDNode;
namespace ISD {
/// isNormalLoad - Returns true if the specified node is a non-extending
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 8e5844e..47c1ba5 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -1091,16 +1091,27 @@ public:
// the SelectionDAGLowering code knows how to lower these.
//
- /// LowerArguments - This hook must be implemented to indicate how we should
- /// lower the arguments for the specified function, into the specified DAG.
- virtual void
- LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue>& ArgValues, DebugLoc dl);
+ /// LowerFormalArguments - This hook must be implemented to lower the
+ /// incoming (formal) arguments, described by the Ins array, into the
+ /// specified DAG. The implementation should fill in the InVals array
+ /// with legal-type argument values, and return the resulting token
+ /// chain value.
+ ///
+ virtual SDValue
+ LowerFormalArguments(SDValue Chain,
+ unsigned CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
+ assert(0 && "Not Implemented");
+ return SDValue(); // this is here to silence compiler errors
+ }
- /// LowerCallTo - This hook lowers an abstract call to a function into an
+ /// LowerCallTo - This function lowers an abstract call to a function into an
/// actual call. This returns a pair of operands. The first element is the
/// return value for the function (if RetTy is not VoidTy). The second
- /// element is the outgoing token chain.
+ /// element is the outgoing token chain. It calls LowerCall to do the actual
+ /// lowering.
struct ArgListEntry {
SDValue Node;
const Type* Ty;
@@ -1116,11 +1127,47 @@ public:
isSRet(false), isNest(false), isByVal(false), Alignment(0) { }
};
typedef std::vector<ArgListEntry> ArgListTy;
- virtual std::pair<SDValue, SDValue>
+ std::pair<SDValue, SDValue>
LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt,
bool isVarArg, bool isInreg, unsigned NumFixedArgs,
- unsigned CallingConv, bool isTailCall, SDValue Callee,
- ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl);
+ unsigned CallConv, bool isTailCall, bool isReturnValueUsed,
+ SDValue Callee, ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl);
+
+ /// LowerCall - This hook must be implemented to lower calls into the
+ /// the specified DAG. The outgoing arguments to the call are described
+ /// by the Outs array, and the values to be returned by the call are
+ /// described by the Ins array. The implementation should fill in the
+ /// InVals array with legal-type return values from the call, and return
+ /// the resulting token chain value.
+ ///
+ /// The isTailCall flag here is normative. If it is true, the
+ /// implementation must emit a tail call. The
+ /// IsEligibleForTailCallOptimization hook should be used to catch
+ /// cases that cannot be handled.
+ ///
+ virtual SDValue
+ LowerCall(SDValue Chain, SDValue Callee,
+ unsigned CallConv, bool isVarArg, bool isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
+ assert(0 && "Not Implemented");
+ return SDValue(); // this is here to silence compiler errors
+ }
+
+ /// 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
+ /// value.
+ ///
+ virtual SDValue
+ LowerReturn(SDValue Chain, unsigned CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) {
+ assert(0 && "Not Implemented");
+ return SDValue(); // this is here to silence compiler errors
+ }
/// EmitTargetCodeForMemcpy - Emit target-specific code that performs a
/// memcpy. This can be used by targets to provide code sequences for cases
@@ -1216,19 +1263,17 @@ public:
/// IsEligibleForTailCallOptimization - Check whether the call is eligible for
/// tail call optimization. Targets which want to do tail call optimization
- /// should override this function.
- virtual bool IsEligibleForTailCallOptimization(CallSDNode *Call,
- SDValue Ret,
- SelectionDAG &DAG) const {
+ /// should override this function.
+ virtual bool
+ IsEligibleForTailCallOptimization(SDValue Callee,
+ unsigned CalleeCC,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ SelectionDAG& DAG) const {
+ // Conservative default: no calls are eligible.
return false;
}
- /// CheckTailCallReturnConstraints - Check whether CALL node immediatly
- /// preceeds the RET node and whether the return uses the result of the node
- /// or is a void return. This function can be used by the target to determine
- /// eligiblity of tail call optimization.
- static bool CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret);
-
/// GetPossiblePreceedingTailCall - Get preceeding TailCallNodeOpCode node if
/// it exists. Skip a possible ISD::TokenFactor.
static SDValue GetPossiblePreceedingTailCall(SDValue Chain,
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index 364d4d0..9a9125e 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -345,7 +345,6 @@ def vsetcc : SDNode<"ISD::VSETCC" , SDTSetCC>;
def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
-def ret : SDNode<"ISD::RET" , SDTNone, [SDNPHasChain]>;
def trap : SDNode<"ISD::TRAP" , SDTNone,
[SDNPHasChain, SDNPSideEffect]>;