1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -memcpyopt -S -verify-memoryssa | FileCheck %s
3
4target datalayout = "e"
5
6declare void @foo(i8*)
7declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
8declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
9declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
10
11; Check that the transformation isn't applied if the called function can
12; capture the pointer argument (i.e. the nocapture attribute isn't present)
13define void @test() {
14; CHECK-LABEL: @test(
15; CHECK-NEXT:    [[PTR1:%.*]] = alloca i8, align 1
16; CHECK-NEXT:    [[PTR2:%.*]] = alloca i8, align 1
17; CHECK-NEXT:    call void @foo(i8* [[PTR2]])
18; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[PTR1]], i8* [[PTR2]], i32 1, i1 false)
19; CHECK-NEXT:    call void @foo(i8* [[PTR1]])
20; CHECK-NEXT:    ret void
21;
22  %ptr1 = alloca i8
23  %ptr2 = alloca i8
24  call void @foo(i8* %ptr2)
25  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr1, i8* %ptr2, i32 1, i1 false)
26  call void @foo(i8* %ptr1)
27  ret void
28}
29
30; Same as previous test, but with a bitcasted argument.
31; TODO: Call slot optimization should not be applied here.
32define void @test_bitcast() {
33; CHECK-LABEL: @test_bitcast(
34; CHECK-NEXT:    [[PTR1:%.*]] = alloca [2 x i8], align 1
35; CHECK-NEXT:    [[PTR2:%.*]] = alloca [2 x i8], align 1
36; CHECK-NEXT:    [[PTR1_CAST:%.*]] = bitcast [2 x i8]* [[PTR1]] to i8*
37; CHECK-NEXT:    [[PTR2_CAST:%.*]] = bitcast [2 x i8]* [[PTR2]] to i8*
38; CHECK-NEXT:    [[PTR11:%.*]] = bitcast [2 x i8]* [[PTR1]] to i8*
39; CHECK-NEXT:    call void @foo(i8* [[PTR11]])
40; CHECK-NEXT:    call void @foo(i8* [[PTR1_CAST]])
41; CHECK-NEXT:    ret void
42;
43  %ptr1 = alloca [2 x i8]
44  %ptr2 = alloca [2 x i8]
45  %ptr1.cast = bitcast [2 x i8]* %ptr1 to i8*
46  %ptr2.cast = bitcast [2 x i8]* %ptr2 to i8*
47  call void @foo(i8* %ptr2.cast)
48  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr1.cast, i8* %ptr2.cast, i32 2, i1 false)
49  call void @foo(i8* %ptr1.cast)
50  ret void
51}
52
53; Lifetime of %ptr2 ends before the potential use of the capture in the second
54; call.
55define void @test_lifetime_end() {
56; CHECK-LABEL: @test_lifetime_end(
57; CHECK-NEXT:    [[PTR1:%.*]] = alloca i8, align 1
58; CHECK-NEXT:    [[PTR2:%.*]] = alloca i8, align 1
59; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* [[PTR2]])
60; CHECK-NEXT:    call void @foo(i8* [[PTR2]])
61; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[PTR1]], i8* [[PTR2]], i32 1, i1 false)
62; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* [[PTR2]])
63; CHECK-NEXT:    call void @foo(i8* [[PTR1]])
64; CHECK-NEXT:    ret void
65;
66  %ptr1 = alloca i8
67  %ptr2 = alloca i8
68  call void @llvm.lifetime.start.p0i8(i64 1, i8* %ptr2)
69  call void @foo(i8* %ptr2)
70  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr1, i8* %ptr2, i32 1, i1 false)
71  call void @llvm.lifetime.end.p0i8(i64 1, i8* %ptr2)
72  call void @foo(i8* %ptr1)
73  ret void
74}
75
76; Lifetime of %ptr2 ends before any potential use of the capture because we
77; return from the function.
78define void @test_function_end() {
79; CHECK-LABEL: @test_function_end(
80; CHECK-NEXT:    [[PTR1:%.*]] = alloca i8, align 1
81; CHECK-NEXT:    [[PTR2:%.*]] = alloca i8, align 1
82; CHECK-NEXT:    call void @foo(i8* [[PTR2]])
83; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[PTR1]], i8* [[PTR2]], i32 1, i1 false)
84; CHECK-NEXT:    ret void
85;
86  %ptr1 = alloca i8
87  %ptr2 = alloca i8
88  call void @foo(i8* %ptr2)
89  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %ptr1, i8* %ptr2, i32 1, i1 false)
90  ret void
91}
92