Index: callgrind/main.c =================================================================== --- callgrind/main.c (revision 12824) +++ callgrind/main.c (working copy) @@ -1889,9 +1889,29 @@ static void CLG_(post_clo_init)(void) { - VG_(clo_vex_control).iropt_unroll_thresh = 0; - VG_(clo_vex_control).guest_chase_thresh = 0; + if (VG_(clo_vex_control).iropt_register_updates + != VexRegUpdAllregsAtSBExits) { + CLG_DEBUG(1, " Using user specified value for " + "--vex-iropt-register-updates\n"); + } else { + CLG_DEBUG(1, + " Using default --vex-iropt-register-updates=" + "allregs-at-sb-exits\n"); + } + if (VG_(clo_vex_control).iropt_unroll_thresh != 0) { + VG_(message)(Vg_UserMsg, + "callgrind only works with --vex-iropt-unroll-thresh=0\n" + "=> resetting it back to 0\n"); + VG_(clo_vex_control).iropt_unroll_thresh = 0; // cannot be overriden. + } + if (VG_(clo_vex_control).guest_chase_thresh != 0) { + VG_(message)(Vg_UserMsg, + "callgrind only works with --vex-guest-chase-thresh=0\n" + "=> resetting it back to 0\n"); + VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden. + } + CLG_DEBUG(1, " dump threads: %s\n", CLG_(clo).separate_threads ? "Yes":"No"); CLG_DEBUG(1, " call sep. : %d\n", CLG_(clo).separate_callers); CLG_DEBUG(1, " rec. sep. : %d\n", CLG_(clo).separate_recursions); @@ -1936,6 +1956,11 @@ VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 500 ); + VG_(clo_vex_control).iropt_register_updates + = VexRegUpdAllregsAtSBExits; // overridable by the user. + VG_(clo_vex_control).iropt_unroll_thresh = 0; // cannot be overriden. + VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden. + VG_(basic_tool_funcs) (CLG_(post_clo_init), CLG_(instrument), CLG_(fini)); Index: NEWS =================================================================== --- NEWS (revision 12824) +++ NEWS (working copy) @@ -90,12 +90,16 @@ * Option --vex-iropt-precise-memory-exns has been removed. It is replaced by --vex-iropt-register-updates which accepts - 3 values : 'unwindregs-at-mem-access' (replacing - --vex-iropt-precise-memory-exns=no), 'allregs-at-mem-access' - (replacing --vex-iropt-precise-memory-exns=yes) - and a new value 'allregs-at-each-insn'. + 4 values : + 'allregs-at-sb-exits' (new value) + 'unwindregs-at-mem-access' (replacing --vex-iropt-precise-memory-exns=no) + 'allregs-at-mem-access' (replacing --vex-iropt-precise-memory-exns=yes) + 'allregs-at-each-insn' (new value) 'allregs-at-each-insn' allows the Valgrind gdbserver to always show up to date values to GDB. + 'allregs-at-sb-exits' is the default value for callgrind and cachegrind, + giving (slightly) better performance than the previous default value + of --vex-iropt-precise-memory-exns=no. * ==================== FIXED BUGS ==================== Index: cachegrind/cg_main.c =================================================================== --- cachegrind/cg_main.c (revision 12824) +++ cachegrind/cg_main.c (working copy) @@ -1695,6 +1695,8 @@ VG_(details_bug_reports_to) (VG_BUGS_TO); VG_(details_avg_translation_sizeB) ( 500 ); + VG_(clo_vex_control).iropt_register_updates + = VexRegUpdAllregsAtSBExits; // overridable by the user. VG_(basic_tool_funcs) (cg_post_clo_init, cg_instrument, cg_fini); Index: none/tests/cmdline2.stdout.exp =================================================================== --- none/tests/cmdline2.stdout.exp (revision 12824) +++ none/tests/cmdline2.stdout.exp (working copy) @@ -117,7 +117,8 @@ Vex options for all Valgrind tools: --vex-iropt-verbosity=<0..9> [0] --vex-iropt-level=<0..2> [2] - --vex-iropt-register-updates=unwindregs-at-mem-access + --vex-iropt-register-updates=allregs-at-sb-exits + |unwindregs-at-mem-access |allregs-at-mem-access |allregs-at-each-insn [unwindregs-at-mem-access] --vex-iropt-unroll-thresh=<0..400> [120] Index: coregrind/m_main.c =================================================================== --- coregrind/m_main.c (revision 12824) +++ coregrind/m_main.c (working copy) @@ -228,7 +228,8 @@ " Vex options for all Valgrind tools:\n" " --vex-iropt-verbosity=<0..9> [0]\n" " --vex-iropt-level=<0..2> [2]\n" -" --vex-iropt-register-updates=unwindregs-at-mem-access\n" +" --vex-iropt-register-updates=allregs-at-sb-exits\n" +" |unwindregs-at-mem-access\n" " |allregs-at-mem-access\n" " |allregs-at-each-insn [unwindregs-at-mem-access]\n" " --vex-iropt-unroll-thresh=<0..400> [120]\n" @@ -605,6 +606,10 @@ else if VG_BINT_CLO(arg, "--vex-iropt-level", VG_(clo_vex_control).iropt_level, 0, 2) {} else if VG_XACT_CLO(arg, + "--vex-iropt-register-updates=allregs-at-sb-exits", + VG_(clo_vex_control).iropt_register_updates, + VexRegUpdAllregsAtSBExits); + else if VG_XACT_CLO(arg, "--vex-iropt-register-updates=unwindregs-at-mem-access", VG_(clo_vex_control).iropt_register_updates, VexRegUpdUnwindregsAtMemAccess); Index: VEX/priv/ir_opt.c =================================================================== --- VEX/priv/ir_opt.c (revision 2457) +++ VEX/priv/ir_opt.c (working copy) @@ -69,6 +69,10 @@ not marked as being read or modified by the helper cannot be assumed to be up-to-date at the point where the helper is called. + * If iropt_register_updates == VexRegUpdAllregsAtSBExits : + The guest state is only up to date only as explained above + (i.e. at SB exits and as specified by dirty helper call). + * If iropt_register_updates == VexRegUpdUnwindregsAtMemAccess : Immediately prior to any load or store, those parts of the guest state marked as requiring precise exceptions will be up to date. @@ -778,11 +782,15 @@ } if (memRW) { - /* This statement accesses memory. So we need to dump all parts + /* This statement accesses memory. So we might need to dump all parts of the environment corresponding to guest state that may not be reordered with respect to memory references. That means at least the stack pointer. */ switch (vex_control.iropt_register_updates) { + case VexRegUpdAllregsAtSBExits: + /* Nothing to dump. It is only at SB exits that + we need to flush guest state. */ + break; case VexRegUpdAllregsAtMemAccess: /* Precise exceptions required at mem access. Flush all guest state. */ @@ -837,9 +845,7 @@ IRStmt* st; UInt key = 0; /* keep gcc -O happy */ - vassert - (vex_control.iropt_register_updates == VexRegUpdUnwindregsAtMemAccess - || vex_control.iropt_register_updates == VexRegUpdAllregsAtMemAccess); + vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn); HashHW* env = newHHW(); @@ -3958,9 +3964,7 @@ Bool delete; IRStmt *st, *stj; - vassert - (vex_control.iropt_register_updates == VexRegUpdUnwindregsAtMemAccess - || vex_control.iropt_register_updates == VexRegUpdAllregsAtMemAccess); + vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn); for (i = 0; i < bb->stmts_used; i++) { st = bb->stmts[i]; @@ -5201,7 +5205,7 @@ ppIRSB(bb); } - if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) { + if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) { redundant_put_removal_BB ( bb, preciseMemExnsFn ); } if (iropt_verbose) { @@ -5241,7 +5245,7 @@ (void)do_cse_BB( bb ); collapse_AddSub_chains_BB( bb ); do_redundant_GetI_elimination( bb ); - if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) { + if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) { do_redundant_PutI_elimination( bb ); } do_deadcode_BB( bb ); @@ -5392,7 +5396,7 @@ work extra hard to get rid of it. */ bb = cprop_BB(bb); bb = spec_helpers_BB ( bb, specHelper ); - if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) { + if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) { redundant_put_removal_BB ( bb, preciseMemExnsFn ); } do_cse_BB( bb ); Index: VEX/pub/libvex.h =================================================================== --- VEX/pub/libvex.h (revision 2457) +++ VEX/pub/libvex.h (working copy) @@ -311,6 +311,9 @@ /* VexRegisterUpdates specifies when to ensure that the guest state is up to date. + VexRegUpdAllregsAtSBExits : all registers are updated at superblock + exits. + VexRegUpdUnwindregsAtMemAccess : registers needed to make a stack trace are up to date at memory exception points. Typically, these are PC/SP/FP. The minimal registers are described by the arch specific functions @@ -320,7 +323,8 @@ points. VexRegUpdAllregsAtEachInsn : all registers up to date at each instruction. */ -typedef enum { VexRegUpdUnwindregsAtMemAccess, +typedef enum { VexRegUpdAllregsAtSBExits, + VexRegUpdUnwindregsAtMemAccess, VexRegUpdAllregsAtMemAccess, VexRegUpdAllregsAtEachInsn } VexRegisterUpdates;