2018-02-09 Sebastian Perta <sebastian.perta@renesas.com>
[official-gcc.git] / gcc / testsuite / jit.dg / test-functions.c
blob45c24d63c4daa85e52d43f07ab4482bb8e73c11c
1 #include <math.h>
2 #include <stdlib.h>
3 #include <stdio.h>
5 #include "libgccjit.h"
7 #include "harness.h"
9 /**********************************************************************
10 GCC_JIT_FUNCTION_ALWAYS_INLINE and GCC_JIT_FUNCTION_INTERNAL
11 **********************************************************************/
12 static void
13 create_test_of_hidden_function (gcc_jit_context *ctxt,
14 enum gcc_jit_function_kind hidden_kind,
15 const char *hidden_func_name,
16 const char *visible_func_name)
18 /* Let's try to inject the equivalent of:
19 static double hidden_mult (double a, double b)
21 return x * x;
23 double my_square (double x)
25 return my_mult (x, x);
28 where hidden_mult can potentially be
29 inline __attribute__((always_inline)). */
30 gcc_jit_type *double_type =
31 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
33 /* Create "my_mult" */
34 gcc_jit_param *param_a =
35 gcc_jit_context_new_param (ctxt, NULL, double_type, "a");
36 gcc_jit_param *param_b =
37 gcc_jit_context_new_param (ctxt, NULL, double_type, "b");
38 gcc_jit_param *params[2] = {param_a, param_b};
39 gcc_jit_function *my_mult =
40 gcc_jit_context_new_function (ctxt, NULL,
41 hidden_kind,
42 double_type,
43 hidden_func_name,
44 2, params,
45 0);
46 gcc_jit_block *body_of_my_mult =
47 gcc_jit_function_new_block (my_mult, NULL);
48 gcc_jit_block_end_with_return (
49 body_of_my_mult, NULL,
50 gcc_jit_context_new_binary_op (
51 ctxt, NULL,
52 GCC_JIT_BINARY_OP_MULT,
53 double_type,
54 gcc_jit_param_as_rvalue (param_a),
55 gcc_jit_param_as_rvalue (param_b)));
57 /* Create "my_square" */
58 gcc_jit_param *param_x =
59 gcc_jit_context_new_param (ctxt, NULL, double_type, "x");
60 gcc_jit_function *my_square =
61 gcc_jit_context_new_function (ctxt, NULL,
62 GCC_JIT_FUNCTION_EXPORTED,
63 double_type,
64 visible_func_name,
65 1, &param_x,
66 0);
67 gcc_jit_block *body_of_my_square =
68 gcc_jit_function_new_block (my_square, NULL);
69 gcc_jit_rvalue *args[2] = {gcc_jit_param_as_rvalue (param_x),
70 gcc_jit_param_as_rvalue (param_x)};
71 gcc_jit_block_end_with_return (
72 body_of_my_square, NULL,
73 gcc_jit_context_new_call (
74 ctxt, NULL,
75 my_mult,
76 2, args));
79 static void
80 create_tests_of_hidden_functions (gcc_jit_context *ctxt)
82 create_test_of_hidden_function (ctxt,
83 GCC_JIT_FUNCTION_INTERNAL,
84 "my_internal_mult",
85 "my_square_with_internal");
86 create_test_of_hidden_function (ctxt,
87 GCC_JIT_FUNCTION_ALWAYS_INLINE,
88 "my_always_inline_mult",
89 "my_square_with_always_inline");
92 static void
93 verify_hidden_functions (gcc_jit_context *ctxt, gcc_jit_result *result)
95 CHECK_NON_NULL (result);
97 /* GCC_JIT_FUNCTION_INTERNAL and GCC_JIT_FUNCTION_ALWAYS_INLINE
98 functions should not be accessible in the result. */
99 CHECK_VALUE (NULL, gcc_jit_result_get_code (result, "my_internal_mult"));
100 CHECK_VALUE (NULL, gcc_jit_result_get_code (result, "my_always_inline_mult"));
102 typedef double (*fn_type) (double);
103 fn_type my_square_with_internal =
104 (fn_type)gcc_jit_result_get_code (result, "my_square_with_internal");
105 CHECK_NON_NULL (my_square_with_internal);
106 CHECK_VALUE (my_square_with_internal (5.0), 25.0);
108 fn_type my_square_with_always_inline =
109 (fn_type)gcc_jit_result_get_code (result, "my_square_with_always_inline");
110 CHECK_NON_NULL (my_square_with_always_inline);
111 CHECK_VALUE (my_square_with_always_inline (5.0), 25.0);
114 /**********************************************************************
115 Builtin functions
116 **********************************************************************/
118 static void
119 create_test_of_builtin_strcmp (gcc_jit_context *ctxt)
121 /* Let's try to inject the equivalent of:
123 test_of_builtin_strcmp (const char *a, const char *b)
125 return __builtin_strcmp (a, b);
128 gcc_jit_type *int_type =
129 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
130 gcc_jit_type *const_char_ptr_type =
131 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
133 /* Get the built-in function. */
134 gcc_jit_function *builtin_fn =
135 gcc_jit_context_get_builtin_function (ctxt, "strcmp");
137 CHECK_STRING_VALUE (
138 gcc_jit_object_get_debug_string (gcc_jit_function_as_object (builtin_fn)),
139 "strcmp");
141 /* Build the test_fn. */
142 gcc_jit_param *param_a =
143 gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "a");
144 gcc_jit_param *param_b =
145 gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "b");
146 gcc_jit_param *params[2] = {param_a, param_b};
147 gcc_jit_function *test_fn =
148 gcc_jit_context_new_function (ctxt, NULL,
149 GCC_JIT_FUNCTION_EXPORTED,
150 int_type,
151 "test_of_builtin_strcmp",
152 2, params,
154 gcc_jit_rvalue *args[2] = {gcc_jit_param_as_rvalue (param_a),
155 gcc_jit_param_as_rvalue (param_b)};
156 gcc_jit_rvalue *call =
157 gcc_jit_context_new_call (ctxt,
158 NULL,
159 builtin_fn,
160 2, args);
161 CHECK_STRING_VALUE (
162 gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (call)),
163 "strcmp (a, b)");
165 gcc_jit_block *initial =
166 gcc_jit_function_new_block (test_fn, "initial");
167 gcc_jit_block_end_with_return (initial, NULL, call);
170 static char *trig_sincos_dump;
171 static char *trig_statistics_dump;
173 static void
174 create_test_of_builtin_trig (gcc_jit_context *ctxt)
176 /* Let's try to inject the equivalent of:
178 test_of_builtin_trig (double theta)
180 return 2 * sin (theta) * cos (theta);
182 (in theory, optimizable to sin (2 * theta))
185 gcc_jit_context_enable_dump (ctxt,
186 "tree-sincos",
187 &trig_sincos_dump);
188 gcc_jit_context_enable_dump (ctxt,
189 "statistics",
190 &trig_statistics_dump);
192 gcc_jit_type *double_t =
193 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
195 /* Get the built-in functions. */
196 gcc_jit_function *builtin_sin =
197 gcc_jit_context_get_builtin_function (ctxt, "sin");
198 gcc_jit_function *builtin_cos =
199 gcc_jit_context_get_builtin_function (ctxt, "cos");
201 /* Build the test_fn. */
202 gcc_jit_param *param_theta =
203 gcc_jit_context_new_param (ctxt, NULL, double_t, "theta");
204 gcc_jit_function *test_fn =
205 gcc_jit_context_new_function (ctxt, NULL,
206 GCC_JIT_FUNCTION_EXPORTED,
207 double_t,
208 "test_of_builtin_trig",
209 1, &param_theta,
211 gcc_jit_rvalue *args[1] = {gcc_jit_param_as_rvalue (param_theta)};
212 gcc_jit_rvalue *two =
213 gcc_jit_context_new_rvalue_from_int (ctxt, double_t, 2);
214 gcc_jit_rvalue *ret =
215 gcc_jit_context_new_binary_op (
216 ctxt, NULL,
217 GCC_JIT_BINARY_OP_MULT,
218 double_t,
219 two,
220 gcc_jit_context_new_binary_op (
221 ctxt, NULL,
222 GCC_JIT_BINARY_OP_MULT,
223 double_t,
224 gcc_jit_context_new_call (ctxt, NULL,
225 builtin_sin,
226 1, args),
227 gcc_jit_context_new_call (ctxt, NULL,
228 builtin_cos,
229 1, args)));
230 CHECK_STRING_VALUE (
231 gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (ret)),
232 "(double)2 * sin (theta) * cos (theta)");
234 gcc_jit_block *initial =
235 gcc_jit_function_new_block (test_fn, "initial");
236 gcc_jit_block_end_with_return (initial, NULL, ret);
239 static void
240 create_use_of_builtins (gcc_jit_context *ctxt)
242 create_test_of_builtin_strcmp (ctxt);
243 create_test_of_builtin_trig (ctxt);
246 static void
247 verify_test_of_builtin_strcmp (gcc_jit_context *ctxt, gcc_jit_result *result)
249 typedef int (*fn_type) (const char *, const char *);
250 CHECK_NON_NULL (result);
252 fn_type test_of_builtin_strcmp =
253 (fn_type)gcc_jit_result_get_code (result, "test_of_builtin_strcmp");
254 CHECK_NON_NULL (test_of_builtin_strcmp);
256 /* Verify that it correctly called strcmp. */
257 CHECK_VALUE (test_of_builtin_strcmp ("foo", "foo"), 0);
258 CHECK (test_of_builtin_strcmp ("foo", "bar") > 0);
259 CHECK (test_of_builtin_strcmp ("bar", "foo") < 0);
262 static void
263 verify_test_of_builtin_trig (gcc_jit_context *ctxt, gcc_jit_result *result)
265 typedef double (*fn_type) (double);
266 CHECK_NON_NULL (result);
268 fn_type test_of_builtin_trig =
269 (fn_type)gcc_jit_result_get_code (result, "test_of_builtin_trig");
270 CHECK_NON_NULL (test_of_builtin_trig);
272 /* Verify that it correctly computes
273 sin (2 * theta)
274 (perhaps calling sin and cos). */
275 CHECK_DOUBLE_VALUE (test_of_builtin_trig (0.0 ), 0.0);
276 CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_4 ), 1.0);
277 CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_2 ), 0.0);
278 CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_4 * 3.0), -1.0);
279 CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI ), 0.0);
281 /* PR jit/64020:
282 The "sincos" pass merges sin/cos calls into the cexpi builtin.
283 Verify that a dump of the "sincos" pass was provided, and that it
284 shows a call to the cexpi builtin on a SSA name of "theta". */
285 CHECK_NON_NULL (trig_sincos_dump);
286 CHECK_STRING_CONTAINS (trig_sincos_dump, " = __builtin_cexpi (theta_");
287 free (trig_sincos_dump);
289 /* Similarly, verify that the statistics dump was provided, and that
290 it shows the sincos optimization. */
291 CHECK_NON_NULL (trig_statistics_dump);
292 CHECK_STRING_CONTAINS (
293 trig_statistics_dump,
294 "sincos \"sincos statements inserted\" \"test_of_builtin_trig\" 1");
295 free (trig_statistics_dump);
298 static void
299 verify_use_of_builtins (gcc_jit_context *ctxt, gcc_jit_result *result)
301 verify_test_of_builtin_strcmp (ctxt, result);
302 verify_test_of_builtin_trig (ctxt, result);
305 /**********************************************************************
306 "void" return
307 **********************************************************************/
309 static void
310 create_use_of_void_return (gcc_jit_context *ctxt)
312 /* Let's try to inject the equivalent of:
313 void
314 test_of_void_return (int *out)
316 *out = 1;
317 return;
320 gcc_jit_type *void_t =
321 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
322 gcc_jit_type *int_t =
323 gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
324 gcc_jit_type *int_ptr_t =
325 gcc_jit_type_get_pointer (int_t);
327 /* Build the test_fn. */
328 gcc_jit_param *param_out =
329 gcc_jit_context_new_param (ctxt, NULL, int_ptr_t, "out");
330 gcc_jit_function *test_fn =
331 gcc_jit_context_new_function (ctxt, NULL,
332 GCC_JIT_FUNCTION_EXPORTED,
333 void_t,
334 "test_of_void_return",
335 1, &param_out,
337 gcc_jit_block *initial =
338 gcc_jit_function_new_block (test_fn, "initial");
340 gcc_jit_block_add_assignment (
341 initial, NULL,
342 /* "*out = ..." */
343 gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (param_out),
344 NULL),
345 gcc_jit_context_one (ctxt, int_t));
346 gcc_jit_block_end_with_void_return (initial, NULL);
349 static void
350 verify_void_return (gcc_jit_context *ctxt, gcc_jit_result *result)
352 typedef void (*fn_type) (int *);
353 CHECK_NON_NULL (result);
355 fn_type test_of_void_return =
356 (fn_type)gcc_jit_result_get_code (result, "test_of_void_return");
357 CHECK_NON_NULL (test_of_void_return);
359 int i;
360 test_of_void_return (&i);
361 CHECK_VALUE (i, 1); /* ensure correct value was written back */
364 /**********************************************************************
365 Code for harness
366 **********************************************************************/
368 void
369 create_code (gcc_jit_context *ctxt, void *user_data)
371 create_tests_of_hidden_functions (ctxt);
372 create_use_of_builtins (ctxt);
373 create_use_of_void_return (ctxt);
377 void
378 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
380 verify_hidden_functions (ctxt, result);
381 verify_use_of_builtins (ctxt, result);
382 verify_void_return (ctxt, result);