Initial support for nested CALLSEQ_START/CALLSEQ_END constructs in LegalizeDAG.
authorStuart Hastings <stuart@apple.com>
Thu, 9 Dec 2010 21:25:20 +0000 (21:25 +0000)
committerStuart Hastings <stuart@apple.com>
Thu, 9 Dec 2010 21:25:20 +0000 (21:25 +0000)
Necessary for byval support on ARM.  Radar 7662569.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121412 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

index aff087f61ee8a563428ae997db80a5c03980177a..de6863a71cf6bea4863b7019dc775a9c92b83b0f 100644 (file)
@@ -252,8 +252,10 @@ void SelectionDAGLegalize::LegalizeDAG() {
 
 /// FindCallEndFromCallStart - Given a chained node that is part of a call
 /// sequence, find the CALLSEQ_END node that terminates the call sequence.
-static SDNode *FindCallEndFromCallStart(SDNode *Node) {
-  if (Node->getOpcode() == ISD::CALLSEQ_END)
+static SDNode *FindCallEndFromCallStart(SDNode *Node, int depth = 0) {
+  if (Node->getOpcode() == ISD::CALLSEQ_START)
+    depth++;
+  if ((Node->getOpcode() == ISD::CALLSEQ_END) && (depth == 1))
     return Node;
   if (Node->use_empty())
     return 0;   // No CallSeqEnd
@@ -284,7 +286,7 @@ static SDNode *FindCallEndFromCallStart(SDNode *Node) {
     SDNode *User = *UI;
     for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i)
       if (User->getOperand(i) == TheChain)
-        if (SDNode *Result = FindCallEndFromCallStart(User))
+        if (SDNode *Result = FindCallEndFromCallStart(User, depth))
           return Result;
   }
   return 0;
@@ -293,12 +295,26 @@ static SDNode *FindCallEndFromCallStart(SDNode *Node) {
 /// FindCallStartFromCallEnd - Given a chained node that is part of a call
 /// sequence, find the CALLSEQ_START node that initiates the call sequence.
 static SDNode *FindCallStartFromCallEnd(SDNode *Node) {
+  int nested = 0;
   assert(Node && "Didn't find callseq_start for a call??");
-  if (Node->getOpcode() == ISD::CALLSEQ_START) return Node;
-
-  assert(Node->getOperand(0).getValueType() == MVT::Other &&
-         "Node doesn't have a token chain argument!");
-  return FindCallStartFromCallEnd(Node->getOperand(0).getNode());
+  while (Node->getOpcode() != ISD::CALLSEQ_START || nested) {
+    Node = Node->getOperand(0).getNode();
+    assert(Node->getOperand(0).getValueType() == MVT::Other &&
+           "Node doesn't have a token chain argument!");
+    switch (Node->getOpcode()) {
+    default:
+      break;
+    case ISD::CALLSEQ_START:
+      if (!nested)
+        return Node;
+      nested--;
+      break;
+    case ISD::CALLSEQ_END:
+      nested++;
+      break;
+    }
+  }
+  return 0;
 }
 
 /// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to