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