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