/* Copyright 2002 - 2009 David A. Schleef Copyright 2012 MIPS Technologies, Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef _MSC_VER #define isnan(x) _isnan(x) #define snprintf _snprintf #endif #define MIN_NONDENORMAL (1.1754944909521339405e-38) void _orc_profile_init(void); OrcRandomContext rand_context; void orc_test_init (void) { orc_init (); setvbuf (stdout, NULL, _IONBF, 0); orc_random_init (&rand_context, 0x12345678); _orc_profile_init (); } OrcTestResult orc_test_gcc_compile (OrcProgram *p) { char cmd[300]; char *base; char source_filename[100]; char obj_filename[100]; char dis_filename[100]; char dump_filename[100]; char dump_dis_filename[100]; int ret; FILE *file; OrcCompileResult result; OrcTarget *target; unsigned int flags; int n; base = "temp-orc-test"; n = snprintf(source_filename, sizeof(source_filename), "%s-source.s", base); ORC_ASSERT(n < sizeof(source_filename)); n = snprintf(obj_filename, sizeof(obj_filename), "%s.o", base); ORC_ASSERT(n < sizeof(obj_filename)); n = snprintf(dis_filename, sizeof(dis_filename), "%s-source.dis", base); ORC_ASSERT(n < sizeof(dis_filename)); n = snprintf(dump_filename, sizeof(dump_filename), "%s-dump.bin", base); ORC_ASSERT(n < sizeof(dump_filename)); n = snprintf(dump_dis_filename, sizeof(dump_dis_filename), "%s-dump.dis", base); ORC_ASSERT(n < sizeof(dump_dis_filename)); target = orc_target_get_default (); flags = orc_target_get_default_flags (target); flags |= ORC_TARGET_CLEAN_COMPILE; if (strcmp (orc_target_get_name (target), "sse") == 0) { flags |= ORC_TARGET_SSE_SHORT_JUMPS; } if (strcmp (orc_target_get_name (target), "mmx") == 0) { flags |= ORC_TARGET_MMX_SHORT_JUMPS; } result = orc_program_compile_full (p, target, flags); if (ORC_COMPILE_RESULT_IS_FATAL(result)) { printf (" error: %s\n", orc_program_get_error (p)); return ORC_TEST_FAILED; } if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { //printf (" no code generated: %s\n", orc_program_get_error (p)); return ORC_TEST_INDETERMINATE; } fflush (stdout); file = fopen (source_filename, "w"); fprintf(file, "%s", orc_program_get_asm_code (p)); fclose (file); file = fopen (dump_filename, "w"); ret = fwrite(p->orccode->code, p->orccode->code_size, 1, file); fclose (file); #if defined(HAVE_POWERPC) n = snprintf (cmd, sizeof(cmd), "gcc -Wa,-mregnames -Wall -c %s -o %s", source_filename, obj_filename); #else n = snprintf (cmd, sizeof(cmd), "gcc -Wall -c %s -o %s", source_filename, obj_filename); #endif ORC_ASSERT(n < sizeof(cmd)); ret = system (cmd); if (ret != 0) { ORC_ERROR ("gcc failed"); printf("%s\n", orc_program_get_asm_code (p)); return ORC_TEST_FAILED; } #if 1 n = snprintf (cmd, sizeof(cmd), "objdump -dr %s | sed 's/^[ 0-9a-f]*:/XXX:/' >%s", obj_filename, dis_filename); #else n = snprintf (cmd, sizeof(cmd), "objdump -dr %s >%s", obj_filename, dis_filename); #endif ORC_ASSERT(n < sizeof(cmd)); ret = system (cmd); if (ret != 0) { ORC_ERROR ("objdump failed"); return ORC_TEST_FAILED; } n = snprintf (cmd, sizeof(cmd), "objcopy -I binary " #ifdef HAVE_I386 "-O elf32-i386 -B i386 " #elif defined(HAVE_AMD64) "-O elf64-x86-64 -B i386 " #elif defined(HAVE_POWERPC) "-O elf32-powerpc -B powerpc " #else /* FIXME */ #endif "--rename-section .data=.text " "--redefine-sym _binary_temp_orc_test_dump_bin_start=%s " "%s %s", p->name, dump_filename, obj_filename); ORC_ASSERT(n < sizeof(cmd)); ret = system (cmd); if (ret != 0) { printf("objcopy failed\n"); return ORC_TEST_FAILED; } #if 1 n = snprintf (cmd, sizeof(cmd), "objdump -Dr %s | sed 's/^[ 0-9a-f]*:/XXX:/' >%s", obj_filename, dump_dis_filename); #else n = snprintf (cmd, sizeof(cmd), "objdump -Dr %s >%s", obj_filename, dump_dis_filename); #endif ORC_ASSERT(n < sizeof(cmd)); ret = system (cmd); if (ret != 0) { printf("objdump failed\n"); return ORC_TEST_FAILED; } n = snprintf (cmd, sizeof(cmd), "diff -u %s %s", dis_filename, dump_dis_filename); ORC_ASSERT(n < sizeof(cmd)); ret = system (cmd); if (ret != 0) { printf("diff failed\n"); return ORC_TEST_FAILED; } remove (source_filename); remove (obj_filename); remove (dis_filename); remove (dump_filename); remove (dump_dis_filename); return ORC_TEST_OK; } #define PREFIX "/opt/arm-2008q3/bin/arm-none-linux-gnueabi-" OrcTestResult orc_test_gcc_compile_neon (OrcProgram *p) { char cmd[300]; char *base; char source_filename[100]; char obj_filename[100]; char dis_filename[100]; char dump_filename[100]; char dump_dis_filename[100]; int ret; FILE *file; OrcCompileResult result; OrcTarget *target; unsigned int flags; base = "temp-orc-test"; sprintf(source_filename, "%s-source.s", base); sprintf(obj_filename, "%s.o", base); sprintf(dis_filename, "%s-source.dis", base); sprintf(dump_filename, "%s-dump.bin", base); sprintf(dump_dis_filename, "%s-dump.dis", base); target = orc_target_get_by_name ("neon"); flags = orc_target_get_default_flags (target); flags |= ORC_TARGET_CLEAN_COMPILE; result = orc_program_compile_full (p, target, flags); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { //printf (" no code generated: %s\n", orc_program_get_error (p)); return ORC_TEST_INDETERMINATE; } fflush (stdout); file = fopen (source_filename, "w"); fprintf(file, "%s", orc_program_get_asm_code (p)); fclose (file); file = fopen (dump_filename, "w"); ret = fwrite(p->orccode->code, p->orccode->code_size, 1, file); fclose (file); sprintf (cmd, PREFIX "gcc -march=armv6t2 -mcpu=cortex-a8 -mfpu=neon -Wall " "-c %s -o %s", source_filename, obj_filename); ret = system (cmd); if (ret != 0) { ORC_ERROR ("arm gcc failed"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, PREFIX "objdump -dr %s >%s", obj_filename, dis_filename); ret = system (cmd); if (ret != 0) { ORC_ERROR ("objdump failed"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, PREFIX "objcopy -I binary " "-O elf32-littlearm -B arm " "--rename-section .data=.text " "--redefine-sym _binary_temp_orc_test_dump_bin_start=%s " "%s %s", p->name, dump_filename, obj_filename); ret = system (cmd); if (ret != 0) { printf("objcopy failed\n"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, PREFIX "objdump -Dr %s >%s", obj_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("objdump failed\n"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, "diff -u %s %s", dis_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("diff failed\n"); return ORC_TEST_FAILED; } remove (source_filename); remove (obj_filename); remove (dis_filename); remove (dump_filename); remove (dump_dis_filename); return ORC_TEST_OK; } #define C64X_PREFIX "/opt/TI/TI_CGT_C6000_6.1.12/bin/" OrcTestResult orc_test_gcc_compile_c64x (OrcProgram *p) { char cmd[300]; char *base; char source_filename[100]; char obj_filename[100]; char dis_filename[100]; char dump_filename[100]; char dump_dis_filename[100]; int ret; FILE *file; OrcCompileResult result; OrcTarget *target; unsigned int flags; base = "temp-orc-test"; sprintf(source_filename, "%s-source.c", base); sprintf(obj_filename, "%s-source.obj", base); sprintf(dis_filename, "%s-source.dis", base); sprintf(dump_filename, "%s-dump.bin", base); sprintf(dump_dis_filename, "%s-dump.dis", base); target = orc_target_get_by_name ("c64x-c"); flags = orc_target_get_default_flags (target); result = orc_program_compile_full (p, target, flags); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { //printf (" no code generated: %s\n", orc_program_get_error (p)); return ORC_TEST_INDETERMINATE; } fflush (stdout); file = fopen (source_filename, "w"); fprintf(file, "%s", orc_target_get_preamble (target)); fprintf(file, "%s", orc_program_get_asm_code (p)); fclose (file); file = fopen (dump_filename, "w"); ret = fwrite(p->orccode->code, p->orccode->code_size, 1, file); fclose (file); sprintf (cmd, C64X_PREFIX "cl6x -mv=6400+ " "-c %s", source_filename); ret = system (cmd); if (ret != 0) { ORC_ERROR ("compiler failed"); //printf("%s\n", orc_program_get_asm_code (p)); return ORC_TEST_INDETERMINATE; } sprintf (cmd, C64X_PREFIX "dis6x %s >%s", obj_filename, dis_filename); ret = system (cmd); if (ret != 0) { ORC_ERROR ("objdump failed"); return ORC_TEST_INDETERMINATE; } #if 0 sprintf (cmd, C64X_PREFIX "objcopy -I binary " "-O elf32-littlearm -B arm " "--rename-section .data=.text " "--redefine-sym _binary_temp_orc_test_dump_bin_start=%s " "%s %s", p->name, dump_filename, obj_filename); ret = system (cmd); if (ret != 0) { printf("objcopy failed\n"); return ORC_TEST_FAILED; } #endif #if 0 sprintf (cmd, C64X_PREFIX "dis6x %s >%s", dump_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("objdump failed\n"); return ORC_TEST_FAILED; } sprintf (cmd, "diff -u %s %s", dis_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("diff failed\n"); return ORC_TEST_FAILED; } #endif remove (source_filename); remove (obj_filename); remove (dis_filename); remove (dump_filename); remove (dump_dis_filename); return ORC_TEST_OK; } void orc_test_random_bits (void *data, int n_bytes) { #if 1 orc_uint8 *d = data; int i; for(i=0;idata, i*array->element_size + j*array->stride); switch (array->element_size) { case 1: printf(" %4d", *(orc_int8 *)ptr); return *(orc_int8 *)ptr; case 2: printf(" %5d", *(orc_int16 *)ptr); return *(orc_int16 *)ptr; case 4: printf(" %10d", *(orc_int32 *)ptr); return *(orc_int32 *)ptr; case 8: printf(" 0x%08x%08x", (orc_uint32)((*(orc_uint64 *)ptr)>>32), (orc_uint32)((*(orc_uint64 *)ptr))); return *(orc_int64 *)ptr; default: return -1; } } #ifdef unused static orc_uint64 print_array_val_unsigned (OrcArray *array, int i, int j) { void *ptr = ORC_PTR_OFFSET (array->data, i*array->element_size + j*array->stride); switch (array->element_size) { case 1: printf(" %4u", *(orc_uint8 *)ptr); return *(orc_int8 *)ptr; case 2: printf(" %5u", *(orc_uint16 *)ptr); return *(orc_int16 *)ptr; case 4: printf(" %10u", *(orc_uint32 *)ptr); return *(orc_int32 *)ptr; case 8: printf(" 0x%08x%08x", (orc_uint32)((*(orc_uint64 *)ptr)>>32), (orc_uint32)((*(orc_uint64 *)ptr))); return *(orc_int64 *)ptr; default: return -1; } } #endif static orc_uint64 print_array_val_hex (OrcArray *array, int i, int j) { void *ptr = ORC_PTR_OFFSET (array->data, i*array->element_size + j*array->stride); switch (array->element_size) { case 1: printf(" %02x", *(orc_uint8 *)ptr); return *(orc_int8 *)ptr; case 2: printf(" %04x", *(orc_uint16 *)ptr); return *(orc_int16 *)ptr; case 4: printf(" %08x", *(orc_uint32 *)ptr); return *(orc_int32 *)ptr; case 8: printf(" 0x%08x%08x", (orc_uint32)((*(orc_uint64 *)ptr)>>32), (orc_uint32)((*(orc_uint64 *)ptr))); return *(orc_int64 *)ptr; default: return -1; } } static orc_uint64 print_array_val_float (OrcArray *array, int i, int j) { void *ptr = ORC_PTR_OFFSET (array->data, i*array->element_size + j*array->stride); switch (array->element_size) { case 4: if (isnan(*(float *)ptr)) { printf(" nan %08x", *(orc_uint32 *)ptr); /* This is to get around signaling/non-signaling nans in the output */ return (*(orc_uint32 *)ptr) & 0xffbfffff; } else { printf(" %12.5g", *(float *)ptr); return *(orc_int32 *)ptr; } case 8: printf(" %12.5g", *(double *)ptr); return *(orc_int64 *)ptr; default: printf(" ERROR"); return -1; } } int float_compare (OrcArray *array1, OrcArray *array2, int i, int j) { void *ptr1 = ORC_PTR_OFFSET (array1->data, i*array1->element_size + j*array1->stride); void *ptr2 = ORC_PTR_OFFSET (array2->data, i*array2->element_size + j*array2->stride); switch (array1->element_size) { case 4: if (isnan(*(float *)ptr1) && isnan(*(float *)ptr2)) return TRUE; if (*(float *)ptr1 == *(float *)ptr2) return TRUE; if (fabs(*(float *)ptr1 - *(float *)ptr2) < MIN_NONDENORMAL) return TRUE; return FALSE; case 8: /* FIXME */ return FALSE; } return FALSE; } OrcTestResult orc_test_compare_output (OrcProgram *program) { return orc_test_compare_output_full (program, 0); } OrcTestResult orc_test_compare_output_backup (OrcProgram *program) { return orc_test_compare_output_full (program, ORC_TEST_FLAGS_BACKUP); } OrcTestResult orc_test_compare_output_full (OrcProgram *program, int flags) { OrcExecutor *ex; int n; int m; OrcArray *dest_exec[4] = { NULL, NULL, NULL, NULL }; OrcArray *dest_emul[4] = { NULL, NULL, NULL, NULL }; OrcArray *src[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int i; int j; int k; int have_dest ORC_GNUC_UNUSED = FALSE; OrcCompileResult result; int have_acc = FALSE; int acc_exec = 0, acc_emul = 0; int ret = ORC_TEST_OK; int bad = 0; int misalignment; ORC_DEBUG ("got here"); { OrcTarget *target; unsigned int flags; target = orc_target_get_default (); flags = orc_target_get_default_flags (target); result = orc_program_compile_full (program, target, flags); if (ORC_COMPILE_RESULT_IS_FATAL(result)) { ret = ORC_TEST_FAILED; goto out; } if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { //printf (" no code generated: %s\n", orc_program_get_error (program)); ret = ORC_TEST_INDETERMINATE; goto out; } } if (program->constant_n > 0) { n = program->constant_n; } else { n = 64 + (orc_random(&rand_context)&0xf); } ex = orc_executor_new (program); orc_executor_set_n (ex, n); if (program->is_2d) { if (program->constant_m > 0) { m = program->constant_m; } else { m = 8 + (orc_random(&rand_context)&0xf); } } else { m = 1; } orc_executor_set_m (ex, m); ORC_DEBUG("size %d %d", ex->n, ex->params[ORC_VAR_A1]); misalignment = 0; for(i=0;ivars[i].name == NULL) continue; if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { src[i-ORC_VAR_S1] = orc_array_new (n, m, program->vars[i].size, misalignment, program->vars[i].alignment); orc_array_set_random (src[i-ORC_VAR_S1], &rand_context); misalignment++; } else if (program->vars[i].vartype == ORC_VAR_TYPE_DEST) { dest_exec[i-ORC_VAR_D1] = orc_array_new (n, m, program->vars[i].size, misalignment, program->vars[i].alignment); orc_array_set_pattern (dest_exec[i], ORC_OOB_VALUE); dest_emul[i-ORC_VAR_D1] = orc_array_new (n, m, program->vars[i].size, misalignment, program->vars[i].alignment); orc_array_set_pattern (dest_emul[i], ORC_OOB_VALUE); misalignment++; } else if (program->vars[i].vartype == ORC_VAR_TYPE_PARAM) { switch (program->vars[i].param_type) { case ORC_PARAM_TYPE_INT: orc_executor_set_param (ex, i, 2); break; case ORC_PARAM_TYPE_FLOAT: orc_executor_set_param_float (ex, i, 2.0); break; case ORC_PARAM_TYPE_INT64: orc_executor_set_param_int64 (ex, i, 2); break; case ORC_PARAM_TYPE_DOUBLE: orc_executor_set_param_double (ex, i, 2.0); break; } } } for(i=0;ivars[i].vartype == ORC_VAR_TYPE_DEST) { orc_executor_set_array (ex, i, dest_exec[i-ORC_VAR_D1]->data); orc_executor_set_stride (ex, i, dest_exec[i-ORC_VAR_D1]->stride); have_dest = TRUE; } if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { orc_executor_set_array (ex, i, src[i-ORC_VAR_S1]->data); orc_executor_set_stride (ex, i, src[i-ORC_VAR_S1]->stride); } } ORC_DEBUG ("running"); if (flags & ORC_TEST_FLAGS_BACKUP) { orc_executor_run_backup (ex); } else { orc_executor_run (ex); } ORC_DEBUG ("done running"); for(i=0;ivars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) { acc_exec = ex->accumulators[0]; have_acc = TRUE; } } for(i=0;ivars[i].vartype == ORC_VAR_TYPE_DEST) { orc_executor_set_array (ex, i, dest_emul[i]->data); orc_executor_set_stride (ex, i, dest_emul[i]->stride); } if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { ORC_DEBUG("setting array %p", src[i-ORC_VAR_S1]->data); orc_executor_set_array (ex, i, src[i-ORC_VAR_S1]->data); orc_executor_set_stride (ex, i, src[i-ORC_VAR_S1]->stride); } } orc_executor_emulate (ex); for(i=0;ivars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) { acc_emul = ex->accumulators[0]; } } for(k=ORC_VAR_D1;kvars[k].size > 0) { if (!orc_array_compare (dest_exec[k-ORC_VAR_D1], dest_emul[k-ORC_VAR_D1], flags)) { printf("dest array %d bad\n", k); bad = TRUE; } if (!orc_array_check_out_of_bounds (dest_exec[k-ORC_VAR_D1])) { printf("out of bounds failure\n"); ret = ORC_TEST_FAILED; } } } if (bad) { for(j=0;jvars[l].size > 0) { if (flags & ORC_TEST_FLAGS_FLOAT) { print_array_val_float (src[l-ORC_VAR_S1], i, j); } else { print_array_val_hex (src[l-ORC_VAR_S1], i, j); } } } printf(" ->"); for(l=ORC_VAR_D1;lvars[l].size > 0) { if (flags & ORC_TEST_FLAGS_FLOAT) { a = print_array_val_float (dest_emul[l-ORC_VAR_D1], i, j); b = print_array_val_float (dest_exec[l-ORC_VAR_D1], i, j); if (!float_compare (dest_emul[l-ORC_VAR_D1], dest_exec[l-ORC_VAR_D1], i, j) != 0) { line_bad = TRUE; } } else { a = print_array_val_hex (dest_emul[l-ORC_VAR_D1], i, j); b = print_array_val_hex (dest_exec[l-ORC_VAR_D1], i, j); if (a != b) { line_bad = TRUE; } } } } if (line_bad) { printf(" *"); } printf("\n"); } } ret = ORC_TEST_FAILED; } if (have_acc) { if (acc_emul != acc_exec) { for(j=0;jvars[k].name == NULL) continue; if (program->vars[k].vartype == ORC_VAR_TYPE_SRC && program->vars[k].size > 0) { if (flags & ORC_TEST_FLAGS_FLOAT) { print_array_val_float (src[k-ORC_VAR_S1], i, j); } else { print_array_val_signed (src[k-ORC_VAR_S1], i, j); } } } printf(" -> acc\n"); } } printf("acc %d %d\n", acc_emul, acc_exec); ret = ORC_TEST_FAILED; } } if (ret == ORC_TEST_FAILED) { printf("%s", orc_program_get_asm_code (program)); } for(i=0;i<4;i++){ if (dest_exec[i]) orc_array_free (dest_exec[i]); if (dest_emul[i]) orc_array_free (dest_emul[i]); } for(i=0;i<8;i++){ if (src[i]) orc_array_free (src[i]); } orc_executor_free (ex); out: orc_program_reset (program); return ret; } OrcProgram * orc_test_get_program_for_opcode (OrcStaticOpcode *opcode) { OrcProgram *p; char s[40]; int flags ORC_GNUC_UNUSED = 0; int args[4] = { -1, -1, -1, -1 }; int n_args = 0; p = orc_program_new (); if (opcode->flags & ORC_STATIC_OPCODE_ACCUMULATOR) { args[n_args++] = orc_program_add_accumulator (p, opcode->dest_size[0], "d1"); } else { args[n_args++] = orc_program_add_destination (p, opcode->dest_size[0], "d1"); } if (opcode->dest_size[1] != 0) { args[n_args++] = orc_program_add_destination (p, opcode->dest_size[1], "d2"); } if (opcode->flags & ORC_STATIC_OPCODE_SCALAR) { if (opcode->src_size[1] == 0) { args[n_args++] = orc_program_add_constant (p, opcode->src_size[0], 1, "c1"); } else { args[n_args++] = orc_program_add_source (p, opcode->src_size[0], "s1"); args[n_args++] = orc_program_add_constant (p, opcode->src_size[1], 1, "c1"); if (opcode->src_size[2] != 0) { args[n_args++] = orc_program_add_constant (p, opcode->src_size[1], 1, "c1"); } } } else { args[n_args++] = orc_program_add_source (p, opcode->src_size[0], "s1"); args[n_args++] = orc_program_add_source (p, opcode->src_size[1], "s2"); } if ((opcode->flags & ORC_STATIC_OPCODE_FLOAT_SRC) || (opcode->flags & ORC_STATIC_OPCODE_FLOAT_DEST)) { flags = ORC_TEST_FLAGS_FLOAT; } sprintf(s, "test_%s", opcode->name); orc_program_set_name (p, s); orc_program_append_2 (p, opcode->name, 0, args[0], args[1], args[2], args[3]); return p; } OrcProgram * orc_test_get_program_for_opcode_const (OrcStaticOpcode *opcode) { OrcProgram *p; char s[40]; int args[4] = { -1, -1, -1, -1 }; int flags ORC_GNUC_UNUSED; int n_args = 0; p = orc_program_new (); if (opcode->flags & ORC_STATIC_OPCODE_ACCUMULATOR) { args[n_args++] = orc_program_add_accumulator (p, opcode->dest_size[0], "d1"); } else { args[n_args++] = orc_program_add_destination (p, opcode->dest_size[0], "d1"); } if (opcode->dest_size[1] != 0) { args[n_args++] = orc_program_add_destination (p, opcode->dest_size[1], "d2"); } if (opcode->src_size[1] == 0) { args[n_args++] = orc_program_add_constant (p, opcode->src_size[0], 1, "c1"); } else { args[n_args++] = orc_program_add_source (p, opcode->src_size[0], "s1"); args[n_args++] = orc_program_add_constant (p, opcode->src_size[1], 1, "c1"); if (opcode->src_size[2]) { args[n_args++] = orc_program_add_constant (p, opcode->src_size[2], 1, "c2"); } } if ((opcode->flags & ORC_STATIC_OPCODE_FLOAT_SRC) || (opcode->flags & ORC_STATIC_OPCODE_FLOAT_DEST)) { flags = ORC_TEST_FLAGS_FLOAT; } sprintf(s, "test_const_%s", opcode->name); orc_program_set_name (p, s); orc_program_append_2 (p, opcode->name, 0, args[0], args[1], args[2], args[3]); return p; } OrcProgram * orc_test_get_program_for_opcode_param (OrcStaticOpcode *opcode) { OrcProgram *p; char s[40]; int args[4] = { -1, -1, -1, -1 }; int flags ORC_GNUC_UNUSED; int n_args = 0; if (opcode->src_size[1] == 0) { return NULL; } p = orc_program_new (); if (opcode->flags & ORC_STATIC_OPCODE_ACCUMULATOR) { args[n_args++] = orc_program_add_accumulator (p, opcode->dest_size[0], "d1"); } else { args[n_args++] = orc_program_add_destination (p, opcode->dest_size[0], "d1"); } if (opcode->dest_size[1] != 0) { args[n_args++] = orc_program_add_destination (p, opcode->dest_size[1], "d2"); } args[n_args++] = orc_program_add_source (p, opcode->src_size[0], "s1"); args[n_args++] = orc_program_add_parameter (p, opcode->src_size[1], "p1"); if (opcode->src_size[2]) { args[n_args++] = orc_program_add_parameter (p, opcode->src_size[2], "p2"); } if ((opcode->flags & ORC_STATIC_OPCODE_FLOAT_SRC) || (opcode->flags & ORC_STATIC_OPCODE_FLOAT_DEST)) { flags = ORC_TEST_FLAGS_FLOAT; } sprintf(s, "test_p_%s", opcode->name); orc_program_set_name (p, s); orc_program_append_2 (p, opcode->name, 0, args[0], args[1], args[2], args[3]); return p; } void orc_test_performance (OrcProgram *program, int flags) { orc_test_performance_full (program, flags, NULL); } double orc_test_performance_full (OrcProgram *program, int flags, const char *target_name) { OrcExecutor *ex; int n; int m; OrcArray *dest_exec[4] = { NULL, NULL, NULL, NULL }; OrcArray *dest_emul[4] = { NULL, NULL, NULL, NULL }; OrcArray *src[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int i, j; OrcCompileResult result; OrcProfile prof; double ave, std; OrcTarget *target; int misalignment; ORC_DEBUG ("got here"); target = orc_target_get_by_name (target_name); if (!(flags & ORC_TEST_FLAGS_BACKUP)) { unsigned int flags; flags = orc_target_get_default_flags (target); result = orc_program_compile_full (program, target, flags); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { //printf("compile failed\n"); orc_program_reset (program); return 0; } } if (program->constant_n > 0) { n = program->constant_n; } else { //n = 64 + (orc_random(&rand_context)&0xf); n = 1000; } ex = orc_executor_new (program); orc_executor_set_n (ex, n); if (program->is_2d) { if (program->constant_m > 0) { m = program->constant_m; } else { m = 8 + (orc_random(&rand_context)&0xf); } } else { m = 1; } orc_executor_set_m (ex, m); ORC_DEBUG("size %d %d", ex->n, ex->params[ORC_VAR_A1]); misalignment = 0; for(i=0;ivars[i].name == NULL) continue; if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { src[i-ORC_VAR_S1] = orc_array_new (n, m, program->vars[i].size, misalignment, program->vars[i].alignment); orc_array_set_random (src[i-ORC_VAR_S1], &rand_context); misalignment++; } else if (program->vars[i].vartype == ORC_VAR_TYPE_DEST) { dest_exec[i-ORC_VAR_D1] = orc_array_new (n, m, program->vars[i].size, misalignment, program->vars[i].alignment); orc_array_set_pattern (dest_exec[i], ORC_OOB_VALUE); dest_emul[i-ORC_VAR_D1] = orc_array_new (n, m, program->vars[i].size, misalignment, program->vars[i].alignment); orc_array_set_pattern (dest_emul[i], ORC_OOB_VALUE); misalignment++; } else if (program->vars[i].vartype == ORC_VAR_TYPE_PARAM) { orc_executor_set_param (ex, i, 2); } } ORC_DEBUG ("running"); orc_profile_init (&prof); for(i=0;i<10;i++){ orc_executor_set_n (ex, n); orc_executor_set_m (ex, m); for(j=0;jvars[j].vartype == ORC_VAR_TYPE_DEST) { orc_executor_set_array (ex, j, dest_exec[j-ORC_VAR_D1]->data); orc_executor_set_stride (ex, j, dest_exec[j-ORC_VAR_D1]->stride); } if (program->vars[j].vartype == ORC_VAR_TYPE_SRC) { orc_executor_set_array (ex, j, src[j-ORC_VAR_S1]->data); orc_executor_set_stride (ex, j, src[j-ORC_VAR_S1]->stride); } } if (flags & ORC_TEST_FLAGS_BACKUP) { orc_profile_start (&prof); orc_executor_run_backup (ex); orc_profile_stop (&prof); } else if (flags & ORC_TEST_FLAGS_EMULATE) { orc_profile_start (&prof); orc_executor_emulate (ex); orc_profile_stop (&prof); } else { orc_profile_start (&prof); orc_executor_run (ex); orc_profile_stop (&prof); } } ORC_DEBUG ("done running"); orc_profile_get_ave_std (&prof, &ave, &std); for(i=0;i<4;i++){ if (dest_exec[i]) orc_array_free (dest_exec[i]); if (dest_emul[i]) orc_array_free (dest_emul[i]); } for(i=0;i<8;i++){ if (src[i]) orc_array_free (src[i]); } orc_executor_free (ex); orc_program_reset (program); return ave/(n*m); } #define MIPS_PREFIX "mipsel-linux-gnu-" OrcTestResult orc_test_gcc_compile_mips (OrcProgram *p) { char cmd[300]; char *base; char source_filename[100]; char obj_filename[100]; char dis_filename[100]; char dump_filename[100]; char dump_dis_filename[100]; int ret; FILE *file; OrcCompileResult result; OrcTarget *target; unsigned int flags; base = "temp-orc-test"; sprintf(source_filename, "%s-source.s", base); sprintf(obj_filename, "%s.o", base); sprintf(dis_filename, "%s-source.dis", base); sprintf(dump_filename, "%s-dump.bin", base); sprintf(dump_dis_filename, "%s-dump.dis", base); target = orc_target_get_by_name ("mips"); flags = orc_target_get_default_flags (target); flags |= ORC_TARGET_CLEAN_COMPILE; result = orc_program_compile_full (p, target, flags); if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { //printf (" no code generated: %s\n", orc_program_get_error (p)); return ORC_TEST_INDETERMINATE; } fflush (stdout); file = fopen (source_filename, "w"); fprintf(file, "%s", orc_target_get_preamble (target)); fprintf(file, "%s", orc_program_get_asm_code (p)); fclose (file); file = fopen (dump_filename, "w"); ret = fwrite(p->orccode->code, p->orccode->code_size, 1, file); fclose (file); sprintf (cmd, MIPS_PREFIX "gcc -mips32r2 -mdspr2 -Wall " "-c %s -o %s", source_filename, obj_filename); ret = system (cmd); if (ret != 0) { ORC_ERROR ("mips gcc failed"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, MIPS_PREFIX "objdump -Dr -j .text %s >%s", obj_filename, dis_filename); ret = system (cmd); if (ret != 0) { ORC_ERROR ("objdump failed"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, MIPS_PREFIX "objcopy -I binary " "-O elf32-tradlittlemips -B mips:isa32r2 " "--rename-section .data=.text " "--redefine-sym _binary_temp_orc_test_dump_bin_start=%s " "%s %s", p->name, dump_filename, obj_filename); ret = system (cmd); if (ret != 0) { printf("objcopy failed\n"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, MIPS_PREFIX "objdump -Dr %s >%s", obj_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("objdump failed\n"); return ORC_TEST_INDETERMINATE; } sprintf (cmd, "diff -u %s %s", dis_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("diff failed\n"); return ORC_TEST_FAILED; } remove (source_filename); remove (obj_filename); remove (dis_filename); remove (dump_filename); remove (dump_dis_filename); return ORC_TEST_OK; }