[llvm-commits] [llvm] r165853 - in /llvm/trunk: lib/Target/ARM/ARMISelLowering.cpp test/CodeGen/ARM/2011-06-16-TailCallByVal.ll test/CodeGen/ARM/struct_byval.ll
Manman Ren
mren at apple.com
Fri Oct 12 16:39:43 PDT 2012
Author: mren
Date: Fri Oct 12 18:39:43 2012
New Revision: 165853
URL: http://llvm.org/viewvc/llvm-project?rev=165853&view=rev
Log:
ARM: tail-call inside a function where part of a byval argument is on caller's
local frame causes problem.
For example:
void f(StructToPass s) {
g(&s, sizeof(s));
}
will cause problem with tail-call since part of s is passed via registers and
saved in f's local frame. When g tries to access s, part of s may be corrupted
since f's local frame is popped out before the tail-call.
The current fix is to disable tail-call if getVarArgsRegSaveSize is not 0 for
the caller. This is a conservative approach, if we can prove the address of
s or part of s is not taken and passed to g, it should be okay to perform
tail-call.
rdar://12442472
Modified:
llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
llvm/trunk/test/CodeGen/ARM/2011-06-16-TailCallByVal.ll
llvm/trunk/test/CodeGen/ARM/struct_byval.ll
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=165853&r1=165852&r2=165853&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Oct 12 18:39:43 2012
@@ -1804,6 +1804,14 @@
}
}
+ // If Caller's vararg or byval argument has been split between registers and
+ // stack, do not perform tail call, since part of the argument is in caller's
+ // local frame.
+ const ARMFunctionInfo *AFI_Caller = DAG.getMachineFunction().
+ getInfo<ARMFunctionInfo>();
+ if (AFI_Caller->getVarArgsRegSaveSize())
+ return false;
+
// If the callee takes no arguments then go on to check the results of the
// call.
if (!Outs.empty()) {
Modified: llvm/trunk/test/CodeGen/ARM/2011-06-16-TailCallByVal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-06-16-TailCallByVal.ll?rev=165853&r1=165852&r2=165853&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/2011-06-16-TailCallByVal.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/2011-06-16-TailCallByVal.ll Fri Oct 12 18:39:43 2012
@@ -1,4 +1,9 @@
; RUN: llc < %s -arm-tail-calls=1 | FileCheck %s
+
+; tail call inside a function where byval argument is splitted between
+; registers and stack is currently unsupported.
+; XFAIL: *
+
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
target triple = "thumbv7-apple-ios"
Modified: llvm/trunk/test/CodeGen/ARM/struct_byval.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/struct_byval.ll?rev=165853&r1=165852&r2=165853&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/struct_byval.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/struct_byval.ll Fri Oct 12 18:39:43 2012
@@ -44,3 +44,47 @@
declare i32 @e1(%struct.SmallStruct* nocapture byval %in) nounwind
declare i32 @e2(%struct.LargeStruct* nocapture byval %in) nounwind
declare i32 @e3(%struct.LargeStruct* nocapture byval align 16 %in) nounwind
+
+; rdar://12442472
+; We can't do tail call since address of s is passed to the callee and part of
+; s is in caller's local frame.
+define void @f3(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
+; CHECK: f3
+; CHECK: bl _consumestruct
+entry:
+ %0 = bitcast %struct.SmallStruct* %s to i8*
+ tail call void @consumestruct(i8* %0, i32 80) optsize
+ ret void
+}
+
+define void @f4(%struct.SmallStruct* nocapture byval %s) nounwind optsize {
+; CHECK: f4
+; CHECK: bl _consumestruct
+entry:
+ %addr = getelementptr inbounds %struct.SmallStruct* %s, i32 0, i32 0
+ %0 = bitcast i32* %addr to i8*
+ tail call void @consumestruct(i8* %0, i32 80) optsize
+ ret void
+}
+
+; We can do tail call here since s is in the incoming argument area.
+define void @f5(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
+; CHECK: f5
+; CHECK: b _consumestruct
+entry:
+ %0 = bitcast %struct.SmallStruct* %s to i8*
+ tail call void @consumestruct(i8* %0, i32 80) optsize
+ ret void
+}
+
+define void @f6(i32 %a, i32 %b, i32 %c, i32 %d, %struct.SmallStruct* nocapture byval %s) nounwind optsize {
+; CHECK: f6
+; CHECK: b _consumestruct
+entry:
+ %addr = getelementptr inbounds %struct.SmallStruct* %s, i32 0, i32 0
+ %0 = bitcast i32* %addr to i8*
+ tail call void @consumestruct(i8* %0, i32 80) optsize
+ ret void
+}
+
+declare void @consumestruct(i8* nocapture %structp, i32 %structsize) nounwind
More information about the llvm-commits
mailing list