llvm.org GIT mirror llvm / 586cf3d
Transforms: reapply SVN r219899 This restores the commit from SVN r219899 with an additional change to ensure that the CodeGen is correct for the case that was identified as being incorrect (originally PR7272). In the case that during inlining we need to synthesize a value on the stack (i.e. for passing a value byval), then any function involving that alloca must be stripped of its tailness as the restriction that it does not access the parent's stack no longer holds. Unfortunately, a single alloca can cause a rippling effect through out the inlining as the value may be aliased or may be mutated through an escaped external call. As such, we simply track if an alloca has been introduced in the frame during inlining, and strip any tail calls. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220811 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 4 years ago
7 changed file(s) with 112 addition(s) and 49 deletion(s). Raw diff Collapse all Expand all
252252 return false;
253253 AllCallsAreTailCalls = true;
254254
255 // The local stack holds all alloca instructions and all byval arguments.
256255 AllocaDerivedValueTracker Tracker;
257 for (Argument &Arg : F.args()) {
258 if (Arg.hasByValAttr())
259 Tracker.walk(&Arg);
260 }
261256 for (auto &BB : F) {
262257 for (auto &I : BB)
263258 if (AllocaInst *AI = dyn_cast(&I))
313308 for (auto &Arg : CI->arg_operands()) {
314309 if (isa(Arg.getUser()))
315310 continue;
316 if (Argument *A = dyn_cast(Arg.getUser()))
317 if (!A->hasByValAttr())
318 continue;
311 if (isa(Arg.getUser()))
312 continue;
319313 SafeToTail = false;
320314 break;
321315 }
742742 static Value *HandleByValArgument(Value *Arg, Instruction *TheCall,
743743 const Function *CalledFunc,
744744 InlineFunctionInfo &IFI,
745 unsigned ByValAlignment) {
745 unsigned ByValAlignment,
746 bool &AddedNewAllocas) {
746747 PointerType *ArgTy = cast(Arg->getType());
747748 Type *AggTy = ArgTy->getElementType();
748749
784785
785786 // Uses of the argument in the function should use our new alloca
786787 // instead.
788 AddedNewAllocas = true;
787789 return NewAlloca;
788790 }
789791
957959 SmallVector Returns;
958960 ClonedCodeInfo InlinedFunctionInfo;
959961 Function::iterator FirstNewBlock;
962 bool AddedNewAllocas = false;
960963
961964 { // Scope to destroy VMap after cloning.
962965 ValueToValueMapTy VMap;
980983 // modify the struct.
981984 if (CS.isByValArgument(ArgNo)) {
982985 ActualArg = HandleByValArgument(ActualArg, TheCall, CalledFunc, IFI,
983 CalledFunc->getParamAlignment(ArgNo+1));
986 CalledFunc->getParamAlignment(ArgNo+1),
987 AddedNewAllocas);
984988 if (ActualArg != *AI)
985989 ByValInit.push_back(std::make_pair(ActualArg, (Value*) *AI));
986990 }
10951099 // f -> musttail g -> tail f ==> f -> tail f
10961100 // f -> g -> musttail f ==> f -> f
10971101 // f -> g -> tail f ==> f -> f
1102 //
1103 // If an alloca was introduced in the frame due to a byval parameter
1104 // being passed to a subsequent call, tail calls must have the tail
1105 // stripped as they may not access variables in the caller's stack.
1106 // A single alloca ripples through out as the alloca may be aliased by
1107 // bitcasts or may escape and be mutated outside of the function.
10981108 CallInst::TailCallKind ChildTCK = CI->getTailCallKind();
10991109 ChildTCK = std::min(CallSiteTailKind, ChildTCK);
1100 CI->setTailCallKind(ChildTCK);
1110 if (AddedNewAllocas)
1111 CI->setTailCallKind(CallInst::TCK_None);
1112 else
1113 CI->setTailCallKind(ChildTCK);
11011114 InlinedMustTailCalls |= CI->isMustTailCall();
11021115
11031116 // Calls inlined through a 'nounwind' call site should be marked
3333 ; CHECK: %[[VAL:.*]] = load i32* %x
3434 ; CHECK: store i32 %[[VAL]], i32* %[[POS]]
3535 ; CHECK: {{^ *}}call void @ext(i32* %[[POS]]
36 ; CHECK: tail call void @ext(i32* null)
36 ; CHECK: {{^ *}}call void @ext(i32* null)
3737 ; CHECK: ret void
3838 tail call void @qux(i32* byval %x)
3939 ret void
4545 }
4646 define void @test_musttail_basic_a(i32* %p) {
4747 musttail call void @test_musttail_basic_b(i32* %p)
48 ret void
49 }
50
51 ; Don't insert lifetime end markers here, the lifetime is trivially over due
52 ; the return.
53 ; CHECK: define void @test_byval_a(
54 ; CHECK: musttail call void @test_byval_c(
55 ; CHECK-NEXT: ret void
56
57 declare void @test_byval_c(i32* byval %p)
58 define internal void @test_byval_b(i32* byval %p) {
59 musttail call void @test_byval_c(i32* byval %p)
60 ret void
61 }
62 define void @test_byval_a(i32* byval %p) {
63 musttail call void @test_byval_b(i32* byval %p)
64 ret void
65 }
66
67 ; Don't insert a stack restore, we're about to return.
68 ; CHECK: define void @test_dynalloca_a(
69 ; CHECK: call i8* @llvm.stacksave(
70 ; CHECK: alloca i8, i32 %n
71 ; CHECK: musttail call void @test_dynalloca_c(
72 ; CHECK-NEXT: ret void
73
74 declare void @escape(i8* %buf)
75 declare void @test_dynalloca_c(i32* byval %p, i32 %n)
76 define internal void @test_dynalloca_b(i32* byval %p, i32 %n) alwaysinline {
77 %buf = alloca i8, i32 %n ; dynamic alloca
78 call void @escape(i8* %buf) ; escape it
79 musttail call void @test_dynalloca_c(i32* byval %p, i32 %n)
80 ret void
81 }
82 define void @test_dynalloca_a(i32* byval %p, i32 %n) {
83 musttail call void @test_dynalloca_b(i32* byval %p, i32 %n)
8448 ret void
8549 }
8650
0 ; RUN: opt -dse -inline -S %s | FileCheck %s
1
2 declare void @external(i32* byval)
3 declare i32 @identity(i32* byval)
4
5 ; An alloca in the inlinee should not force the tail to be stripped
6
7 define void @inlinee_with_alloca() {
8 %local = alloca i32
9 store i32 42, i32* %local, align 4
10 tail call void @external(i32* byval %local)
11 ret void
12 }
13
14 define void @inliner_without_alloca() {
15 tail call void @inlinee_with_alloca()
16 ret void
17 }
18
19 ; CHECK-LABEL: inliner_without_alloca
20 ; CHECK-NEXT: %local.i = alloca i32
21 ; CHECK: store i32 42, i32* %local.i
22 ; CHECK: tail call void @external
23 ; CHECK: ret
24
25 ; An alloca in the inliner should not force the tail to be stripped
26
27 define i32 @inliner_with_alloca() {
28 %local = alloca i32
29 store i32 42, i32* %local, align 4
30 %1 = tail call i32 @identity(i32* byval %local)
31 ret i32 %1
32 }
33
34 ; CHECK-LABEL: inliner_with_alloca
35 ; CHECK: %local = alloca i32
36 ; CHECK: store i32 42, i32* %local
37 ; CHECK: %1 = tail call i32 @identity
38 ; CHECK: ret i32 %1
39
40 ; Force the synthesis of the value through the byval parameter.
41 ; The alloca should force the tail to be stripped
42
43 define void @inlinee_with_passthru(i32* byval %value) {
44 tail call void @external(i32* byval %value)
45 ret void
46 }
47
48 define void @strip_tail(i32* %value) {
49 tail call void @inlinee_with_passthru(i32* %value)
50 ret void
51 }
52
53 ; CHECK-LABEL: strip_tail
54 ; CHECK: %value1 = alloca i32
55 ; CHECK: {{^ *}}call void @external
56 ; CHECK: ret void
57
146146 ; Don't tail call if a byval arg is captured.
147147 define void @test9(i32* byval %a) {
148148 ; CHECK-LABEL: define void @test9(
149 ; CHECK: {{^ *}}call void @use(
149 ; CHECK: tail call void @use(
150150 call void @use(i32* %a)
151151 ret void
152152 }
0 ; RUN: opt -mtriple i386 -Os -S %s -o - | FileCheck %s
1 ; RUN: opt -mtriple x86_64 -Os -S %s -o - | FileCheck %s
2 ; RUN: opt -mtriple armv7 -Os -S %s -o - | FileCheck %s
3
4 %struct.D16 = type { [16 x double] }
5
6 declare void @_Z2OpP3D16PKS_S2_(%struct.D16*, %struct.D16*, %struct.D16*)
7
8 define void @_Z7TestRefRK3D16S1_(%struct.D16* noalias sret %agg.result, %struct.D16* %RHS, %struct.D16* %LHS) {
9 %1 = alloca %struct.D16*, align 8
10 %2 = alloca %struct.D16*, align 8
11 store %struct.D16* %RHS, %struct.D16** %1, align 8
12 store %struct.D16* %LHS, %struct.D16** %2, align 8
13 %3 = load %struct.D16** %1, align 8
14 %4 = load %struct.D16** %2, align 8
15 call void @_Z2OpP3D16PKS_S2_(%struct.D16* %agg.result, %struct.D16* %3, %struct.D16* %4)
16 ret void
17 }
18
19 ; CHECK: define void @_Z7TestRefRK3D16S1_({{.*}}) {
20 ; CHECK: tail call void @_Z2OpP3D16PKS_S2_(%struct.D16* %agg.result, %struct.D16* %RHS, %struct.D16* %LHS)
21 ; CHECK: ret void
22 ; CHECK: }
23
24 define void @_Z7TestVal3D16S_(%struct.D16* noalias sret %agg.result, %struct.D16* byval align 8 %RHS, %struct.D16* byval align 8 %LHS) {
25 call void @_Z2OpP3D16PKS_S2_(%struct.D16* %agg.result, %struct.D16* %RHS, %struct.D16* %LHS)
26 ret void
27 }
28
29 ; CHECK: define void @_Z7TestVal3D16S_({{.*}}) {
30 ; CHECK: tail call void @_Z2OpP3D16PKS_S2_(%struct.D16* %agg.result, %struct.D16* %RHS, %struct.D16* %LHS)
31 ; CHECK: ret void
32 ; CHECK: }
33