1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
2; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
3; Test that we only promote arguments when the caller/callee have compatible
4; function attrubtes.
5
6target triple = "x86_64-unknown-linux-gnu"
7
8define internal fastcc void @no_promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1) #0 {
9; CHECK-LABEL: define {{[^@]+}}@no_promote_avx2
10; CHECK-SAME: (<4 x i64>* [[ARG:%.*]], <4 x i64>* readonly [[ARG1:%.*]])
11; CHECK-NEXT:  bb:
12; CHECK-NEXT:    [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]]
13; CHECK-NEXT:    store <4 x i64> [[TMP]], <4 x i64>* [[ARG]]
14; CHECK-NEXT:    ret void
15;
16bb:
17  %tmp = load <4 x i64>, <4 x i64>* %arg1
18  store <4 x i64> %tmp, <4 x i64>* %arg
19  ret void
20}
21
22define void @no_promote(<4 x i64>* %arg) #1 {
23; CHECK-LABEL: define {{[^@]+}}@no_promote
24; CHECK-SAME: (<4 x i64>* [[ARG:%.*]])
25; CHECK-NEXT:  bb:
26; CHECK-NEXT:    [[TMP:%.*]] = alloca <4 x i64>, align 32
27; CHECK-NEXT:    [[TMP2:%.*]] = alloca <4 x i64>, align 32
28; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8*
29; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
30; CHECK-NEXT:    call fastcc void @no_promote_avx2(<4 x i64>* [[TMP2]], <4 x i64>* [[TMP]])
31; CHECK-NEXT:    [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32
32; CHECK-NEXT:    store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2
33; CHECK-NEXT:    ret void
34;
35bb:
36  %tmp = alloca <4 x i64>, align 32
37  %tmp2 = alloca <4 x i64>, align 32
38  %tmp3 = bitcast <4 x i64>* %tmp to i8*
39  call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
40  call fastcc void @no_promote_avx2(<4 x i64>* %tmp2, <4 x i64>* %tmp)
41  %tmp4 = load <4 x i64>, <4 x i64>* %tmp2, align 32
42  store <4 x i64> %tmp4, <4 x i64>* %arg, align 2
43  ret void
44}
45
46define internal fastcc void @promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1) #0 {
47; CHECK-LABEL: define {{[^@]+}}@promote_avx2
48; CHECK-SAME: (<4 x i64>* [[ARG:%.*]], <4 x i64> [[ARG1_VAL:%.*]])
49; CHECK-NEXT:  bb:
50; CHECK-NEXT:    store <4 x i64> [[ARG1_VAL]], <4 x i64>* [[ARG]]
51; CHECK-NEXT:    ret void
52;
53bb:
54  %tmp = load <4 x i64>, <4 x i64>* %arg1
55  store <4 x i64> %tmp, <4 x i64>* %arg
56  ret void
57}
58
59define void @promote(<4 x i64>* %arg) #0 {
60; CHECK-LABEL: define {{[^@]+}}@promote
61; CHECK-SAME: (<4 x i64>* [[ARG:%.*]])
62; CHECK-NEXT:  bb:
63; CHECK-NEXT:    [[TMP:%.*]] = alloca <4 x i64>, align 32
64; CHECK-NEXT:    [[TMP2:%.*]] = alloca <4 x i64>, align 32
65; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8*
66; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
67; CHECK-NEXT:    [[TMP_VAL:%.*]] = load <4 x i64>, <4 x i64>* [[TMP]]
68; CHECK-NEXT:    call fastcc void @promote_avx2(<4 x i64>* [[TMP2]], <4 x i64> [[TMP_VAL]])
69; CHECK-NEXT:    [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32
70; CHECK-NEXT:    store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2
71; CHECK-NEXT:    ret void
72;
73bb:
74  %tmp = alloca <4 x i64>, align 32
75  %tmp2 = alloca <4 x i64>, align 32
76  %tmp3 = bitcast <4 x i64>* %tmp to i8*
77  call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
78  call fastcc void @promote_avx2(<4 x i64>* %tmp2, <4 x i64>* %tmp)
79  %tmp4 = load <4 x i64>, <4 x i64>* %tmp2, align 32
80  store <4 x i64> %tmp4, <4 x i64>* %arg, align 2
81  ret void
82}
83
84; Function Attrs: argmemonly nounwind
85declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #2
86
87attributes #0 = { inlinehint norecurse nounwind uwtable "target-features"="+avx2" }
88attributes #1 = { nounwind uwtable }
89attributes #2 = { argmemonly nounwind }
90