jit: add test-benchmark.c
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 6 May 2015 20:13:50 +0000 (20:13 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Wed, 6 May 2015 20:13:50 +0000 (20:13 +0000)
gcc/testsuite/ChangeLog:
* jit.dg/harness.h (set_options): Wrap with
#ifndef TEST_ESCHEWS_SET_OPTIONS.
* jit.dg/jit.exp (is_testcase_meant_to_generate_a_reproducer):
Special-case test-benchmark.c as a negative.
* jit.dg/test-benchmark.c: New file.

From-SVN: r222863

gcc/testsuite/ChangeLog
gcc/testsuite/jit.dg/harness.h
gcc/testsuite/jit.dg/jit.exp
gcc/testsuite/jit.dg/test-benchmark.c [new file with mode: 0644]

index 7c4781c..669efb5 100644 (file)
@@ -1,3 +1,11 @@
+2015-05-06  David Malcolm  <dmalcolm@redhat.com>
+
+       * jit.dg/harness.h (set_options): Wrap with
+       #ifndef TEST_ESCHEWS_SET_OPTIONS.
+       * jit.dg/jit.exp (is_testcase_meant_to_generate_a_reproducer):
+       Special-case test-benchmark.c as a negative.
+       * jit.dg/test-benchmark.c: New file.
+
 2015-05-06  Yvan Roux  <yvan.roux@linaro.org>
 
        PR target/64208
index 907da56..6b59fb5 100644 (file)
@@ -230,6 +230,7 @@ check_string_contains (const char *funcname,
        test, funcname, name, expected_substring);
 }
 
+#ifndef TEST_ESCHEWS_SET_OPTIONS
 static void set_options (gcc_jit_context *ctxt, const char *argv0)
 {
   /* Set up options.  */
@@ -262,6 +263,7 @@ static void set_options (gcc_jit_context *ctxt, const char *argv0)
     GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
     0);
 }
+#endif /* #ifndef TEST_ESCHEWS_SET_OPTIONS */
 
 /* Concatenate two strings.  The result must be released using "free".  */
 
index d13f6b5..39e37c2 100644 (file)
@@ -308,12 +308,16 @@ verbose "tests: $tests"
 proc is_testcase_meant_to_generate_a_reproducer {name} {
     # We expect most testcases to generate a reproducer.
     # The exceptions are the tutorials (which don't have a "test-"
-    # prefix), and test-threads.c (which is unique).
+    # prefix), and test-threads.c and test-benchmark.c (which are each
+    # unique).
     verbose "is_testcase_meant_to_generate_a_reproducer: $name"
     if { [string match "*test-*" $name] } {
        if { [string match "*test-threads.c" $name] } {
            return 0
        }
+       if { [string match "*test-benchmark.c" $name] } {
+           return 0
+       }
        return 1
     }
     return 0
diff --git a/gcc/testsuite/jit.dg/test-benchmark.c b/gcc/testsuite/jit.dg/test-benchmark.c
new file mode 100644 (file)
index 0000000..324ba93
--- /dev/null
@@ -0,0 +1,240 @@
+/* A simple benchmark: how long does it take to use libgccjit to
+   compile and run a simple function?  */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/times.h>
+
+#include "libgccjit.h"
+
+#define TEST_ESCHEWS_SET_OPTIONS
+#define TEST_ESCHEWS_TEST_JIT
+#define TEST_PROVIDES_MAIN
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /*
+    Simple sum-of-squares, to test conditionals and looping
+
+    int loop_test (int n)
+    {
+      int i;
+      int sum = 0;
+      for (i = 0; i < n ; i ++)
+      {
+       sum += i * i;
+      }
+      return sum;
+   */
+  gcc_jit_type *the_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_type *return_type = the_type;
+
+  gcc_jit_param *n =
+    gcc_jit_context_new_param (ctxt, NULL, the_type, "n");
+  gcc_jit_param *params[1] = {n};
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+                                 GCC_JIT_FUNCTION_EXPORTED,
+                                 return_type,
+                                 "loop_test",
+                                 1, params, 0);
+
+  /* Build locals:  */
+  gcc_jit_lvalue *i =
+    gcc_jit_function_new_local (func, NULL, the_type, "i");
+  gcc_jit_lvalue *sum =
+    gcc_jit_function_new_local (func, NULL, the_type, "sum");
+
+  gcc_jit_block *initial =
+    gcc_jit_function_new_block (func, "initial");
+  gcc_jit_block *loop_cond =
+    gcc_jit_function_new_block (func, "loop_cond");
+  gcc_jit_block *loop_body =
+    gcc_jit_function_new_block (func, "loop_body");
+  gcc_jit_block *after_loop =
+    gcc_jit_function_new_block (func, "after_loop");
+
+  /* sum = 0; */
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    sum,
+    gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
+
+  /* i = 0; */
+  gcc_jit_block_add_assignment (
+    initial, NULL,
+    i,
+    gcc_jit_context_new_rvalue_from_int (ctxt, the_type, 0));
+
+  gcc_jit_block_end_with_jump (initial, NULL, loop_cond);
+
+  /* if (i >= n) */
+  gcc_jit_block_end_with_conditional (
+    loop_cond, NULL,
+    gcc_jit_context_new_comparison (
+       ctxt, NULL,
+       GCC_JIT_COMPARISON_GE,
+       gcc_jit_lvalue_as_rvalue (i),
+       gcc_jit_param_as_rvalue (n)),
+    after_loop,
+    loop_body);
+
+  /* sum += i * i */
+  gcc_jit_block_add_assignment (
+    loop_body, NULL,
+    sum,
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      GCC_JIT_BINARY_OP_PLUS, the_type,
+      gcc_jit_lvalue_as_rvalue (sum),
+      gcc_jit_context_new_binary_op (
+        ctxt, NULL,
+        GCC_JIT_BINARY_OP_MULT, the_type,
+        gcc_jit_lvalue_as_rvalue (i),
+        gcc_jit_lvalue_as_rvalue (i))));
+
+  /* i++ */
+  gcc_jit_block_add_assignment (
+    loop_body, NULL,
+    i,
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      GCC_JIT_BINARY_OP_PLUS, the_type,
+      gcc_jit_lvalue_as_rvalue (i),
+      gcc_jit_context_new_rvalue_from_int (
+       ctxt,
+       the_type,
+       1)));
+
+  gcc_jit_block_end_with_jump (loop_body, NULL, loop_cond);
+
+  /* return sum */
+  gcc_jit_block_end_with_return (
+    after_loop,
+    NULL,
+    gcc_jit_lvalue_as_rvalue (sum));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  typedef int (*loop_test_fn_type) (int);
+  if (!result)
+    {
+      fail ("%s: %s: !result", test, __func__);
+      return;
+    }
+  loop_test_fn_type loop_test =
+    (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
+  if (!loop_test)
+    {
+      fail ("%s: %s: !loop_test", test, __func__);
+      return;
+    }
+  int val = loop_test (100);
+  if (val != 328350)
+    fail ("%s: %s: val != 328350", test, __func__);
+}
+
+/* Run one iteration of the test.  */
+static void
+test_jit (const char *argv0, int opt_level)
+{
+  gcc_jit_context *ctxt;
+  gcc_jit_result *result;
+
+  ctxt = gcc_jit_context_acquire ();
+  if (!ctxt)
+    {
+      fail ("gcc_jit_context_acquire failed");
+      return;
+    }
+
+  /* Set up options.  */
+  gcc_jit_context_set_str_option (
+    ctxt,
+    GCC_JIT_STR_OPTION_PROGNAME,
+    argv0);
+
+  /* Set up options for benchmarking.  */
+  gcc_jit_context_set_int_option (
+    ctxt,
+    GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
+    opt_level);
+  /* Generating debuginfo takes time; turn it off.  */
+  gcc_jit_context_set_bool_option (
+    ctxt,
+    GCC_JIT_BOOL_OPTION_DEBUGINFO,
+    0);
+  /* This option is extremely slow; turn it off.  */
+  gcc_jit_context_set_bool_option (
+    ctxt,
+    GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
+    0);
+
+  /* Turn this on to get detailed timings.  */
+  if (0)
+    gcc_jit_context_set_bool_option (
+      ctxt,
+      GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
+      1);
+
+  create_code (ctxt, NULL);
+
+  result = gcc_jit_context_compile (ctxt);
+  verify_code (ctxt, result);
+
+  gcc_jit_context_release (ctxt);
+  gcc_jit_result_release (result);
+}
+
+/* Taken from timevar.c.  */
+static double ticks_to_msec;
+#define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
+#define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
+static double get_wallclock_time (void)
+{
+  struct tms tms;
+  return times (&tms) * ticks_to_msec;
+}
+
+/* Time 100 iterations, at each optimization level
+   (for 400 iterations in all).  */
+
+int
+main (int argc, char **argv)
+{
+  int opt_level;
+  int num_iterations = 100;
+
+  ticks_to_msec = TICKS_TO_MSEC;
+
+  for (opt_level = 0; opt_level < 4; opt_level++)
+    {
+      int i;
+      double start_time, end_time, elapsed_time;
+      start_time = get_wallclock_time ();
+      for (i = 1; i <= num_iterations; i++)
+       {
+         snprintf (test, sizeof (test),
+                   "%s iteration %d of %d",
+                   extract_progname (argv[0]),
+                   i, num_iterations);
+         test_jit (argv[0], opt_level);
+       }
+      end_time = get_wallclock_time ();
+      elapsed_time = end_time - start_time;
+      pass ("%s: survived %i iterations at optlevel %i",
+           argv[0], num_iterations, opt_level);
+      note (("%s: %i iterations at optlevel %i"
+            " took a total of %.3fs (%.3fs per iteration)"),
+           argv[0], num_iterations, opt_level,
+           elapsed_time, elapsed_time / num_iterations);
+    }
+  totals ();
+
+  return 0;
+}