mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
9d308b85ac
a function into itself. We tried to fix this before in r306495 but that got reverted as the assert was actually hit. This fixes the original bug (which we seem to have lost track of with the revert) by blocking a second remapping when the function being inlined is also the caller and the remapping could succeed but erroneously. The included test case would actually load from an inlined copy of the alloca before this change, failing to load the stored value and miscompiling. Many thanks to Richard Smith for diagnosing a user miscompile to this bug, and to Kyle for the first attempt and initial analysis and David Li for remembering the issue and how to fix it and suggesting the patch. I'm just stitching it together and landing it. =] llvm-svn: 311229
74 lines
2.0 KiB
LLVM
74 lines
2.0 KiB
LLVM
; Inlining in the presence of recursion presents special challenges that we
|
|
; test here.
|
|
;
|
|
; RUN: opt -inline -S < %s | FileCheck %s
|
|
; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
|
|
|
|
define i32 @large_stack_callee(i32 %param) {
|
|
; CHECK-LABEL: define i32 @large_stack_callee(
|
|
entry:
|
|
%yyy = alloca [100000 x i8]
|
|
%r = bitcast [100000 x i8]* %yyy to i8*
|
|
call void @bar(i8* %r)
|
|
ret i32 4
|
|
}
|
|
|
|
; Test a recursive function which calls another function with a large stack. In
|
|
; addition to not inlining the recursive call, we should also not inline the
|
|
; large stack allocation into a potentially recursive frame.
|
|
define i32 @large_stack_recursive_caller(i32 %param) {
|
|
; CHECK-LABEL: define i32 @large_stack_recursive_caller(
|
|
entry:
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NOT: alloca
|
|
%t = call i32 @foo(i32 %param)
|
|
%cmp = icmp eq i32 %t, -1
|
|
br i1 %cmp, label %exit, label %cont
|
|
|
|
cont:
|
|
%r = call i32 @large_stack_recursive_caller(i32 %t)
|
|
; CHECK: call i32 @large_stack_recursive_caller
|
|
%f = call i32 @large_stack_callee(i32 %r)
|
|
; CHECK: call i32 @large_stack_callee
|
|
br label %exit
|
|
|
|
exit:
|
|
ret i32 4
|
|
}
|
|
|
|
declare void @bar(i8* %in)
|
|
|
|
declare i32 @foo(i32 %param)
|
|
|
|
; Check that when inlining a non-recursive path into a function's own body that
|
|
; we get the re-mapping of instructions correct.
|
|
define i32 @test_recursive_inlining_remapping(i1 %init, i8* %addr) {
|
|
; CHECK-LABEL: define i32 @test_recursive_inlining_remapping(
|
|
bb:
|
|
%n = alloca i32
|
|
br i1 %init, label %store, label %load
|
|
; CHECK-NOT: alloca
|
|
;
|
|
; CHECK: %[[N:.*]] = alloca i32
|
|
; CHECK-NEXT: br i1 %init,
|
|
|
|
store:
|
|
store i32 0, i32* %n
|
|
%cast = bitcast i32* %n to i8*
|
|
%v = call i32 @test_recursive_inlining_remapping(i1 false, i8* %cast)
|
|
ret i32 %v
|
|
; CHECK-NOT: call
|
|
;
|
|
; CHECK: store i32 0, i32* %[[N]]
|
|
; CHECK-NEXT: %[[CAST:.*]] = bitcast i32* %[[N]] to i8*
|
|
; CHECK-NEXT: %[[INLINED_LOAD:.*]] = load i32, i32* %[[N]]
|
|
; CHECK-NEXT: ret i32 %[[INLINED_LOAD]]
|
|
;
|
|
; CHECK-NOT: call
|
|
|
|
load:
|
|
%castback = bitcast i8* %addr to i32*
|
|
%n.load = load i32, i32* %castback
|
|
ret i32 %n.load
|
|
}
|