1 /* A simple benchmark: how long does it take to use libgccjit to
2 compile and run a simple function? */
10 #define TEST_ESCHEWS_SET_OPTIONS
11 #define TEST_ESCHEWS_TEST_JIT
12 #define TEST_PROVIDES_MAIN
16 create_code (gcc_jit_context
*ctxt
, void *user_data
)
19 Simple sum-of-squares, to test conditionals and looping
25 for (i = 0; i < n ; i ++)
31 gcc_jit_type
*the_type
=
32 gcc_jit_context_get_type (ctxt
, GCC_JIT_TYPE_INT
);
33 gcc_jit_type
*return_type
= the_type
;
36 gcc_jit_context_new_param (ctxt
, NULL
, the_type
, "n");
37 gcc_jit_param
*params
[1] = {n
};
38 gcc_jit_function
*func
=
39 gcc_jit_context_new_function (ctxt
, NULL
,
40 GCC_JIT_FUNCTION_EXPORTED
,
47 gcc_jit_function_new_local (func
, NULL
, the_type
, "i");
49 gcc_jit_function_new_local (func
, NULL
, the_type
, "sum");
51 gcc_jit_block
*initial
=
52 gcc_jit_function_new_block (func
, "initial");
53 gcc_jit_block
*loop_cond
=
54 gcc_jit_function_new_block (func
, "loop_cond");
55 gcc_jit_block
*loop_body
=
56 gcc_jit_function_new_block (func
, "loop_body");
57 gcc_jit_block
*after_loop
=
58 gcc_jit_function_new_block (func
, "after_loop");
61 gcc_jit_block_add_assignment (
64 gcc_jit_context_new_rvalue_from_int (ctxt
, the_type
, 0));
67 gcc_jit_block_add_assignment (
70 gcc_jit_context_new_rvalue_from_int (ctxt
, the_type
, 0));
72 gcc_jit_block_end_with_jump (initial
, NULL
, loop_cond
);
75 gcc_jit_block_end_with_conditional (
77 gcc_jit_context_new_comparison (
79 GCC_JIT_COMPARISON_GE
,
80 gcc_jit_lvalue_as_rvalue (i
),
81 gcc_jit_param_as_rvalue (n
)),
86 gcc_jit_block_add_assignment (
89 gcc_jit_context_new_binary_op (
91 GCC_JIT_BINARY_OP_PLUS
, the_type
,
92 gcc_jit_lvalue_as_rvalue (sum
),
93 gcc_jit_context_new_binary_op (
95 GCC_JIT_BINARY_OP_MULT
, the_type
,
96 gcc_jit_lvalue_as_rvalue (i
),
97 gcc_jit_lvalue_as_rvalue (i
))));
100 gcc_jit_block_add_assignment (
103 gcc_jit_context_new_binary_op (
105 GCC_JIT_BINARY_OP_PLUS
, the_type
,
106 gcc_jit_lvalue_as_rvalue (i
),
107 gcc_jit_context_new_rvalue_from_int (
112 gcc_jit_block_end_with_jump (loop_body
, NULL
, loop_cond
);
115 gcc_jit_block_end_with_return (
118 gcc_jit_lvalue_as_rvalue (sum
));
122 verify_code (gcc_jit_context
*ctxt
, gcc_jit_result
*result
)
124 typedef int (*loop_test_fn_type
) (int);
127 fail ("%s: %s: !result", test
, __func__
);
130 loop_test_fn_type loop_test
=
131 (loop_test_fn_type
)gcc_jit_result_get_code (result
, "loop_test");
134 fail ("%s: %s: !loop_test", test
, __func__
);
137 int val
= loop_test (100);
139 fail ("%s: %s: val != 328350", test
, __func__
);
142 /* Run one iteration of the test. */
144 test_jit (const char *argv0
, int opt_level
)
146 gcc_jit_context
*ctxt
;
147 gcc_jit_result
*result
;
149 ctxt
= gcc_jit_context_acquire ();
152 fail ("gcc_jit_context_acquire failed");
156 /* Set up options. */
157 gcc_jit_context_set_str_option (
159 GCC_JIT_STR_OPTION_PROGNAME
,
162 /* Set up options for benchmarking. */
163 gcc_jit_context_set_int_option (
165 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
,
167 /* Generating debuginfo takes time; turn it off. */
168 gcc_jit_context_set_bool_option (
170 GCC_JIT_BOOL_OPTION_DEBUGINFO
,
172 /* This option is extremely slow; turn it off. */
173 gcc_jit_context_set_bool_option (
175 GCC_JIT_BOOL_OPTION_SELFCHECK_GC
,
178 /* Turn this on to get detailed timings. */
180 gcc_jit_context_set_bool_option (
182 GCC_JIT_BOOL_OPTION_DUMP_SUMMARY
,
185 create_code (ctxt
, NULL
);
187 result
= gcc_jit_context_compile (ctxt
);
188 verify_code (ctxt
, result
);
190 gcc_jit_context_release (ctxt
);
191 gcc_jit_result_release (result
);
194 /* Taken from timevar.c. */
195 static double ticks_to_msec
;
196 #define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
197 #define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
198 static double get_wallclock_time (void)
201 return times (&tms
) * ticks_to_msec
;
204 /* Time 100 iterations, at each optimization level
205 (for 400 iterations in all). */
208 main (int argc
, char **argv
)
211 int num_iterations
= 100;
212 double elapsed_time
[4];
214 ticks_to_msec
= TICKS_TO_MSEC
;
216 for (opt_level
= 0; opt_level
< 4; opt_level
++)
219 double start_time
, end_time
;
220 start_time
= get_wallclock_time ();
221 for (i
= 1; i
<= num_iterations
; i
++)
223 snprintf (test
, sizeof (test
),
224 "%s iteration %d of %d",
225 extract_progname (argv
[0]),
227 test_jit (argv
[0], opt_level
);
229 end_time
= get_wallclock_time ();
230 elapsed_time
[opt_level
] = end_time
- start_time
;
231 pass ("%s: survived %i iterations at optlevel %i",
232 argv
[0], num_iterations
, opt_level
);
233 note (("%s: %i iterations at optlevel %i"
234 " took a total of %.3fs (%.3fs per iteration)"),
235 argv
[0], num_iterations
, opt_level
,
236 elapsed_time
[opt_level
],
237 elapsed_time
[opt_level
] / num_iterations
);
242 /* Print a summary. */
243 printf ("%s: %i iterations: time taken (lower is better)\n",
244 argv
[0], num_iterations
);
245 for (opt_level
= 0; opt_level
< 4; opt_level
++)
246 printf ("optlevel %i: %.3fs (%.3fs per iteration)\n",
248 elapsed_time
[opt_level
],
249 elapsed_time
[opt_level
] / num_iterations
);