1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "libgccjit.h"
6 
7 #include "harness.h"
8 
9 typedef int v4si __attribute__ ((vector_size (16)));
10 typedef unsigned int v4ui __attribute__ ((vector_size (16)));
11 typedef float v4f __attribute__ ((vector_size (16)));
12 
13 static void
create_vec_fn(gcc_jit_context * ctxt,const char * fnname,gcc_jit_type * vec_type,gcc_jit_type * elem_type,enum gcc_jit_binary_op op)14 create_vec_fn (gcc_jit_context *ctxt, const char *fnname,
15 	       gcc_jit_type *vec_type,
16 	       gcc_jit_type *elem_type,
17 	       enum gcc_jit_binary_op op)
18 {
19   /* Create equivalent to:
20 
21        static void
22        FNNAME (V *dst, const V *lhs, E p, E q, E r, E s)
23        {
24 	 V pqrs;
25 	 pqrs = {p, q, r, s};
26 	 *dst = *lhs OP pqrs;
27        }
28 
29      where V is "vec_type" (e.g. v4si)
30      and   E is "elem_type" (e.g. int).  */
31 
32   gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (vec_type);
33 
34   gcc_jit_type *const_type = gcc_jit_type_get_const (vec_type);
35   gcc_jit_type *ptr_to_const_type = gcc_jit_type_get_pointer (const_type);
36 
37   gcc_jit_param *dst =
38     gcc_jit_context_new_param (ctxt, NULL, ptr_type, "dst");
39   gcc_jit_param *lhs =
40     gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "lhs");
41   gcc_jit_param *p =
42     gcc_jit_context_new_param (ctxt, NULL, elem_type, "p");
43   gcc_jit_param *q =
44     gcc_jit_context_new_param (ctxt, NULL, elem_type, "q");
45   gcc_jit_param *r =
46     gcc_jit_context_new_param (ctxt, NULL, elem_type, "r");
47   gcc_jit_param *s =
48     gcc_jit_context_new_param (ctxt, NULL, elem_type, "s");
49 
50   gcc_jit_type *return_type =
51     gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
52 
53   gcc_jit_param *params[6] = {dst, lhs, p, q, r, s};
54   gcc_jit_function *func =
55     gcc_jit_context_new_function (ctxt, NULL,
56 				  GCC_JIT_FUNCTION_EXPORTED,
57 				  return_type,
58 				  fnname,
59 				  6, params, 0);
60   gcc_jit_block *initial =
61     gcc_jit_function_new_block (func, "initial");
62 
63   /* V pqrs; */
64   gcc_jit_lvalue *pqrs
65     = gcc_jit_function_new_local (func, NULL,
66 				  vec_type, "pqrs");
67 
68   /* pqrs = {p, q, r, s}; */
69   gcc_jit_rvalue *elems[4];
70   elems[0] = gcc_jit_param_as_rvalue (p);
71   elems[1] = gcc_jit_param_as_rvalue (q);
72   elems[2] = gcc_jit_param_as_rvalue (r);
73   elems[3] = gcc_jit_param_as_rvalue (s);
74   gcc_jit_block_add_assignment (
75     initial, NULL,
76     pqrs,
77     gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, vec_type, 4, elems));
78 
79   /* (*lhs OP pqrs) */
80   gcc_jit_rvalue *op_result =
81     gcc_jit_context_new_binary_op (
82       ctxt, NULL,
83       op,
84       vec_type,
85       gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (lhs),
86 							    NULL)),
87       gcc_jit_lvalue_as_rvalue (pqrs));
88   /* *dst = *lhs OP pqrs; */
89   gcc_jit_block_add_assignment (
90     initial, NULL,
91     gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (dst), NULL),
92     op_result);
93   gcc_jit_block_end_with_void_return (initial, NULL);
94 }
95 
96 void
create_code(gcc_jit_context * ctxt,void * user_data)97 create_code (gcc_jit_context *ctxt, void *user_data)
98 {
99   gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
100   gcc_jit_type *unsigned_type
101     = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
102   gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
103 
104   gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);
105   gcc_jit_type *v4ui_type = gcc_jit_type_get_vector (unsigned_type, 4);
106   gcc_jit_type *v4f_type = gcc_jit_type_get_vector (float_type, 4);
107 
108   create_vec_fn (ctxt, "jit_v4si_add",
109 		 v4si_type, int_type, GCC_JIT_BINARY_OP_PLUS);
110   create_vec_fn (ctxt, "jit_v4si_sub",
111 		 v4si_type, int_type, GCC_JIT_BINARY_OP_MINUS);
112   create_vec_fn (ctxt, "jit_v4si_mult",
113 		 v4si_type, int_type, GCC_JIT_BINARY_OP_MULT);
114   create_vec_fn (ctxt, "jit_v4si_div",
115 		 v4si_type, int_type, GCC_JIT_BINARY_OP_DIVIDE);
116 
117   create_vec_fn (ctxt, "jit_v4ui_add",
118 		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_PLUS);
119   create_vec_fn (ctxt, "jit_v4ui_sub",
120 		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_MINUS);
121   create_vec_fn (ctxt, "jit_v4ui_mult",
122 		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_MULT);
123   create_vec_fn (ctxt, "jit_v4ui_div",
124 		 v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_DIVIDE);
125 
126   create_vec_fn (ctxt, "jit_v4f_add",
127 		 v4f_type, float_type, GCC_JIT_BINARY_OP_PLUS);
128   create_vec_fn (ctxt, "jit_v4f_sub",
129 		 v4f_type, float_type, GCC_JIT_BINARY_OP_MINUS);
130   create_vec_fn (ctxt, "jit_v4f_mult",
131 		 v4f_type, float_type, GCC_JIT_BINARY_OP_MULT);
132   create_vec_fn (ctxt, "jit_v4f_div",
133 		 v4f_type, float_type, GCC_JIT_BINARY_OP_DIVIDE);
134 }
135 
136 template <typename V>
137 void
check_add(const V & a,const V & b,const V & c)138 check_add (const V &a, const V &b, const V &c)
139 {
140   for (int i = 0; i < 4; i++)
141     CHECK_VALUE (c[i], a[i] + b[i]);
142 }
143 
144 template <typename V>
145 void
check_sub(const V & a,const V & b,const V & c)146 check_sub (const V &a, const V &b, const V &c)
147 {
148   for (int i = 0; i < 4; i++)
149     CHECK_VALUE (c[i], a[i] - b[i]);
150 }
151 
152 template <typename V>
153 void
check_mult(const V & a,const V & b,const V & c)154 check_mult (const V &a, const V &b, const V &c)
155 {
156   for (int i = 0; i < 4; i++)
157     CHECK_VALUE (c[i], a[i] * b[i]);
158 }
159 
160 template <typename V>
161 void
check_div(const V & a,const V & b,const V & c)162 check_div (const V &a, const V &b, const V &c)
163 {
164   for (int i = 0; i < 4; i++)
165     CHECK_VALUE (c[i], a[i] / b[i]);
166 }
167 
168 template <typename V, typename E>
169 void
verify_vec_code(gcc_jit_context * ctxt,gcc_jit_result * result,const char * fnname,void (* check_cb)(const V & a,const V & b,const V & c))170 verify_vec_code (gcc_jit_context *ctxt, gcc_jit_result *result,
171 		 const char *fnname,
172 		 void (*check_cb) (const V &a, const V &b, const V &c))
173 {
174   typedef void (*binop_type) (const V *a, V *b, E p, E q, E r, E s);
175   CHECK_NON_NULL (result);
176   binop_type fn =
177     (binop_type)gcc_jit_result_get_code (result, fnname);
178   CHECK_NON_NULL (fn);
179 
180   V dst, lhs, pqrs;
181 
182   /* Init.  */
183   for (int i = 0; i < 4; i++)
184     {
185       lhs[i] = i + 5;
186       pqrs[i] = (i + 4) * 3;
187     }
188 
189   /* Run jit-compiled code and verify result.  */
190   fn (&dst, &lhs, pqrs[0], pqrs[1], pqrs[2], pqrs[3]);
191   check_cb (lhs, pqrs, dst);
192 }
193 
194 void
verify_code(gcc_jit_context * ctxt,gcc_jit_result * result)195 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
196 {
197   verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_add", check_add);
198   verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_sub", check_sub);
199   verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_mult", check_mult);
200   verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_div", check_div);
201 
202   verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_add", check_add);
203   verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_sub", check_sub);
204   verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_mult", check_mult);
205   verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_div", check_div);
206 
207   verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_add", check_add);
208   verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_sub", check_sub);
209   verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_mult", check_mult);
210   verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_div", check_div);
211 }
212