jit: add test-benchmark.c

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
This commit is contained in:
David Malcolm 2015-05-06 20:13:50 +00:00 committed by David Malcolm
parent d2463960a4
commit 5631585aa6
4 changed files with 255 additions and 1 deletions

View 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

View 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". */

View 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

View File

@ -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;
}