From: Julian Seward Date: Mon, 25 Oct 2004 13:01:45 +0000 (+0000) Subject: Add run-time controllability to iropt. X-Git-Tag: svn/VALGRIND_3_0_1^2~914 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d258f4458f1265f1ce5f1de707ed5dbe6bfa51f;p=thirdparty%2Fvalgrind.git Add run-time controllability to iropt. git-svn-id: svn://svn.valgrind.org/vex/trunk@420 --- diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 817a5c243c..41272fed8d 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -37,9 +37,6 @@ #include "guest-x86/gdefs.h" -#define RESTEER_THRESH 10 - - /*------------------------------------------------------------*/ /*--- Globals ---*/ /*------------------------------------------------------------*/ @@ -133,7 +130,12 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, DisResult dres; static Int n_resteers = 0; Int d_resteers = 0; - Int resteerBelow = RESTEER_THRESH; /* the threshold value */ + + /* check sanity .. */ + vassert(vex_control.guest_max_insns >= 1); + vassert(vex_control.guest_max_insns < 1000); + vassert(vex_control.guest_chase_thresh >= 0); + vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns); /* Set up globals. */ host_is_bigendian = host_bigendian; @@ -142,14 +144,7 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, guest_eip_bbstart = (Addr32)guest_eip_start; irbb = emptyIRBB(); - if (vex_guest_insns_per_bb <= resteerBelow) - resteerBelow = vex_guest_insns_per_bb-1; - vassert((guest_eip_start >> 32) == 0); - vassert(vex_guest_insns_per_bb >= 1); - vassert(resteerBelow < vex_guest_insns_per_bb); - vassert(resteerBelow >= 0); - vassert(vex_guest_insns_per_bb); DIP("Original x86 code to IR:\n\n"); @@ -160,10 +155,10 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, *guest_bytes_read = 0; while (True) { - vassert(n_instrs < vex_guest_insns_per_bb); + vassert(n_instrs < vex_control.guest_max_insns); guest_next = 0; - resteerOK = n_instrs < resteerBelow; + resteerOK = n_instrs < vex_control.guest_chase_thresh; dres = disInstr( resteerOK, delta, &size, &guest_next ); delta += size; *guest_bytes_read += size; @@ -179,7 +174,7 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, switch (dres) { case Dis_Continue: vassert(irbb->next == NULL); - if (n_instrs < vex_guest_insns_per_bb) { + if (n_instrs < vex_control.guest_max_insns) { /* keep going */ } else { irbb->next = mkU32(((Addr32)guest_eip_start)+delta); diff --git a/VEX/priv/ir/iropt.c b/VEX/priv/ir/iropt.c index abd88f1099..ab478a0847 100644 --- a/VEX/priv/ir/iropt.c +++ b/VEX/priv/ir/iropt.c @@ -11,26 +11,13 @@ #include "libvex.h" #include "main/vex_util.h" +#include "main/vex_globals.h" #include "ir/iropt.h" -/* Possibly disable iropt for drastic debugging: - Set to 0 to completely disable iropt - 1 for simple optimisation - 2 for maximum optimisation (the default) */ -#define IROPT_LEVEL 2 /* Set to 1 for lots of debugging output. */ #define DEBUG_IROPT 0 -/* Controls the enthusiasm of the loop unroller. It tries to - unroll loops enough times to get somewhere near this number of SSA - statements, as measured after initial cleanup pass. Set to zero to - disable the unroller. */ -#define UNROLL_TARGET 120 - -/* Set to 1 to get details of loop unrolling. */ -#define UNROLL_VERBOSE 0 - /* Implementation notes, 12 Oct 04. @@ -770,7 +757,8 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st ) it is for now, since we'd have to truncate the BB at this point, which is tricky. */ /* fall out into the reconstruct-the-exit code. */ - if (UNROLL_VERBOSE) /* really a misuse of UNROLL_VERBOSE */ + if (vex_control.iropt_verbosity > 0) + /* really a misuse of vex_control.iropt_verbosity */ vex_printf("vex iropt: IRStmt_Exit became unconditional\n"); } } @@ -2852,27 +2840,27 @@ static Int calc_unroll_factor( IRBB* bb ) if (bb->stmts[i]) n_stmts++; - if (n_stmts <= UNROLL_TARGET/8) { - if (UNROLL_VERBOSE) + if (n_stmts <= vex_control.iropt_unroll_thresh/8) { + if (vex_control.iropt_verbosity > 0) vex_printf("vex iropt: 8 x unrolling (%d sts -> %d sts)\n", n_stmts, 8* n_stmts); return 8; } - if (n_stmts <= UNROLL_TARGET/4) { - if (UNROLL_VERBOSE) + if (n_stmts <= vex_control.iropt_unroll_thresh/4) { + if (vex_control.iropt_verbosity > 0) vex_printf("vex iropt: 4 x unrolling (%d sts -> %d sts)\n", n_stmts, 4* n_stmts); return 4; } - if (n_stmts <= UNROLL_TARGET/2) { - if (UNROLL_VERBOSE) + if (n_stmts <= vex_control.iropt_unroll_thresh/2) { + if (vex_control.iropt_verbosity > 0) vex_printf("vex iropt: 2 x unrolling (%d sts -> %d sts)\n", n_stmts, 2* n_stmts); return 2; } - if (UNROLL_VERBOSE) + if (vex_control.iropt_verbosity > 0) vex_printf("vex iropt: not unrolling (%d sts)\n", n_stmts); return 1; @@ -2890,7 +2878,7 @@ static IRBB* maybe_loop_unroll_BB ( IRBB* bb0, Addr64 my_addr ) IRBB *bb1, *bb2; Int unroll_factor; - if (UNROLL_TARGET <= 0) + if (vex_control.iropt_unroll_thresh <= 0) return NULL; /* First off, figure out if we can unroll this loop. Do this @@ -3193,7 +3181,7 @@ IRBB* do_iropt_BB ( IRBB* bb0, IRBB *bb, *bb2; /* Completely disable iropt? */ - if (IROPT_LEVEL <= 0) return bb0; + if (vex_control.iropt_level <= 0) return bb0; n_total++; @@ -3215,7 +3203,7 @@ IRBB* do_iropt_BB ( IRBB* bb0, bb = cheap_transformations( bb, specHelper ); - if (IROPT_LEVEL > 1) { + if (vex_control.iropt_level > 1) { do_expensive = hasGetIorPutI(bb); if (do_expensive) { n_expensive++; diff --git a/VEX/priv/main/vex_globals.c b/VEX/priv/main/vex_globals.c index 8407177ef1..1ab0866824 100644 --- a/VEX/priv/main/vex_globals.c +++ b/VEX/priv/main/vex_globals.c @@ -35,7 +35,7 @@ Int vex_verbosity = 0; Bool vex_valgrind_support = False; /* Max # guest insns per bb */ -Int vex_guest_insns_per_bb = 0; +VexControl vex_control = { 0,0,False,0,0,0 }; diff --git a/VEX/priv/main/vex_globals.h b/VEX/priv/main/vex_globals.h index 3f77d97a71..0c1417d6f4 100644 --- a/VEX/priv/main/vex_globals.h +++ b/VEX/priv/main/vex_globals.h @@ -10,6 +10,7 @@ #define __VEX_GLOBALS_H #include "libvex_basictypes.h" +#include "libvex.h" /* Global settings for the VEX library. These are the @@ -34,8 +35,8 @@ extern Int vex_verbosity; /* Are we supporting valgrind checking? */ extern Bool vex_valgrind_support; -/* Max # guest insns per bb */ -extern Int vex_guest_insns_per_bb; +/* Optimiser/front-end control */ +extern VexControl vex_control; #endif /* ndef __VEX_GLOBALS_H */ diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index b9a4bdede6..e04247a5bc 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -20,6 +20,19 @@ /* --------- Initialise the library. --------- */ +/* Exported to library client. */ + +void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon ) +{ + vcon->iropt_verbosity = 0; + vcon->iropt_level = 2; + vcon->iropt_precise_memory_exns = False; + vcon->iropt_unroll_thresh = 120; + vcon->guest_max_insns = 50; + vcon->guest_chase_thresh = 10; +} + + /* Exported to library client. */ void LibVEX_Init ( @@ -34,12 +47,12 @@ void LibVEX_Init ( Int verbosity, /* Are we supporting valgrind checking? */ Bool valgrind_support, - /* Max # guest insns per bb */ - Int guest_insns_per_bb + /* Control ... */ + /*READONLY*/VexControl* vcon ) { - /* First off, do enough minimal setup so that the follow asserts can - fail in a sane fashion, if need be. */ + /* First off, do enough minimal setup so that the following + assertions can fail in a sane fashion, if need be. */ vex_failure_exit = failure_exit; vex_log_bytes = log_bytes; @@ -49,7 +62,16 @@ void LibVEX_Init ( vassert(log_bytes); vassert(debuglevel >= 0); vassert(verbosity >= 0); - vassert(guest_insns_per_bb >= 1 && guest_insns_per_bb <= 100); + + vassert(vcon->iropt_verbosity >= 0); + vassert(vcon->iropt_level >= 0); + vassert(vcon->iropt_level <= 2); + vassert(vcon->iropt_unroll_thresh >= 0); + vassert(vcon->iropt_unroll_thresh <= 400); + vassert(vcon->guest_max_insns >= 1); + vassert(vcon->guest_max_insns <= 100); + vassert(vcon->guest_chase_thresh >= 0); + vassert(vcon->guest_chase_thresh < vcon->guest_max_insns); /* Check that Vex has been built with sizes of basic types as stated in priv/libvex_basictypes.h. Failure of any of these is @@ -79,7 +101,7 @@ void LibVEX_Init ( vex_debuglevel = debuglevel; vex_verbosity = verbosity; vex_valgrind_support = valgrind_support; - vex_guest_insns_per_bb = guest_insns_per_bb; + vex_control = *vcon; vex_initdone = True; LibVEX_SetAllocMode ( AllocModeTEMPORARY ); } diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 702a91b44f..60a889570a 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -19,6 +19,41 @@ /*---------------------------------------------------------------*/ +/* Control of Vex's optimiser. */ + +typedef + struct { + /* Controls verbosity of iropt. 0 = no output. */ + Int iropt_verbosity; + /* Control aggressiveness of iropt. 0 = no opt, 1 = simple + opts, 2 (default) = max optimisation. */ + Int iropt_level; + /* Ensure all integer registers are up to date at potential + memory exception points? True(default)=yes, False=no, only + the guest's stack pointer. */ + Bool iropt_precise_memory_exns; + /* How aggressive should iropt be in unrolling loops? Higher + numbers make it more enthusiastic about loop unrolling. + Default=120. A setting of zero disables unrolling. */ + Int iropt_unroll_thresh; + /* What's the maximum basic block length the front end(s) allow? + BBs longer than this are split up. Default=50 (guest + insns). */ + Int guest_max_insns; + /* How aggressive should front ends be in following + unconditional branches to known destinations? Default=10, + meaning that if a block contains less than 10 guest insns so + far, the front end(s) will attempt to chase into its + successor. A setting of zero disables chasing. */ + Int guest_chase_thresh; + } + VexControl; + + +/* Write the default settings into *vcon. */ +extern void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon ); + + /* Initialise the translator. */ extern void LibVEX_Init ( @@ -33,8 +68,8 @@ extern void LibVEX_Init ( Int verbosity, /* Are we supporting valgrind checking? */ Bool valgrind_support, - /* Max # guest insns per bb */ - Int guest_insns_per_bb + /* Control ... */ + /*READONLY*/VexControl* vcon );