/gcc/testsuite/jit.dg/test-benchmark.c

https://gitlab.com/4144/gcc · C · 268 lines · 201 code · 35 blank · 32 comment · 9 complexity · 3f5b0ae02ffd9c801777cd40eeb400a9 MD5 · raw file

  1. /* A simple benchmark: how long does it take to use libgccjit to
  2. compile and run a simple function? */
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <sys/times.h>
  7. #include "libgccjit.h"
  8. #define TEST_ESCHEWS_SET_OPTIONS
  9. #define TEST_ESCHEWS_TEST_JIT
  10. #define TEST_PROVIDES_MAIN
  11. #include "harness.h"
  12. void
  13. create_code (gcc_jit_context *ctxt, void *user_data)
  14. {
  15. /*
  16. Simple sum-of-squares, to test conditionals and looping
  17. int loop_test (int n)
  18. {
  19. int i;
  20. int sum = 0;
  21. for (i = 0; i < n ; i ++)
  22. {
  23. sum += i * i;
  24. }
  25. return sum;
  26. */
  27. gcc_jit_type *the_type =
  28. gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
  29. gcc_jit_type *return_type = the_type;
  30. gcc_jit_param *n =
  31. gcc_jit_context_new_param (ctxt, NULL, the_type, "n");
  32. gcc_jit_param *params[1] = {n};
  33. gcc_jit_function *func =
  34. gcc_jit_context_new_function (ctxt, NULL,
  35. GCC_JIT_FUNCTION_EXPORTED,
  36. return_type,
  37. "loop_test",
  38. 1, params, 0);
  39. /* Build locals: */
  40. gcc_jit_lvalue *i =
  41. gcc_jit_function_new_local (func, NULL, the_type, "i");
  42. gcc_jit_lvalue *sum =
  43. gcc_jit_function_new_local (func, NULL, the_type, "sum");
  44. gcc_jit_block *initial =
  45. gcc_jit_function_new_block (func, "initial");
  46. gcc_jit_block *loop_cond =
  47. gcc_jit_function_new_block (func, "loop_cond");
  48. gcc_jit_block *loop_body =
  49. gcc_jit_function_new_block (func, "loop_body");
  50. gcc_jit_block *after_loop =
  51. gcc_jit_function_new_block (func, "after_loop");
  52. /* sum = 0; */
  53. gcc_jit_block_add_assignment (
  54. initial, NULL,
  55. sum,
  56. gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
  57. /* i = 0; */
  58. gcc_jit_block_add_assignment (
  59. initial, NULL,
  60. i,
  61. gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
  62. gcc_jit_block_end_with_jump (initial, NULL, loop_cond);
  63. /* if (i >= n) */
  64. gcc_jit_block_end_with_conditional (
  65. loop_cond, NULL,
  66. gcc_jit_context_new_comparison (
  67. ctxt, NULL,
  68. GCC_JIT_COMPARISON_GE,
  69. gcc_jit_lvalue_as_rvalue (i),
  70. gcc_jit_param_as_rvalue (n)),
  71. after_loop,
  72. loop_body);
  73. /* sum += i * i */
  74. gcc_jit_block_add_assignment (
  75. loop_body, NULL,
  76. sum,
  77. gcc_jit_context_new_binary_op (
  78. ctxt, NULL,
  79. GCC_JIT_BINARY_OP_PLUS, the_type,
  80. gcc_jit_lvalue_as_rvalue (sum),
  81. gcc_jit_context_new_binary_op (
  82. ctxt, NULL,
  83. GCC_JIT_BINARY_OP_MULT, the_type,
  84. gcc_jit_lvalue_as_rvalue (i),
  85. gcc_jit_lvalue_as_rvalue (i))));
  86. /* i++ */
  87. gcc_jit_block_add_assignment (
  88. loop_body, NULL,
  89. i,
  90. gcc_jit_context_new_binary_op (
  91. ctxt, NULL,
  92. GCC_JIT_BINARY_OP_PLUS, the_type,
  93. gcc_jit_lvalue_as_rvalue (i),
  94. gcc_jit_context_new_rvalue_from_int (
  95. ctxt,
  96. the_type,
  97. 1)));
  98. gcc_jit_block_end_with_jump (loop_body, NULL, loop_cond);
  99. /* return sum */
  100. gcc_jit_block_end_with_return (
  101. after_loop,
  102. NULL,
  103. gcc_jit_lvalue_as_rvalue (sum));
  104. }
  105. void
  106. verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
  107. {
  108. typedef int (*loop_test_fn_type) (int);
  109. if (!result)
  110. {
  111. fail ("%s: %s: !result", test, __func__);
  112. return;
  113. }
  114. loop_test_fn_type loop_test =
  115. (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
  116. if (!loop_test)
  117. {
  118. fail ("%s: %s: !loop_test", test, __func__);
  119. return;
  120. }
  121. int val = loop_test (100);
  122. if (val != 328350)
  123. fail ("%s: %s: val != 328350", test, __func__);
  124. }
  125. /* Run one iteration of the test. */
  126. static void
  127. test_jit (const char *argv0, int opt_level, gcc_jit_timer *timer)
  128. {
  129. gcc_jit_context *ctxt;
  130. gcc_jit_result *result;
  131. gcc_jit_timer_push (timer, "test_jit");
  132. ctxt = gcc_jit_context_acquire ();
  133. if (!ctxt)
  134. {
  135. fail ("gcc_jit_context_acquire failed");
  136. return;
  137. }
  138. gcc_jit_context_set_timer (ctxt, timer);
  139. /* Set up options. */
  140. gcc_jit_context_set_str_option (
  141. ctxt,
  142. GCC_JIT_STR_OPTION_PROGNAME,
  143. argv0);
  144. /* Set up options for benchmarking. */
  145. gcc_jit_context_set_int_option (
  146. ctxt,
  147. GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
  148. opt_level);
  149. /* Generating debuginfo takes time; turn it off. */
  150. gcc_jit_context_set_bool_option (
  151. ctxt,
  152. GCC_JIT_BOOL_OPTION_DEBUGINFO,
  153. 0);
  154. /* This option is extremely slow; turn it off. */
  155. gcc_jit_context_set_bool_option (
  156. ctxt,
  157. GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
  158. 0);
  159. /* Turn this on to get detailed timings. */
  160. if (0)
  161. gcc_jit_context_set_bool_option (
  162. ctxt,
  163. GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
  164. 1);
  165. gcc_jit_timer_push (timer, "create_code");
  166. create_code (ctxt, NULL);
  167. gcc_jit_timer_pop (timer, "create_code");
  168. gcc_jit_timer_push (timer, "compile");
  169. result = gcc_jit_context_compile (ctxt);
  170. gcc_jit_timer_pop (timer, "compile");
  171. gcc_jit_timer_push (timer, "verify_code");
  172. verify_code (ctxt, result);
  173. gcc_jit_timer_pop (timer, "verify_code");
  174. gcc_jit_context_release (ctxt);
  175. gcc_jit_result_release (result);
  176. gcc_jit_timer_pop (timer, "test_jit");
  177. }
  178. /* Taken from timevar.c. */
  179. static double ticks_to_msec;
  180. #define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
  181. #define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
  182. static double get_wallclock_time (void)
  183. {
  184. struct tms tms;
  185. return times (&tms) * ticks_to_msec;
  186. }
  187. /* Time 100 iterations, at each optimization level
  188. (for 400 iterations in all). */
  189. int
  190. main (int argc, char **argv)
  191. {
  192. int opt_level;
  193. int num_iterations = 100;
  194. double elapsed_time[4];
  195. ticks_to_msec = TICKS_TO_MSEC;
  196. for (opt_level = 0; opt_level < 4; opt_level++)
  197. {
  198. int i;
  199. double start_time, end_time;
  200. start_time = get_wallclock_time ();
  201. gcc_jit_timer *timer = gcc_jit_timer_new ();
  202. for (i = 1; i <= num_iterations; i++)
  203. {
  204. snprintf (test, sizeof (test),
  205. "%s iteration %d of %d",
  206. extract_progname (argv[0]),
  207. i, num_iterations);
  208. test_jit (argv[0], opt_level, timer);
  209. }
  210. end_time = get_wallclock_time ();
  211. elapsed_time[opt_level] = end_time - start_time;
  212. gcc_jit_timer_print (timer, stderr);
  213. gcc_jit_timer_release (timer);
  214. pass ("%s: survived %i iterations at optlevel %i",
  215. argv[0], num_iterations, opt_level);
  216. note (("%s: %i iterations at optlevel %i"
  217. " took a total of %.3fs (%.3fs per iteration)"),
  218. argv[0], num_iterations, opt_level,
  219. elapsed_time[opt_level],
  220. elapsed_time[opt_level] / num_iterations);
  221. }
  222. totals ();
  223. /* Print a summary. */
  224. printf ("%s: %i iterations: time taken (lower is better)\n",
  225. argv[0], num_iterations);
  226. for (opt_level = 0; opt_level < 4; opt_level++)
  227. printf ("optlevel %i: %.3fs (%.3fs per iteration)\n",
  228. opt_level,
  229. elapsed_time[opt_level],
  230. elapsed_time[opt_level] / num_iterations);
  231. return 0;
  232. }