xref: /llvm-project/llvm/test/Transforms/SLPVectorizer/X86/call.ll (revision 918313d17d38d8723d5d81fef008538677abf9cc)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=slp-vectorizer,dce -slp-threshold=-999 -S -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx | FileCheck %s
3
4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
5target triple = "x86_64-apple-macosx10.8.0"
6
7declare double @sin(double) nounwind willreturn
8declare double @cos(double) nounwind willreturn
9declare double @tan(double) nounwind willreturn
10declare double @pow(double, double) nounwind willreturn
11declare double @exp2(double) nounwind willreturn
12declare double @sqrt(double) nounwind willreturn
13declare i64 @round(i64) nounwind willreturn
14
15
16define void @sin_libm(ptr %a, ptr %b) {
17; CHECK-LABEL: @sin_libm(
18; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
19; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.sin.v2f64(<2 x double> [[TMP2]])
20; CHECK-NEXT:    store <2 x double> [[TMP3]], ptr [[B:%.*]], align 8
21; CHECK-NEXT:    ret void
22;
23  %a0 = load double, ptr %a, align 8
24  %idx1 = getelementptr inbounds double, ptr %a, i64 1
25  %a1 = load double, ptr %idx1, align 8
26  %sin1 = tail call double @sin(double %a0) nounwind readnone
27  %sin2 = tail call double @sin(double %a1) nounwind readnone
28  store double %sin1, ptr %b, align 8
29  %idx2 = getelementptr inbounds double, ptr %b, i64 1
30  store double %sin2, ptr %idx2, align 8
31  ret void
32}
33
34define void @cos_libm(ptr %a, ptr %b) {
35; CHECK-LABEL: @cos_libm(
36; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
37; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.cos.v2f64(<2 x double> [[TMP2]])
38; CHECK-NEXT:    store <2 x double> [[TMP3]], ptr [[B:%.*]], align 8
39; CHECK-NEXT:    ret void
40;
41  %a0 = load double, ptr %a, align 8
42  %idx1 = getelementptr inbounds double, ptr %a, i64 1
43  %a1 = load double, ptr %idx1, align 8
44  %cos1 = tail call double @cos(double %a0) nounwind readnone
45  %cos2 = tail call double @cos(double %a1) nounwind readnone
46  store double %cos1, ptr %b, align 8
47  %idx2 = getelementptr inbounds double, ptr %b, i64 1
48  store double %cos2, ptr %idx2, align 8
49  ret void
50}
51
52define void @tan_libm(ptr %a, ptr %b) {
53; CHECK-LABEL: @tan_libm(
54; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
55; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.tan.v2f64(<2 x double> [[TMP2]])
56; CHECK-NEXT:    store <2 x double> [[TMP3]], ptr [[B:%.*]], align 8
57; CHECK-NEXT:    ret void
58;
59  %a0 = load double, ptr %a, align 8
60  %idx1 = getelementptr inbounds double, ptr %a, i64 1
61  %a1 = load double, ptr %idx1, align 8
62  %tan1 = tail call double @tan(double %a0) nounwind readnone
63  %tan2 = tail call double @tan(double %a1) nounwind readnone
64  store double %tan1, ptr %b, align 8
65  %idx2 = getelementptr inbounds double, ptr %b, i64 1
66  store double %tan2, ptr %idx2, align 8
67  ret void
68}
69
70define void @pow_libm(ptr %a, ptr %b) {
71; CHECK-LABEL: @pow_libm(
72; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
73; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[TMP2]], <2 x double> [[TMP2]])
74; CHECK-NEXT:    store <2 x double> [[TMP3]], ptr [[B:%.*]], align 8
75; CHECK-NEXT:    ret void
76;
77  %a0 = load double, ptr %a, align 8
78  %idx1 = getelementptr inbounds double, ptr %a, i64 1
79  %a1 = load double, ptr %idx1, align 8
80  %pow1 = tail call double @pow(double %a0, double %a0) nounwind readnone
81  %pow2 = tail call double @pow(double %a1, double %a1) nounwind readnone
82  store double %pow1, ptr %b, align 8
83  %idx2 = getelementptr inbounds double, ptr %b, i64 1
84  store double %pow2, ptr %idx2, align 8
85  ret void
86}
87
88define void @exp_libm(ptr %a, ptr %b) {
89; CHECK-LABEL: @exp_libm(
90; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
91; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[TMP2]])
92; CHECK-NEXT:    store <2 x double> [[TMP3]], ptr [[B:%.*]], align 8
93; CHECK-NEXT:    ret void
94;
95  %a0 = load double, ptr %a, align 8
96  %idx1 = getelementptr inbounds double, ptr %a, i64 1
97  %a1 = load double, ptr %idx1, align 8
98  %exp1 = tail call double @exp2(double %a0) nounwind readnone
99  %exp2 = tail call double @exp2(double %a1) nounwind readnone
100  store double %exp1, ptr %b, align 8
101  %idx2 = getelementptr inbounds double, ptr %b, i64 1
102  store double %exp2, ptr %idx2, align 8
103  ret void
104}
105
106; No fast-math-flags are required to convert sqrt library calls to an intrinsic.
107; We just need to know that errno is not set (readnone).
108
109define void @sqrt_libm_no_errno(ptr %a, ptr %b) {
110; CHECK-LABEL: @sqrt_libm_no_errno(
111; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
112; CHECK-NEXT:    [[TMP3:%.*]] = call <2 x double> @llvm.sqrt.v2f64(<2 x double> [[TMP2]])
113; CHECK-NEXT:    store <2 x double> [[TMP3]], ptr [[B:%.*]], align 8
114; CHECK-NEXT:    ret void
115;
116  %a0 = load double, ptr %a, align 8
117  %idx1 = getelementptr inbounds double, ptr %a, i64 1
118  %a1 = load double, ptr %idx1, align 8
119  %sqrt1 = tail call double @sqrt(double %a0) nounwind readnone
120  %sqrt2 = tail call double @sqrt(double %a1) nounwind readnone
121  store double %sqrt1, ptr %b, align 8
122  %idx2 = getelementptr inbounds double, ptr %b, i64 1
123  store double %sqrt2, ptr %idx2, align 8
124  ret void
125}
126
127; The sqrt intrinsic does not set errno, but a non-constant sqrt call might, so this can't vectorize.
128; The nnan on the call does not matter because there's no guarantee in the C standard that a negative
129; input would result in a nan output ("On a domain error, the function returns an
130; implementation-defined value.")
131
132define void @sqrt_libm_errno(ptr %a, ptr %b) {
133; CHECK-LABEL: @sqrt_libm_errno(
134; CHECK-NEXT:    [[A0:%.*]] = load double, ptr [[A:%.*]], align 8
135; CHECK-NEXT:    [[IDX1:%.*]] = getelementptr inbounds double, ptr [[A]], i64 1
136; CHECK-NEXT:    [[A1:%.*]] = load double, ptr [[IDX1]], align 8
137; CHECK-NEXT:    [[SQRT1:%.*]] = tail call nnan double @sqrt(double [[A0]]) #[[ATTR3:[0-9]+]]
138; CHECK-NEXT:    [[SQRT2:%.*]] = tail call nnan double @sqrt(double [[A1]]) #[[ATTR3]]
139; CHECK-NEXT:    store double [[SQRT1]], ptr [[B:%.*]], align 8
140; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds double, ptr [[B]], i64 1
141; CHECK-NEXT:    store double [[SQRT2]], ptr [[IDX2]], align 8
142; CHECK-NEXT:    ret void
143;
144  %a0 = load double, ptr %a, align 8
145  %idx1 = getelementptr inbounds double, ptr %a, i64 1
146  %a1 = load double, ptr %idx1, align 8
147  %sqrt1 = tail call nnan double @sqrt(double %a0) nounwind
148  %sqrt2 = tail call nnan double @sqrt(double %a1) nounwind
149  store double %sqrt1, ptr %b, align 8
150  %idx2 = getelementptr inbounds double, ptr %b, i64 1
151  store double %sqrt2, ptr %idx2, align 8
152  ret void
153}
154
155; Negative test case
156define void @round_custom(ptr %a, ptr %b) {
157; CHECK-LABEL: @round_custom(
158; CHECK-NEXT:    [[A0:%.*]] = load i64, ptr [[A:%.*]], align 8
159; CHECK-NEXT:    [[IDX1:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 1
160; CHECK-NEXT:    [[A1:%.*]] = load i64, ptr [[IDX1]], align 8
161; CHECK-NEXT:    [[ROUND1:%.*]] = tail call i64 @round(i64 [[A0]]) #[[ATTR4:[0-9]+]]
162; CHECK-NEXT:    [[ROUND2:%.*]] = tail call i64 @round(i64 [[A1]]) #[[ATTR4]]
163; CHECK-NEXT:    store i64 [[ROUND1]], ptr [[B:%.*]], align 8
164; CHECK-NEXT:    [[IDX2:%.*]] = getelementptr inbounds i64, ptr [[B]], i64 1
165; CHECK-NEXT:    store i64 [[ROUND2]], ptr [[IDX2]], align 8
166; CHECK-NEXT:    ret void
167;
168  %a0 = load i64, ptr %a, align 8
169  %idx1 = getelementptr inbounds i64, ptr %a, i64 1
170  %a1 = load i64, ptr %idx1, align 8
171  %round1 = tail call i64 @round(i64 %a0) nounwind readnone
172  %round2 = tail call i64 @round(i64 %a1) nounwind readnone
173  store i64 %round1, ptr %b, align 8
174  %idx2 = getelementptr inbounds i64, ptr %b, i64 1
175  store i64 %round2, ptr %idx2, align 8
176  ret void
177}
178
179
180
181
182