1 /* { dg-do run } */
2 /* { dg-options "-O3 --save-temps" } */
3 
4 #include <arm_neon.h>
5 
6 extern void abort (void);
7 
8 #define MAPs(size, xx) int##size##xx##_t
9 #define MAPu(size, xx) uint##size##xx##_t
10 
11 
12 #define TEST_VMLS(q, su, size, in1_lanes, in2_lanes)		\
13 static void							\
14 test_vmlsq_lane##q##_##su##size (MAP##su (size, ) * res,	\
15 				 const MAP##su(size, ) *in1,	\
16 				 const MAP##su(size, ) *in2)	\
17 {								\
18   MAP##su (size, x##in1_lanes) a = vld1q_##su##size (res);	\
19   MAP##su (size, x##in1_lanes) b = vld1q_##su##size (in1);	\
20   MAP##su (size, x##in2_lanes) c = vld1##q##_##su##size (in2);	\
21   a = vmlsq_lane##q##_##su##size (a, b, c, 1);			\
22   vst1q_##su##size (res, a);					\
23 }
24 
25 #define BUILD_VARS(width, n_lanes, n_half_lanes)		\
26 TEST_VMLS (, s, width, n_lanes, n_half_lanes)			\
27 TEST_VMLS (q, s, width, n_lanes, n_lanes)			\
28 TEST_VMLS (, u, width, n_lanes, n_half_lanes)			\
29 TEST_VMLS (q, u, width, n_lanes, n_lanes)			\
30 
31 BUILD_VARS (32, 4, 2)
32 BUILD_VARS (16, 8, 4)
33 
34 #define MAP_OPs +
35 #define MAP_OPu -
36 
37 #define POOL4 {0, 1, 2, 3}
38 #define POOL8 {0, 1, 2, 3, 4, 5, 6, 7}
39 #define EMPTY4s {0, 0, 0, 0}
40 #define EMPTY8s {0, 0, 0, 0, 0, 0, 0, 0}
41 #define EMPTY4u {0, 2, 4, 6}
42 #define EMPTY8u {0, 2, 4, 6, 8, 10, 12, 14}
43 
44 #define BUILD_TEST(su, size, lanes)				\
45 static void							\
46 test_##su##size (void)						\
47 {								\
48   int i;							\
49   MAP##su (size,) pool[lanes] = POOL##lanes;			\
50   MAP##su (size,) res[lanes] = EMPTY##lanes##su;		\
51   MAP##su (size,) res2[lanes] = EMPTY##lanes##su;		\
52 								\
53   /* Forecfully avoid optimization.  */				\
54   asm volatile ("" : : : "memory");				\
55   test_vmlsq_lane_##su##size (res, pool, pool);			\
56   for (i = 0; i < lanes; i++)					\
57     if (res[i] MAP_OP##su pool[i] != 0)				\
58       abort ();							\
59 								\
60   /* Forecfully avoid optimization.  */				\
61   asm volatile ("" : : : "memory");				\
62   test_vmlsq_laneq_##su##size (res2, pool, pool);		\
63   for (i = 0; i < lanes; i++)					\
64     if (res2[i] MAP_OP##su pool[i] != 0)			\
65       abort ();							\
66 }
67 
68 #undef BUILD_VARS
69 #define BUILD_VARS(size, lanes)					\
70 BUILD_TEST (s, size, lanes)					\
71 BUILD_TEST (u, size, lanes)
72 
73 BUILD_VARS (32, 4)
74 BUILD_VARS (16, 8)
75 
76 int
main(int argc,char ** argv)77 main (int argc, char **argv)
78 {
79   test_s32 ();
80   test_u32 ();
81   test_s16 ();
82   test_u16 ();
83   return 0;
84 }
85 
86 /* { dg-final { scan-assembler-times "mls\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.4s\\\[\[0-9\]+\\\]" 4 } } */
87 /* { dg-final { scan-assembler-times "mls\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h, v\[0-9\]+\.8h\\\[\[0-9\]+\\\]" 4 } } */
88 
89