|
From: <sv...@va...> - 2007-05-16 18:41:33
|
Author: sewardj
Date: 2007-05-16 19:41:27 +0100 (Wed, 16 May 2007)
New Revision: 6742
Log:
Another optimisation: allow tools to provide a final_tidy function
which they can use to mess with the final post-tree-built IR before it
is handed off to instruction selection.
In memcheck, use this to remove redundant calls to
MC_(helperc_value_check0_fail) et al. Gives a 6% reduction in code
size for Memcheck on x86 and a smaller (3% ?) speedup.
Modified:
branches/CGTUNE/cachegrind/cg_main.c
branches/CGTUNE/callgrind/main.c
branches/CGTUNE/coregrind/m_tooliface.c
branches/CGTUNE/coregrind/m_translate.c
branches/CGTUNE/coregrind/pub_core_tooliface.h
branches/CGTUNE/helgrind/hg_main.c
branches/CGTUNE/include/pub_tool_tooliface.h
branches/CGTUNE/lackey/lk_main.c
branches/CGTUNE/massif/ms_main.c
branches/CGTUNE/memcheck/mc_include.h
branches/CGTUNE/memcheck/mc_main.c
branches/CGTUNE/memcheck/mc_translate.c
branches/CGTUNE/none/nl_main.c
Modified: branches/CGTUNE/cachegrind/cg_main.c
===================================================================
--- branches/CGTUNE/cachegrind/cg_main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/cachegrind/cg_main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -1362,6 +1362,7 @@
VG_(basic_tool_funcs) (cg_post_clo_init,
cg_instrument,
+ NULL,
cg_fini);
VG_(needs_superblock_discards)(cg_discard_superblock_info);
Modified: branches/CGTUNE/callgrind/main.c
===================================================================
--- branches/CGTUNE/callgrind/main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/callgrind/main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -1090,6 +1090,7 @@
VG_(basic_tool_funcs) (CLG_(post_clo_init),
CLG_(instrument),
+ NULL,
CLG_(fini));
VG_(needs_superblock_discards)(clg_discard_superblock_info);
Modified: branches/CGTUNE/coregrind/m_tooliface.c
===================================================================
--- branches/CGTUNE/coregrind/m_tooliface.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/coregrind/m_tooliface.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -42,11 +42,13 @@
void(*post_clo_init)(void),
IRSB*(*instrument)(VgCallbackClosure*, IRSB*,
VexGuestLayout*, VexGuestExtents*, IRType, IRType),
+ IRSB*(*final_tidy)(IRSB*),
void(*fini)(Int)
)
{
VG_(tdict).tool_post_clo_init = post_clo_init;
VG_(tdict).tool_instrument = instrument;
+ VG_(tdict).final_tidy = final_tidy;
VG_(tdict).tool_fini = fini;
}
Modified: branches/CGTUNE/coregrind/m_translate.c
===================================================================
--- branches/CGTUNE/coregrind/m_translate.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/coregrind/m_translate.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -1287,6 +1287,7 @@
vta.instrument2 = need_to_handle_SP_assignment()
? vg_SP_update_pass
: NULL;
+ vta.finaltidy = VG_(tdict).final_tidy;
vta.do_self_check = do_self_check;
vta.traceflags = verbosity;
Modified: branches/CGTUNE/coregrind/pub_core_tooliface.h
===================================================================
--- branches/CGTUNE/coregrind/pub_core_tooliface.h 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/coregrind/pub_core_tooliface.h 2007-05-16 18:41:27 UTC (rev 6742)
@@ -109,6 +109,7 @@
IRSB*,
VexGuestLayout*, VexGuestExtents*,
IRType, IRType);
+ IRSB* (*final_tidy) (IRSB*);
void (*tool_fini) (Int);
// VG_(needs).core_errors
Modified: branches/CGTUNE/helgrind/hg_main.c
===================================================================
--- branches/CGTUNE/helgrind/hg_main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/helgrind/hg_main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -3389,6 +3389,7 @@
VG_(basic_tool_funcs) (hg_post_clo_init,
hg_instrument,
+ NULL,
hg_fini);
VG_(printf)(
Modified: branches/CGTUNE/include/pub_tool_tooliface.h
===================================================================
--- branches/CGTUNE/include/pub_tool_tooliface.h 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/include/pub_tool_tooliface.h 2007-05-16 18:41:27 UTC (rev 6742)
@@ -239,6 +239,8 @@
IRType gWordTy,
IRType hWordTy),
+ IRSB*(*final_tidy)(IRSB*),
+
// Finish up, print out any results, etc. `exitcode' is program's exit
// code. The shadow can be found with VG_(get_exit_status_shadow)().
void (*fini)(Int)
Modified: branches/CGTUNE/lackey/lk_main.c
===================================================================
--- branches/CGTUNE/lackey/lk_main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/lackey/lk_main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -919,6 +919,7 @@
VG_(basic_tool_funcs) (lk_post_clo_init,
lk_instrument,
+ NULL,
lk_fini);
VG_(needs_command_line_options)(lk_process_cmd_line_option,
lk_print_usage,
Modified: branches/CGTUNE/massif/ms_main.c
===================================================================
--- branches/CGTUNE/massif/ms_main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/massif/ms_main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -1729,6 +1729,7 @@
// Basic functions
VG_(basic_tool_funcs) (ms_post_clo_init,
ms_instrument,
+ NULL,
ms_fini);
// Needs
Modified: branches/CGTUNE/memcheck/mc_include.h
===================================================================
--- branches/CGTUNE/memcheck/mc_include.h 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/memcheck/mc_include.h 2007-05-16 18:41:27 UTC (rev 6742)
@@ -320,6 +320,9 @@
VexGuestExtents* vge,
IRType gWordTy, IRType hWordTy );
+extern
+IRSB* MC_(final_tidy) ( IRSB* );
+
#endif /* ndef __MC_INCLUDE_H */
/*--------------------------------------------------------------------*/
Modified: branches/CGTUNE/memcheck/mc_main.c
===================================================================
--- branches/CGTUNE/memcheck/mc_main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/memcheck/mc_main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -4967,6 +4967,7 @@
VG_(basic_tool_funcs) (mc_post_clo_init,
MC_(instrument),
+ MC_(final_tidy),
mc_fini);
VG_(needs_core_errors) ();
Modified: branches/CGTUNE/memcheck/mc_translate.c
===================================================================
--- branches/CGTUNE/memcheck/mc_translate.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/memcheck/mc_translate.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -37,6 +37,9 @@
#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry)
#include "mc_include.h"
+#include "pub_tool_xarray.h"
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_libcbase.h"
/* This file implements the Memcheck instrumentation, and in
particular contains the core of its undefined value detection
@@ -3468,6 +3471,132 @@
return bb;
}
+/*------------------------------------------------------------*/
+/*--- Post-tree-build final tidying ---*/
+/*------------------------------------------------------------*/
+
+/* This exploits the observation that Memcheck often produces
+ repeated conditional calls of the form
+
+ Dirty G MC_(helperc_value_check0/1/4/8_fail)()
+
+ with the same guard expression G guarding the same helper call.
+ The second and subsequent calls are redundant. This usually
+ results from instrumentation of guest code containing multiple
+ memory references at different constant offsets from the same base
+ register. After optimisation of the instrumentation, you get a
+ test for the definedness of the base register for each memory
+ reference, which is kinda pointless. MC_(final_tidy) therefore
+ looks for such repeated calls and removes all but the first. */
+
+/* A struct for recording which (helper, guard) pairs we have already
+ seen. */
+typedef
+ struct { void* entry; IRExpr* guard; }
+ Pair;
+
+/* Return True if e1 and e2 definitely denote the same value (used to
+ compare guards). Return False if unknown; False is the safe
+ answer. Since guest registers and guest memory do not have the
+ SSA property we must return False if any Gets or Loads appear in
+ the expression. */
+
+static Bool sameIRValue ( IRExpr* e1, IRExpr* e2 )
+{
+ if (e1->tag != e2->tag)
+ return False;
+ switch (e1->tag) {
+ case Iex_Const:
+ return eqIRConst( e1->Iex.Const.con, e2->Iex.Const.con );
+ case Iex_Binop:
+ return e1->Iex.Binop.op == e2->Iex.Binop.op
+ && sameIRValue(e1->Iex.Binop.arg1, e2->Iex.Binop.arg1)
+ && sameIRValue(e1->Iex.Binop.arg2, e2->Iex.Binop.arg2);
+ case Iex_Unop:
+ return e1->Iex.Unop.op == e2->Iex.Unop.op
+ && sameIRValue(e1->Iex.Unop.arg, e2->Iex.Unop.arg);
+ case Iex_RdTmp:
+ return e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp;
+ case Iex_Get:
+ return False; /* be conservative */
+ default:
+ VG_(printf)("mc_translate.c: sameIRValue: unhandled: ");
+ ppIRExpr(e1);
+ VG_(printf)("\n");
+ return False;
+ }
+}
+
+/* See if 'pairs' already has an entry for (entry, guard). Return
+ True if so. If not, add an entry. */
+
+static
+Bool check_or_add ( XArray* /*of Pair*/ pairs, IRExpr* guard, void* entry )
+{
+ Pair p;
+ Pair* pp;
+ Int i, n = VG_(sizeXA)( pairs );
+ for (i = 0; i < n; i++) {
+ pp = VG_(indexXA)( pairs, i );
+ if (pp->entry == entry && sameIRValue(pp->guard, guard))
+ return True;
+ }
+ p.guard = guard;
+ p.entry = entry;
+ VG_(addToXA)( pairs, &p );
+ return False;
+}
+
+static Bool is_helperc_value_checkN_fail ( HChar* name )
+{
+ return
+ 0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail)")
+ || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail)")
+ || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail)")
+ || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail)");
+}
+
+IRSB* MC_(final_tidy) ( IRSB* sb_in )
+{
+ Int i;
+ IRStmt* st;
+ IRDirty* di;
+ IRExpr* guard;
+ IRCallee* cee;
+ Bool alreadyPresent;
+ XArray* pairs = VG_(newXA)( VG_(malloc), VG_(free), sizeof(Pair) );
+ /* Scan forwards through the statements. Each time a call to one
+ of the relevant helpers is seen, check if we have made a
+ previous call to the same helper using the same guard
+ expression, and if so, delete the call. */
+ for (i = 0; i < sb_in->stmts_used; i++) {
+ st = sb_in->stmts[i];
+ tl_assert(st);
+ if (st->tag != Ist_Dirty)
+ continue;
+ di = st->Ist.Dirty.details;
+ guard = di->guard;
+ if (!guard)
+ continue;
+ if (0) { ppIRExpr(guard); VG_(printf)("\n"); }
+ cee = di->cee;
+ if (!is_helperc_value_checkN_fail( cee->name ))
+ continue;
+ /* Ok, we have a call to helperc_value_check0/1/4/8_fail with
+ guard 'guard'. Check if we have already seen a call to this
+ function with the same guard. If so, delete it. If not,
+ add it to the set of calls we do know about. */
+ alreadyPresent = check_or_add( pairs, guard, cee->addr );
+ if (alreadyPresent) {
+ sb_in->stmts[i] = IRStmt_NoOp();
+ if (0) VG_(printf)("XX\n");
+ }
+ }
+ VG_(deleteXA)( pairs );
+ return sb_in;
+}
+
+
/*--------------------------------------------------------------------*/
/*--- end mc_translate.c ---*/
/*--------------------------------------------------------------------*/
Modified: branches/CGTUNE/none/nl_main.c
===================================================================
--- branches/CGTUNE/none/nl_main.c 2007-05-15 03:59:23 UTC (rev 6741)
+++ branches/CGTUNE/none/nl_main.c 2007-05-16 18:41:27 UTC (rev 6742)
@@ -60,6 +60,7 @@
VG_(basic_tool_funcs) (nl_post_clo_init,
nl_instrument,
+ NULL,
nl_fini);
/* No needs, no core events to track */
|