|
From: <sv...@va...> - 2012-12-21 10:34:20
|
sewardj 2012-12-21 10:34:08 +0000 (Fri, 21 Dec 2012)
New Revision: 13194
Log:
Teach Cachegrind about IRLoadG and IRStoreG.
Modified files:
branches/COMEM/cachegrind/cg_main.c
Modified: branches/COMEM/cachegrind/cg_main.c (+80 -4)
===================================================================
--- branches/COMEM/cachegrind/cg_main.c 2012-12-21 04:25:10 +00:00 (rev 13193)
+++ branches/COMEM/cachegrind/cg_main.c 2012-12-21 10:34:08 +00:00 (rev 13194)
@@ -419,6 +419,9 @@
n->parent->Dw.a++;
}
+/* Note that addEvent_D_guarded assumes that log_0Ir_1Dr_cache_access
+ and log_0Ir_1Dw_cache_access have exactly the same prototype. If
+ you change them, you must change addEvent_D_guarded too. */
static VG_REGPARM(3)
void log_0Ir_1Dr_cache_access(InstrInfo* n, Addr data_addr, Word data_size)
{
@@ -429,6 +432,7 @@
n->parent->Dr.a++;
}
+/* See comment on log_0Ir_1Dr_cache_access. */
static VG_REGPARM(3)
void log_0Ir_1Dw_cache_access(InstrInfo* n, Addr data_addr, Word data_size)
{
@@ -930,10 +934,10 @@
/* Is it possible to merge this write with the preceding read? */
lastEvt = &cgs->events[cgs->events_used-1];
if (cgs->events_used > 0
- && lastEvt->tag == Ev_Dr
- && lastEvt->Ev.Dr.szB == datasize
- && lastEvt->inode == inode
- && eqIRAtom(lastEvt->Ev.Dr.ea, ea))
+ && lastEvt->tag == Ev_Dr
+ && lastEvt->Ev.Dr.szB == datasize
+ && lastEvt->inode == inode
+ && eqIRAtom(lastEvt->Ev.Dr.ea, ea))
{
lastEvt->tag = Ev_Dm;
return;
@@ -953,6 +957,52 @@
}
static
+void addEvent_D_guarded ( CgState* cgs, InstrInfo* inode,
+ Int datasize, IRAtom* ea, IRAtom* guard,
+ Bool isWrite )
+{
+ tl_assert(isIRAtom(ea));
+ tl_assert(guard);
+ tl_assert(isIRAtom(guard));
+ tl_assert(datasize >= 1 && datasize <= min_line_size);
+
+ if (!clo_cache_sim)
+ return;
+
+ /* Adding guarded memory actions and merging them with the existing
+ queue is too complex. Simply flush the queue and add this
+ action immediately. Since guarded loads and stores are pretty
+ rare, this is not thought likely to cause any noticeable
+ performance loss as a result of the loss of event-merging
+ opportunities. */
+ tl_assert(cgs->events_used >= 0);
+ flushEvents(cgs);
+ tl_assert(cgs->events_used == 0);
+ /* Same as case Ev_Dw / case Ev_Dr in flushEvents, except with guard */
+ IRExpr* i_node_expr;
+ const HChar* helperName;
+ void* helperAddr;
+ IRExpr** argv;
+ Int regparms;
+ IRDirty* di;
+ i_node_expr = mkIRExpr_HWord( (HWord)inode );
+ helperName = isWrite ? "log_0Ir_1Dw_cache_access"
+ : "log_0Ir_1Dr_cache_access";
+ helperAddr = isWrite ? &log_0Ir_1Dw_cache_access
+ : &log_0Ir_1Dr_cache_access;
+ argv = mkIRExprVec_3( i_node_expr,
+ ea, mkIRExpr_HWord( datasize ) );
+ regparms = 3;
+ di = unsafeIRDirty_0_N(
+ regparms,
+ helperName, VG_(fnptr_to_fnentry)( helperAddr ),
+ argv );
+ di->guard = guard;
+ addStmtToIRSB( cgs->sbOut, IRStmt_Dirty(di) );
+}
+
+
+static
void addEvent_Bc ( CgState* cgs, InstrInfo* inode, IRAtom* guard )
{
Event* evt;
@@ -1101,6 +1151,31 @@
break;
}
+ case Ist_StoreG: {
+ IRStoreG* sg = st->Ist.StoreG.details;
+ IRExpr* data = sg->data;
+ IRExpr* addr = sg->addr;
+ IRType type = typeOfIRExpr(tyenv, data);
+ tl_assert(type != Ity_INVALID);
+ addEvent_D_guarded( &cgs, curr_inode,
+ sizeofIRType(type), addr, sg->guard,
+ True/*isWrite*/ );
+ break;
+ }
+
+ case Ist_LoadG: {
+ IRLoadG* lg = st->Ist.LoadG.details;
+ IRType type = Ity_INVALID; /* loaded type */
+ IRType typeWide = Ity_INVALID; /* after implicit widening */
+ IRExpr* addr = lg->addr;
+ typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
+ tl_assert(type != Ity_INVALID);
+ addEvent_D_guarded( &cgs, curr_inode,
+ sizeofIRType(type), addr, lg->guard,
+ False/*!isWrite*/ );
+ break;
+ }
+
case Ist_Dirty: {
Int dataSize;
IRDirty* d = st->Ist.Dirty.details;
@@ -1231,6 +1306,7 @@
}
default:
+ ppIRStmt(st);
tl_assert(0);
break;
}
|