aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff options
context:
space:
mode:
authorArnold Schwaighofer <arnold.schwaighofer@gmail.com>2007-10-11 19:40:01 +0000
committerArnold Schwaighofer <arnold.schwaighofer@gmail.com>2007-10-11 19:40:01 +0000
commite2d6bbb00da7530c4f8846774bfeddeef56f66ed (patch)
treee6e745a81699085d757db166e645f8a6639cde7a /lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
parente702a31df3fd7c0076ffdc51d69753712c7b08af (diff)
downloadexternal_llvm-e2d6bbb00da7530c4f8846774bfeddeef56f66ed.zip
external_llvm-e2d6bbb00da7530c4f8846774bfeddeef56f66ed.tar.gz
external_llvm-e2d6bbb00da7530c4f8846774bfeddeef56f66ed.tar.bz2
Added tail call optimization to the x86 back end. It can be
enabled by passing -tailcallopt to llc. The optimization is performed if the following conditions are satisfied: * caller/callee are fastcc * elf/pic is disabled OR elf/pic enabled + callee is in module + callee has visibility protected or hidden git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42870 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp48
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 5f32165..b1bf475 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -4444,6 +4444,48 @@ static void copyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB,
}
}
+/// CheckDAGForTailCallsAndFixThem - This Function looks for CALL nodes in the
+/// DAG and fixes their tailcall attribute operand
+static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
+ TargetLowering& TLI) {
+ SDNode * Ret = NULL;
+ SDOperand Terminator = DAG.getRoot();
+
+ // Find RET node.
+ if (Terminator.getOpcode() == ISD::RET) {
+ Ret = Terminator.Val;
+ }
+
+ // Fix tail call attribute of CALL nodes.
+ for (SelectionDAG::allnodes_iterator BE = DAG.allnodes_begin(),
+ BI = prior(DAG.allnodes_end()); BI != BE; --BI) {
+ if (BI->getOpcode() == ISD::CALL) {
+ SDOperand OpRet(Ret, 0);
+ SDOperand OpCall(static_cast<SDNode*>(BI), 0);
+ bool isMarkedTailCall =
+ cast<ConstantSDNode>(OpCall.getOperand(3))->getValue() != 0;
+ // If CALL node has tail call attribute set to true and the call is not
+ // eligible (no RET or the target rejects) the attribute is fixed to
+ // false. The TargetLowering::IsEligibleForTailCallOptimization function
+ // must correctly identify tail call optimizable calls.
+ if (isMarkedTailCall &&
+ (Ret==NULL ||
+ !TLI.IsEligibleForTailCallOptimization(OpCall, OpRet, DAG))) {
+ SmallVector<SDOperand, 32> Ops;
+ unsigned idx=0;
+ for(SDNode::op_iterator I =OpCall.Val->op_begin(),
+ E=OpCall.Val->op_end(); I!=E; I++, idx++) {
+ if (idx!=3)
+ Ops.push_back(*I);
+ else
+ Ops.push_back(DAG.getConstant(false, TLI.getPointerTy()));
+ }
+ DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
+ }
+ }
+ }
+}
+
void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
FunctionLoweringInfo &FuncInfo) {
@@ -4621,6 +4663,12 @@ void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
// Make sure the root of the DAG is up-to-date.
DAG.setRoot(SDL.getRoot());
+
+ // Check whether calls in this block are real tail calls. Fix up CALL nodes
+ // with correct tailcall attribute so that the target can rely on the tailcall
+ // attribute indicating whether the call is really eligible for tail call
+ // optimization.
+ CheckDAGForTailCallsAndFixThem(DAG, TLI);
}
void SelectionDAGISel::CodeGenAndEmitDAG(SelectionDAG &DAG) {