llvm.org GIT mirror llvm / 791162c
[TailCallElim] Enable marking of calls with byval as tails In r339636 the alias analysis rules were changed with regards to tail calls and byval arguments. Previously, tail calls were assumed not to alias allocas from the current frame. This has been updated, to not assume this for arguments with the byval attribute. This patch aligns TailCallElim with the new rule. Tail marking can now be more aggressive and mark more calls as tails, e.g.: define void @test() { %f = alloca %struct.foo call void @bar(%struct.foo* byval %f) ret void } define void @test2(%struct.foo* byval %f) { call void @bar(%struct.foo* byval %f) ret void } define void @test3(%struct.foo* byval %f) { %agg.tmp = alloca %struct.foo %0 = bitcast %struct.foo* %agg.tmp to i8* %1 = bitcast %struct.foo* %f to i8* call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 40, i1 false) call void @bar(%struct.foo* byval %agg.tmp) ret void } The problematic case where a byval parameter is captured by a call is still handled correctly, and will not be marked as a tail (see PR7272). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343986 91177308-0d34-0410-b5e6-96231b3b80d8 Robert Lougher 11 months ago
3 changed file(s) with 80 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
126126 case Instruction::Call:
127127 case Instruction::Invoke: {
128128 CallSite CS(I);
129 // If the alloca-derived argument is passed byval it is not an escape
130 // point, or a use of an alloca. Calling with byval copies the contents
131 // of the alloca into argument registers or stack slots, which exist
132 // beyond the lifetime of the current frame.
133 if (CS.isArgOperand(U) && CS.isByValArgument(CS.getArgumentNo(U)))
134 continue;
129135 bool IsNocapture =
130136 CS.isDataOperand(U) && CS.doesNotCapture(CS.getDataOperandNo(U));
131137 callUsesLocalStack(CS, IsNocapture);
3939 tail call void @qux(i32* byval %x)
4040 ret void
4141 }
42
43 ; A byval parameter passed into a function which is passed out as byval does
44 ; not block the call from being marked as tail.
45
46 declare void @ext2(i32* byval)
47
48 define void @bar2(i32* byval %x) {
49 call void @ext2(i32* byval %x)
50 ret void
51 }
52
53 define void @foobar(i32* %x) {
54 ; CHECK-LABEL: define void @foobar(
55 ; CHECK: %[[POS:.*]] = alloca i32
56 ; CHECK: %[[VAL:.*]] = load i32, i32* %x
57 ; CHECK: store i32 %[[VAL]], i32* %[[POS]]
58 ; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]
59 ; CHECK: ret void
60 tail call void @bar2(i32* byval %x)
61 ret void
62 }
63
64 define void @barfoo() {
65 ; CHECK-LABEL: define void @barfoo(
66 ; CHECK: %[[POS:.*]] = alloca i32
67 ; CHECK: %[[VAL:.*]] = load i32, i32* %x
68 ; CHECK: store i32 %[[VAL]], i32* %[[POS]]
69 ; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]
70 ; CHECK: ret void
71 %x = alloca i32
72 tail call void @bar2(i32* byval %x)
73 ret void
74 }
197197 call void undef(i8* undef) [ "foo"(i8* %e) ]
198198 unreachable
199199 }
200
201 %struct.foo = type { [10 x i32] }
202
203 ; If an alloca is passed byval it is not a use of the alloca or an escape
204 ; point, and both calls below can be marked tail.
205 define void @test13() {
206 ; CHECK-LABEL: @test13
207 ; CHECK: tail call void @bar(%struct.foo* byval %f)
208 ; CHECK: tail call void @bar(%struct.foo* null)
209 entry:
210 %f = alloca %struct.foo
211 call void @bar(%struct.foo* byval %f)
212 call void @bar(%struct.foo* null)
213 ret void
214 }
215
216 ; A call which passes a byval parameter using byval can be marked tail.
217 define void @test14(%struct.foo* byval %f) {
218 ; CHECK-LABEL: @test14
219 ; CHECK: tail call void @bar
220 entry:
221 call void @bar(%struct.foo* byval %f)
222 ret void
223 }
224
225 ; If a byval parameter is copied into an alloca and passed byval the call can
226 ; be marked tail.
227 define void @test15(%struct.foo* byval %f) {
228 ; CHECK-LABEL: @test15
229 ; CHECK: tail call void @bar
230 entry:
231 %agg.tmp = alloca %struct.foo
232 %0 = bitcast %struct.foo* %agg.tmp to i8*
233 %1 = bitcast %struct.foo* %f to i8*
234 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 40, i1 false)
235 call void @bar(%struct.foo* byval %agg.tmp)
236 ret void
237 }
238
239 declare void @bar(%struct.foo* byval)
240 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)