Enable tail call optimization for functions that return a struct (bug 3664) and for...
authorArnold Schwaighofer <arnold.schwaighofer@gmail.com>
Sat, 28 Mar 2009 08:33:27 +0000 (08:33 +0000)
committerArnold Schwaighofer <arnold.schwaighofer@gmail.com>
Sat, 28 Mar 2009 08:33:27 +0000 (08:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67934 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/TargetLowering.cpp
test/CodeGen/X86/tailcall-i1.ll [new file with mode: 0644]
test/CodeGen/X86/tailcall-structret.ll [new file with mode: 0644]

index 587666f04a3f86dcf015d1ce17965fe6f78d5588..cbe4ca4f5384dd23856df4df1b17c1d8c28d4a7a 100644 (file)
@@ -1206,18 +1206,7 @@ public:
   /// 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) {
-    unsigned NumOps = Ret.getNumOperands();
-    if ((NumOps == 1 &&
-       (Ret.getOperand(0) == SDValue(TheCall,1) ||
-        Ret.getOperand(0) == SDValue(TheCall,0))) ||
-      (NumOps > 1 &&
-       Ret.getOperand(0) == SDValue(TheCall,
-                                    TheCall->getNumValues()-1) &&
-       Ret.getOperand(1) == SDValue(TheCall,0)))
-      return true;
-    return false;
-  }
+  static bool CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret); 
 
   /// GetPossiblePreceedingTailCall - Get preceeding TailCallNodeOpCode node if
   /// it exists. Skip a possible ISD::TokenFactor.
index a08dcb2e49d4852c305d6feb11d91202154378ee..1efc4a677f751a4a3e6ba9f37fb71a15083e88c2 100644 (file)
@@ -2571,3 +2571,27 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
                        DAG.getConstant(magics.s-1, getShiftAmountTy()));
   }
 }
+
+bool TargetLowering::CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret) {
+  unsigned NumOps = Ret.getNumOperands();
+  // Struct return.
+  if(NumOps >= 5&&
+      Ret.getOperand(1).getOpcode()==ISD::MERGE_VALUES &&
+      Ret.getOperand(1).getOperand(0) == SDValue(TheCall, 0))
+    return true;
+  if ((NumOps == 1 &&
+        (Ret.getOperand(0) == SDValue(TheCall,1) ||
+         Ret.getOperand(0) == SDValue(TheCall,0))) ||
+      (NumOps == 3 &&
+       Ret.getOperand(1).getOpcode() == ISD::ANY_EXTEND && 
+       Ret.getOperand(1).getNumOperands()>0 &&
+       Ret.getOperand(1).getOperand(0).getOpcode() == ISD::TRUNCATE &&
+       Ret.getOperand(1).getOperand(0).getNumOperands()>0 &&
+       Ret.getOperand(1).getOperand(0).getOperand(0) == SDValue(TheCall, 0)) ||
+      (NumOps > 1 &&
+       Ret.getOperand(0) == SDValue(TheCall,
+         TheCall->getNumValues()-1) &&
+       Ret.getOperand(1) == SDValue(TheCall,0)))
+    return true;
+  return false;
+}
diff --git a/test/CodeGen/X86/tailcall-i1.ll b/test/CodeGen/X86/tailcall-i1.ll
new file mode 100644 (file)
index 0000000..0ec6a77
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: llvm-as < %s | llc -march=x86 -tailcallopt | grep TAILCALL
+define fastcc i1 @i1test(i32, i32, i32, i32) {
+  entry:
+  %4 = tail call fastcc i1 @i1test( i32 %0, i32 %1, i32 %2, i32 %3)
+  ret i1 %4
+}
diff --git a/test/CodeGen/X86/tailcall-structret.ll b/test/CodeGen/X86/tailcall-structret.ll
new file mode 100644 (file)
index 0000000..e94d7d8
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: llvm-as < %s | llc -march=x86 -tailcallopt | grep TAILCALL
+define fastcc { { i8*, i8* }*, i8*} @init({ { i8*, i8* }*, i8*}, i32) {
+entry:
+      %2 = tail call fastcc { { i8*, i8* }*, i8* } @init({ { i8*, i8*}*, i8*} %0, i32 %1)
+      ret { { i8*, i8* }*, i8*} %2
+}