1 // RUN: %clang_cc1 -O1 -triple arm64-apple-ios7 -target-feature +neon -ffreestanding -S -o - -emit-llvm %s | FileCheck %s
2 // RUN: %clang_cc1 -O1 -triple arm64-apple-ios7 -target-feature +neon -ffreestanding -S -o - %s | FileCheck -check-prefix=CHECK-CODEGEN %s
3 // REQUIRES: aarch64-registered-target
4 // Test ARM64 SIMD max/min intrinsics
5
6 #include <arm_neon.h>
7
8 // Test a represntative sample of 8 and 16, signed and unsigned, 64 and 128 bit reduction
test_vmaxv_s8(int8x8_t a1)9 int8_t test_vmaxv_s8(int8x8_t a1) {
10 // CHECK-LABEL: define i8 @test_vmaxv_s8(
11 return vmaxv_s8(a1);
12 // CHECK: call i32 @llvm.aarch64.neon.smaxv.i32.v8i8(
13 }
14
test_vminvq_u16(uint16x8_t a1)15 uint16_t test_vminvq_u16(uint16x8_t a1) {
16 // CHECK-LABEL: define i16 @test_vminvq_u16(
17 return vminvq_u16(a1);
18 // CHECK: call i32 @llvm.aarch64.neon.uminv.i32.v8i16(
19 }
20
21 // Test a represntative sample of 8 and 16, signed and unsigned, 64 and 128 bit pairwise
test_vmin_u8(uint8x8_t a1,uint8x8_t a2)22 uint8x8_t test_vmin_u8(uint8x8_t a1, uint8x8_t a2) {
23 // CHECK-LABEL: define <8 x i8> @test_vmin_u8(
24 return vmin_u8(a1, a2);
25 // CHECK: call <8 x i8> @llvm.aarch64.neon.umin.v8i8(
26 }
27
test_vminq_u8(uint8x16_t a1,uint8x16_t a2)28 uint8x16_t test_vminq_u8(uint8x16_t a1, uint8x16_t a2) {
29 // CHECK-LABEL: define <16 x i8> @test_vminq_u8(
30 return vminq_u8(a1, a2);
31 // CHECK: call <16 x i8> @llvm.aarch64.neon.umin.v16i8(
32 }
33
test_vmaxq_s16(int16x8_t a1,int16x8_t a2)34 int16x8_t test_vmaxq_s16(int16x8_t a1, int16x8_t a2) {
35 // CHECK-LABEL: define <8 x i16> @test_vmaxq_s16(
36 return vmaxq_s16(a1, a2);
37 // CHECK: call <8 x i16> @llvm.aarch64.neon.smax.v8i16(
38 }
39
40 // Test the more complicated cases of [suf]32 and f64
test_vmaxq_f64(float64x2_t a1,float64x2_t a2)41 float64x2_t test_vmaxq_f64(float64x2_t a1, float64x2_t a2) {
42 // CHECK-LABEL: define <2 x double> @test_vmaxq_f64(
43 return vmaxq_f64(a1, a2);
44 // CHECK: call <2 x double> @llvm.aarch64.neon.fmax.v2f64(
45 }
46
test_vmaxq_f32(float32x4_t a1,float32x4_t a2)47 float32x4_t test_vmaxq_f32(float32x4_t a1, float32x4_t a2) {
48 // CHECK-LABEL: define <4 x float> @test_vmaxq_f32(
49 return vmaxq_f32(a1, a2);
50 // CHECK: call <4 x float> @llvm.aarch64.neon.fmax.v4f32(
51 }
52
test_vminq_f64(float64x2_t a1,float64x2_t a2)53 float64x2_t test_vminq_f64(float64x2_t a1, float64x2_t a2) {
54 // CHECK-LABEL: define <2 x double> @test_vminq_f64(
55 return vminq_f64(a1, a2);
56 // CHECK: call <2 x double> @llvm.aarch64.neon.fmin.v2f64(
57 }
58
test_vmax_f32(float32x2_t a1,float32x2_t a2)59 float32x2_t test_vmax_f32(float32x2_t a1, float32x2_t a2) {
60 // CHECK-LABEL: define <2 x float> @test_vmax_f32(
61 return vmax_f32(a1, a2);
62 // CHECK: call <2 x float> @llvm.aarch64.neon.fmax.v2f32(
63 }
64
test_vmax_s32(int32x2_t a1,int32x2_t a2)65 int32x2_t test_vmax_s32(int32x2_t a1, int32x2_t a2) {
66 // CHECK-LABEL: define <2 x i32> @test_vmax_s32(
67 return vmax_s32(a1, a2);
68 // CHECK: call <2 x i32> @llvm.aarch64.neon.smax.v2i32(
69 }
70
test_vmin_u32(uint32x2_t a1,uint32x2_t a2)71 uint32x2_t test_vmin_u32(uint32x2_t a1, uint32x2_t a2) {
72 // CHECK-LABEL: define <2 x i32> @test_vmin_u32(
73 return vmin_u32(a1, a2);
74 // CHECK: call <2 x i32> @llvm.aarch64.neon.umin.v2i32(
75 }
76
test_vmaxnmv_f32(float32x2_t a1)77 float32_t test_vmaxnmv_f32(float32x2_t a1) {
78 // CHECK-LABEL: define float @test_vmaxnmv_f32(
79 return vmaxnmv_f32(a1);
80 // CHECK: llvm.aarch64.neon.fmaxnmv.f32.v2f32
81 // CHECK-NEXT: ret
82 }
83
84 // this doesn't translate into a valid instruction, regardless of what the
85 // ARM doc says.
86 #if 0
87 float64_t test_vmaxnmvq_f64(float64x2_t a1) {
88 // CHECK@ test_vmaxnmvq_f64
89 return vmaxnmvq_f64(a1);
90 // CHECK@ llvm.aarch64.neon.saddlv.i64.v2i32
91 // CHECK-NEXT@ ret
92 }
93 #endif
94
test_vmaxnmvq_f32(float32x4_t a1)95 float32_t test_vmaxnmvq_f32(float32x4_t a1) {
96 // CHECK-LABEL: define float @test_vmaxnmvq_f32(
97 return vmaxnmvq_f32(a1);
98 // CHECK: call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(
99 // CHECK-NEXT: ret
100 }
101
test_vmaxv_f32(float32x2_t a1)102 float32_t test_vmaxv_f32(float32x2_t a1) {
103 // CHECK-LABEL: define float @test_vmaxv_f32(
104 return vmaxv_f32(a1);
105 // CHECK: call float @llvm.aarch64.neon.fmaxv.f32.v2f32(
106 // FIXME check that the 2nd and 3rd arguments are the same V register below
107 // CHECK-CODEGEN: fmaxp.2s
108 // CHECK-NEXT: ret
109 }
110
test_vmaxv_s32(int32x2_t a1)111 int32_t test_vmaxv_s32(int32x2_t a1) {
112 // CHECK-LABEL: define i32 @test_vmaxv_s32(
113 return vmaxv_s32(a1);
114 // CHECK: call i32 @llvm.aarch64.neon.smaxv.i32.v2i32(
115 // FIXME check that the 2nd and 3rd arguments are the same V register below
116 // CHECK-CODEGEN: smaxp.2s
117 // CHECK-NEXT: ret
118 }
119
test_vmaxv_u32(uint32x2_t a1)120 uint32_t test_vmaxv_u32(uint32x2_t a1) {
121 // CHECK-LABEL: define i32 @test_vmaxv_u32(
122 return vmaxv_u32(a1);
123 // CHECK: call i32 @llvm.aarch64.neon.umaxv.i32.v2i32(
124 // FIXME check that the 2nd and 3rd arguments are the same V register below
125 // CHECK-CODEGEN: umaxp.2s
126 // CHECK-NEXT: ret
127 }
128
129 // FIXME punt on this for now; don't forget to fix CHECKs
130 #if 0
131 float64_t test_vmaxvq_f64(float64x2_t a1) {
132 // CHECK@ test_vmaxvq_f64
133 return vmaxvq_f64(a1);
134 // CHECK@ llvm.aarch64.neon.fmaxv.i64.v2f64
135 // CHECK-NEXT@ ret
136 }
137 #endif
138
test_vmaxvq_f32(float32x4_t a1)139 float32_t test_vmaxvq_f32(float32x4_t a1) {
140 // CHECK-LABEL: define float @test_vmaxvq_f32(
141 return vmaxvq_f32(a1);
142 // CHECK: call float @llvm.aarch64.neon.fmaxv.f32.v4f32(
143 // CHECK-NEXT: ret
144 }
145
test_vminnmv_f32(float32x2_t a1)146 float32_t test_vminnmv_f32(float32x2_t a1) {
147 // CHECK-LABEL: define float @test_vminnmv_f32(
148 return vminnmv_f32(a1);
149 // CHECK: call float @llvm.aarch64.neon.fminnmv.f32.v2f32(
150 // CHECK-NEXT: ret
151 }
152
test_vminvq_f32(float32x4_t a1)153 float32_t test_vminvq_f32(float32x4_t a1) {
154 // CHECK-LABEL: define float @test_vminvq_f32(
155 return vminvq_f32(a1);
156 // CHECK: call float @llvm.aarch64.neon.fminv.f32.v4f32(
157 // CHECK-NEXT: ret
158 }
159
160 // this doesn't translate into a valid instruction, regardless of what the ARM
161 // doc says.
162 #if 0
163 float64_t test_vminnmvq_f64(float64x2_t a1) {
164 // CHECK@ test_vminnmvq_f64
165 return vminnmvq_f64(a1);
166 // CHECK@ llvm.aarch64.neon.saddlv.i64.v2i32
167 // CHECK-NEXT@ ret
168 }
169 #endif
170
test_vminnmvq_f32(float32x4_t a1)171 float32_t test_vminnmvq_f32(float32x4_t a1) {
172 // CHECK-LABEL: define float @test_vminnmvq_f32(
173 return vminnmvq_f32(a1);
174 // CHECK: call float @llvm.aarch64.neon.fminnmv.f32.v4f32(
175 // CHECK-NEXT: ret
176 }
177
test_vminv_f32(float32x2_t a1)178 float32_t test_vminv_f32(float32x2_t a1) {
179 // CHECK-LABEL: define float @test_vminv_f32(
180 return vminv_f32(a1);
181 // CHECK: call float @llvm.aarch64.neon.fminv.f32.v2f32(
182 // CHECK-NEXT: ret
183 }
184
test_vminv_s32(int32x2_t a1)185 int32_t test_vminv_s32(int32x2_t a1) {
186 // CHECK-LABEL: define i32 @test_vminv_s32(
187 return vminv_s32(a1);
188 // CHECK: call i32 @llvm.aarch64.neon.sminv.i32.v2i32(
189 // CHECK-CODEGEN: sminp.2s
190 // CHECK-NEXT: ret
191 }
192
test_vminv_u32(uint32x2_t a1)193 uint32_t test_vminv_u32(uint32x2_t a1) {
194 // CHECK-LABEL: define i32 @test_vminv_u32(
195 return vminv_u32(a1);
196 // CHECK: call i32 @llvm.aarch64.neon.uminv.i32.v2i32(
197 }
198
199 // FIXME punt on this for now; don't forget to fix CHECKs
200 #if 0
201 float64_t test_vminvq_f64(float64x2_t a1) {
202 // CHECK@ test_vminvq_f64
203 return vminvq_f64(a1);
204 // CHECK@ llvm.aarch64.neon.saddlv.i64.v2i32
205 // CHECK-NEXT@ ret
206 }
207 #endif
208