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
9int8_t test_vmaxv_s8(int8x8_t a1) {
10  // CHECK: test_vmaxv_s8
11  return vmaxv_s8(a1);
12  // CHECK @llvm.aarch64.neon.smaxv.i32.v8i8
13}
14
15uint16_t test_vminvq_u16(uint16x8_t a1) {
16  // CHECK: test_vminvq_u16
17  return vminvq_u16(a1);
18  // CHECK llvm.aarch64.neon.uminv.i16.v8i16
19}
20
21// Test a represntative sample of 8 and 16, signed and unsigned, 64 and 128 bit pairwise
22uint8x8_t test_vmin_u8(uint8x8_t a1, uint8x8_t a2) {
23  // CHECK: test_vmin_u8
24  return vmin_u8(a1, a2);
25  // CHECK llvm.aarch64.neon.umin.v8i8
26}
27
28uint8x16_t test_vminq_u8(uint8x16_t a1, uint8x16_t a2) {
29  // CHECK: test_vminq_u8
30  return vminq_u8(a1, a2);
31  // CHECK llvm.aarch64.neon.umin.v16i8
32}
33
34int16x8_t test_vmaxq_s16(int16x8_t a1, int16x8_t a2) {
35  // CHECK: test_vmaxq_s16
36  return vmaxq_s16(a1, a2);
37  // CHECK llvm.aarch64.neon.smax.v8i16
38}
39
40// Test the more complicated cases of [suf]32 and f64
41float64x2_t test_vmaxq_f64(float64x2_t a1, float64x2_t a2) {
42  // CHECK: test_vmaxq_f64
43  return vmaxq_f64(a1, a2);
44  // CHECK llvm.aarch64.neon.fmax.v2f64
45}
46
47float32x4_t test_vmaxq_f32(float32x4_t a1, float32x4_t a2) {
48  // CHECK: test_vmaxq_f32
49  return vmaxq_f32(a1, a2);
50  // CHECK llvm.aarch64.neon.fmax.v4f32
51}
52
53float64x2_t test_vminq_f64(float64x2_t a1, float64x2_t a2) {
54  // CHECK: test_vminq_f64
55  return vminq_f64(a1, a2);
56  // CHECK llvm.aarch64.neon.fmin.v2f64
57}
58
59float32x2_t test_vmax_f32(float32x2_t a1, float32x2_t a2) {
60  // CHECK: test_vmax_f32
61  return vmax_f32(a1, a2);
62  // CHECK llvm.aarch64.neon.fmax.v2f32
63}
64
65int32x2_t test_vmax_s32(int32x2_t a1, int32x2_t a2) {
66  // CHECK: test_vmax_s32
67  return vmax_s32(a1, a2);
68  // CHECK llvm.aarch64.neon.smax.v2i32
69}
70
71uint32x2_t test_vmin_u32(uint32x2_t a1, uint32x2_t a2) {
72  // CHECK: test_vmin_u32
73  return vmin_u32(a1, a2);
74  // CHECK llvm.aarch64.neon.umin.v2i32
75}
76
77float32_t test_vmaxnmv_f32(float32x2_t a1) {
78  // CHECK: 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
87float64_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
95float32_t test_vmaxnmvq_f32(float32x4_t a1) {
96  // CHECK: test_vmaxnmvq_f32
97  return vmaxnmvq_f32(a1);
98  // CHECK: llvm.aarch64.neon.fmaxnmv.f32.v4f32
99  // CHECK-NEXT: ret
100}
101
102float32_t test_vmaxv_f32(float32x2_t a1) {
103  // CHECK: test_vmaxv_f32
104  return vmaxv_f32(a1);
105  // CHECK: 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
111int32_t test_vmaxv_s32(int32x2_t a1) {
112  // CHECK: test_vmaxv_s32
113  return vmaxv_s32(a1);
114  // CHECK: 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
120uint32_t test_vmaxv_u32(uint32x2_t a1) {
121  // CHECK: test_vmaxv_u32
122  return vmaxv_u32(a1);
123  // CHECK: 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
131float64_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
139float32_t test_vmaxvq_f32(float32x4_t a1) {
140  // CHECK: test_vmaxvq_f32
141  return vmaxvq_f32(a1);
142  // CHECK: llvm.aarch64.neon.fmaxv.f32.v4f32
143  // CHECK-NEXT: ret
144}
145
146float32_t test_vminnmv_f32(float32x2_t a1) {
147  // CHECK: test_vminnmv_f32
148  return vminnmv_f32(a1);
149  // CHECK: llvm.aarch64.neon.fminnmv.f32.v2f32
150  // CHECK-NEXT: ret
151}
152
153float32_t test_vminvq_f32(float32x4_t a1) {
154  // CHECK: test_vminvq_f32
155  return vminvq_f32(a1);
156  // CHECK: 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
163float64_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
171float32_t test_vminnmvq_f32(float32x4_t a1) {
172  // CHECK: test_vminnmvq_f32
173  return vminnmvq_f32(a1);
174  // CHECK: llvm.aarch64.neon.fminnmv.f32.v4f32
175  // CHECK-NEXT: ret
176}
177
178float32_t test_vminv_f32(float32x2_t a1) {
179  // CHECK: test_vminv_f32
180  return vminv_f32(a1);
181  // CHECK: llvm.aarch64.neon.fminv.f32.v2f32
182  // CHECK-NEXT: ret
183}
184
185int32_t test_vminv_s32(int32x2_t a1) {
186  // CHECK: test_vminv_s32
187  return vminv_s32(a1);
188  // CHECK: llvm.aarch64.neon.sminv.i32.v2i32
189  // CHECK-CODEGEN: sminp.2s
190  // CHECK-NEXT: ret
191}
192
193uint32_t test_vminv_u32(uint32x2_t a1) {
194  // CHECK: test_vminv_u32
195  return vminv_u32(a1);
196  // CHECK: llvm.aarch64.neon.fminv.f32.v2f32
197}
198
199// FIXME punt on this for now; don't forget to fix CHECKs
200#if 0
201float64_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