]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Callgrind: event sets now consist of event groups
authorJosef Weidendorfer <Josef.Weidendorfer@gmx.de>
Wed, 9 Jun 2010 22:32:53 +0000 (22:32 +0000)
committerJosef Weidendorfer <Josef.Weidendorfer@gmx.de>
Wed, 9 Jun 2010 22:32:53 +0000 (22:32 +0000)
Offsets of groups within event sets are now
stored in a offset table as part of the event set, and
can be accessed directly. Before, offsets were hardcoded
all over the place. This should make addition of further
event groups much simpler.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11165

callgrind/bbcc.c
callgrind/debug.c
callgrind/events.c
callgrind/events.h
callgrind/global.h
callgrind/main.c
callgrind/sim.c

index ac7c21ed06adda5180dd60916660a55c682edc83..66d609cd69025fce1d9b669c23832845cc52b47b 100644 (file)
@@ -601,7 +601,7 @@ void CLG_(setup_bbcc)(BB* bb)
          if (!CLG_(clo).simulate_cache) {
              /* update Ir cost */
              int instr_count = last_bb->jmp[passed].instr+1;
-             CLG_(current_state).cost[CLG_(sets).off_full_Ir] += instr_count;
+             CLG_(current_state).cost[ fullOffset(EG_IR) ] += instr_count;
          }
       }
 
index b89b753613e06113de2ce680c06998edd68440dc..966aa747f35c16e356c6623d410ab6f49c3d1242 100644 (file)
@@ -137,40 +137,46 @@ void CLG_(print_bbcc)(int s, BBCC* bbcc)
 
 void CLG_(print_eventset)(int s, EventSet* es)
 {
-  int i;
+    int i, j;
+    UInt mask;
+    EventGroup* eg;
 
-  if (s<0) {
-    s = -s;
-    print_indent(s);
-  }
+    if (s<0) {
+       s = -s;
+       print_indent(s);
+    }
 
-  if (!es) {
-    VG_(printf)("(EventSet not set)\n");
-    return;
-  }
+    if (!es) {
+       VG_(printf)("(EventSet not set)\n");
+       return;
+    }
 
-  VG_(printf)("%5s (Size/Cap %d/%d): ",
-             es->name, es->size, es->capacity);
-
-  if (es->size == 0)
-    VG_(printf)("-");
-  else {
-    for(i=0; i< es->size; i++) {
-      if (i>0) {
-       VG_(printf)(" ");
-       if (es->e[i-1].nextTop == i)
-         VG_(printf)("| ");
-      }
-      VG_(printf)("%s", es->e[i].type->name);
+    VG_(printf)("EventSet %d (%d groups, size %d):",
+               es->mask, es->count, es->size);
+
+    if (es->count == 0) {
+       VG_(printf)("-\n");
+       return;
     }
-  }
-  VG_(printf)("\n");
+
+    for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
+       if ((es->mask & mask)==0) continue;
+       eg = CLG_(get_event_group)(i);
+       if (!eg) continue;
+       VG_(printf)(" (%d: %s", i, eg->name[0]);
+       for(j=1; j<eg->size; j++)
+           VG_(printf)(" %s", eg->name[j]);
+       VG_(printf)(")");
+    }
+    VG_(printf)("\n");
 }
 
 
 void CLG_(print_cost)(int s, EventSet* es, ULong* c)
 {
-  Int i, pos;
+    Int i, j, pos, off;
+    UInt mask;
+    EventGroup* eg;
 
     if (s<0) {
        s = -s;
@@ -182,29 +188,36 @@ void CLG_(print_cost)(int s, EventSet* es, ULong* c)
       return;
     }
     if (!c) {
-      VG_(printf)("Cost (Null, EventSet %s)\n", es->name);
+      VG_(printf)("Cost (Null, EventSet %d)\n", es->mask);
       return;
     }
 
     if (es->size == 0) {
-      VG_(printf)("Cost (Nothing, EventSet %s with len 0)\n", es->name);
+      VG_(printf)("Cost (Nothing, EventSet with len 0)\n");
       return;
     } 
 
     pos = s;
-    pos += VG_(printf)("Cost %s [%p]: %s %llu", es->name, c, es->e[0].type->name, c[0]);
-
-    i = 1;
-    while(i<es->size) {
-      if (pos > 70) {
-       VG_(printf)(",\n");
-       print_indent(s+5);
-       pos = s+5;
-      }
-      else
-       pos += VG_(printf)(", ");
-      pos += VG_(printf)("%s %llu", es->e[i].type->name, c[i]);
-      i++;
+    pos += VG_(printf)("Cost [%p]: ", c);
+    off = 0;
+    for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
+       if ((es->mask & mask)==0) continue;
+       eg = CLG_(get_event_group)(i);
+       if (!eg) continue;
+       for(j=0; j<eg->size; j++) {
+
+           if (off>0) {
+               if (pos > 70) {
+                   VG_(printf)(",\n");
+                   print_indent(s+5);
+                   pos = s+5;
+               }
+               else
+                   pos += VG_(printf)(", ");
+           }
+
+           pos += VG_(printf)("%s %llu", eg->name[j], c[off++]);
+       }
     }
     VG_(printf)("\n");
 }
@@ -213,13 +226,13 @@ void CLG_(print_cost)(int s, EventSet* es, ULong* c)
 void CLG_(print_short_jcc)(jCC* jcc)
 {
     if (jcc)
-       VG_(printf)("%#lx => %#lx [%llu/%llu,%llu,%llu]",
+       VG_(printf)("%#lx => %#lx [calls %llu/Ir %llu, Dr %llu, Dw %llu]",
                    bb_jmpaddr(jcc->from->bb),
                    bb_addr(jcc->to->bb),
                    jcc->call_counter,
-                   jcc->cost ? jcc->cost[CLG_(sets).off_full_Ir]:0,
-                   jcc->cost ? jcc->cost[CLG_(sets).off_full_Dr]:0,
-                   jcc->cost ? jcc->cost[CLG_(sets).off_full_Dw]:0);
+                   jcc->cost ? jcc->cost[fullOffset(EG_IR)]:0,
+                   jcc->cost ? jcc->cost[fullOffset(EG_DR)]:0,
+                   jcc->cost ? jcc->cost[fullOffset(EG_DW)]:0);
     else
        VG_(printf)("[Skipped JCC]");
 }
index c0654143e08d999474371d015ad938cf3f3045ea..fb5a77a380ab84a74ea69f290592fc3220d8ba0f 100644 (file)
 
 #include "global.h"
 
-#define MAX_EVENTTYPE 20
+/* This should be 2**MAX_EVENTGROUP_COUNT */
+#define MAX_EVENTSET_COUNT 1024
 
-static EventType eventtype[MAX_EVENTTYPE];
-static Int eventtype_count = 0;
+static EventGroup* eventGroup[MAX_EVENTGROUP_COUNT];
+static EventSet* eventSetTable[MAX_EVENTSET_COUNT];
+static Bool eventSets_initialized = 0;
 
-EventType* CLG_(register_eventtype)(Char* name)
+static
+void initialize_event_sets(void)
 {
-  EventType* et;
+    Int i;
 
-  if (eventtype_count == MAX_EVENTTYPE) {
-    VG_(printf)("\nMore than %d event types used!\n"
-               "Increase MAX_EVENTTYPE in ct_events.c and recomile this tool!\n",
-               MAX_EVENTTYPE);
-    VG_(tool_panic)("Too many event types requested.");
-  }
+    if (eventSets_initialized) return;
 
-  et = &(eventtype[eventtype_count]);
-  et->id = eventtype_count; 
-  et->name = (UChar*) VG_(strdup)("cl.events.re.1", name);
-  et->description = 0;
+    for(i=0; i< MAX_EVENTGROUP_COUNT; i++)
+       eventGroup[i] = 0;
 
-  eventtype_count++;
-
-  return et;
-}
+    for(i=0; i< MAX_EVENTSET_COUNT; i++)
+       eventSetTable[i] = 0;
 
+    eventSets_initialized = 1;
+ }
 
-EventType* CLG_(get_eventtype)(Char* name)
+static
+EventGroup* new_event_group(int id, int n)
 {
-  Int i;
+    EventGroup* eg;
+
+    initialize_event_sets();
 
-  for(i=0;i<eventtype_count;i++)
-    if (VG_(strcmp)(eventtype[i].name, name) == 0)
-      return eventtype+i;
-  return 0;
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+    CLG_ASSERT(eventGroup[id]==0);
+
+    eg = (EventGroup*) CLG_MALLOC("cl.events.group.1",
+                                 sizeof(EventGroup) + n * sizeof(Char*));
+    eg->size = n;
+    eventGroup[id] = eg;
+    return eg;
 }
 
-EventType* CLG_(get_eventtype_byindex)(Int id)
+EventGroup* CLG_(register_event_group) (int id, Char* n1)
 {
-  if ((id >= 0) && (id < eventtype_count))
-    return eventtype+id;
-  return 0;
+    EventGroup* eg = new_event_group(id, 1);
+    eg->name[0] = n1;
+
+    return eg;
 }
 
-/* Allocate space for an event set */
-EventSet* CLG_(get_eventset)(Char* n, Int capacity)
+EventGroup* CLG_(register_event_group2)(int id, Char* n1, Char* n2)
 {
-  EventSet* es;
+    EventGroup* eg = new_event_group(id, 2);
+    eg->name[0] = n1;
+    eg->name[1] = n2;
 
-  es = (EventSet*) CLG_MALLOC("cl.events.geSet.1",
-                               sizeof(EventSet) +
-                              capacity * sizeof(EventSetEntry));
-  es->capacity = capacity;
-  es->size = 0;
-  es->name = n;
-
-  return es;
+    return eg;
 }
 
-/* Incorporate a event type into a set, get start offset */
-Int CLG_(add_eventtype)(EventSet* es, EventType* t)
+EventGroup* CLG_(register_event_group3)(int id, Char* n1, Char* n2, Char* n3)
 {
-  Int offset = es->size;
-  if (es->capacity - offset < 1) return -1;
-
-  es->size++;
-  es->e[offset].type = t;
-  es->e[offset].nextTop = es->size;
+    EventGroup* eg = new_event_group(id, 3);
+    eg->name[0] = n1;
+    eg->name[1] = n2;
+    eg->name[2] = n3;
 
-  return offset;
+    return eg;
 }
 
-/* Incorporate one event set into another, get start offset */
-Int CLG_(add_eventset)(EventSet* dst, EventSet* src)
+EventGroup* CLG_(register_event_group4)(int id,
+                                       Char* n1, Char* n2, Char* n3, Char* n4)
 {
-  Int offset = dst->size, i;
-  if (!src || (src->size == 0)) return offset;
+    EventGroup* eg = new_event_group(id, 4);
+    eg->name[0] = n1;
+    eg->name[1] = n2;
+    eg->name[2] = n3;
+    eg->name[3] = n4;
 
-  if (dst->capacity - offset < src->size) return -1;
-  
-  for(i=0;i<src->size;i++) {
-    dst->e[offset+i].type = src->e[i].type;
-    dst->e[offset+i].nextTop = src->e[i].nextTop + offset;
-  }
-  dst->size += src->size;
+    return eg;
+}
 
-  return offset;
+EventGroup* CLG_(get_event_group)(int id)
+{
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+
+    return eventGroup[id];
 }
 
-/* Incorporate two event types into a set, with second < first */
-Int CLG_(add_dep_event2)(EventSet* es, EventType* e1, EventType* e2)
+
+static
+EventSet* eventset_from_mask(UInt mask)
 {
-  Int offset = es->size;
+    EventSet* es;
+    Int i, count, offset;
 
-  if (es->capacity - offset < 2) return -1;
+    if (mask >= MAX_EVENTSET_COUNT) return 0;
 
-  es->size += 2;
-  es->e[offset].type = e1;
-  es->e[offset].nextTop = es->size;
-  es->e[offset+1].type = e2;
-  es->e[offset+1].nextTop = es->size;
-  
-  return offset;
+    initialize_event_sets();
+    if (eventSetTable[mask]) return eventSetTable[mask];
+
+    es = (EventSet*) CLG_MALLOC("cl.events.eventset.1", sizeof(EventSet));
+    es->mask = mask;
+
+    offset = 0;
+    count = 0;
+    for(i=0;i<MAX_EVENTGROUP_COUNT;i++) {
+       es->offset[i] = offset;
+       if ( ((mask & (1u<<i))==0) || (eventGroup[i]==0))
+           continue;
+
+       offset += eventGroup[i]->size;
+       count++;
+    }
+    es->size = offset;
+    es->count = count;
+
+    eventSetTable[mask] = es;
+    return es;
 }
 
-/* Incorporate 3 event types into a set, with third < second < first */
-Int CLG_(add_dep_event3)(EventSet* es,
-                       EventType* e1, EventType* e2, EventType* e3)
+EventSet* CLG_(get_event_set)(Int id)
 {
-  Int offset = es->size;
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+    return eventset_from_mask(1u << id);
+}
 
-  if (es->capacity - offset < 3) return -1;
+EventSet* CLG_(get_event_set2)(Int id1, Int id2)
+{
+    CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
+    CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
+    return eventset_from_mask((1u << id1) | (1u << id2));
+}
 
-  es->size += 3;
-  es->e[offset].type = e1;
-  es->e[offset].nextTop = es->size;
-  es->e[offset+1].type = e2;
-  es->e[offset+1].nextTop = es->size;
-  es->e[offset+2].type = e3;
-  es->e[offset+2].nextTop = es->size;
-  
-  return offset;
+EventSet* CLG_(get_event_set3)(Int id1, Int id2, Int id3)
+{
+    CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
+    CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
+    CLG_ASSERT(id3>=0 && id3<MAX_EVENTGROUP_COUNT);
+    return eventset_from_mask((1u << id1) | (1u << id2) | (1u << id3));
 }
 
-Int CLG_(add_dep_event4)(EventSet* es,
-                       EventType* e1, EventType* e2,
-                       EventType* e3, EventType* e4)
+EventSet* CLG_(add_event_group)(EventSet* es, Int id)
 {
-  Int offset = es->size;
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+    if (!es) es = eventset_from_mask(0);
+    return eventset_from_mask(es->mask | (1u << id));
+}
 
-  if (es->capacity - offset < 4) return -1;
+EventSet* CLG_(add_event_group2)(EventSet* es, Int id1, Int id2)
+{
+    CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
+    CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
+    if (!es) es = eventset_from_mask(0);
+    return eventset_from_mask(es->mask | (1u << id1) | (1u << id2));
+}
 
-  es->size += 4;
-  es->e[offset].type = e1;
-  es->e[offset].nextTop = es->size;
-  es->e[offset+1].type = e2;
-  es->e[offset+1].nextTop = es->size;
-  es->e[offset+2].type = e3;
-  es->e[offset+2].nextTop = es->size;
-  es->e[offset+3].type = e4;
-  es->e[offset+3].nextTop = es->size;
-  
-  return offset;
+EventSet* CLG_(add_event_set)(EventSet* es1, EventSet* es2)
+{
+    if (!es1) es1 = eventset_from_mask(0);
+    if (!es2) es2 = eventset_from_mask(0);
+    return eventset_from_mask(es1->mask | es2->mask);
 }
 
-/* Returns number of characters written */
 Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
 {
-  Int i, pos = 0;
-
-  for(i=0; i< es->size; i++) {
-    if (pos>0) buf[pos++] = ' ';
-    pos += VG_(sprintf)(buf + pos, "%s", es->e[i].type->name);
-  }
-  buf[pos] = 0;
+    Int i, j, pos;
+    UInt mask;
+    EventGroup* eg;
+
+
+    CLG_ASSERT(es->size >0);
+    pos = 0;
+    for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
+       if ((es->mask & mask)==0) continue;
+       if (eventGroup[i] ==0) continue;
+
+       eg = eventGroup[i];
+       for(j=0; j<eg->size; j++) {
+           if (pos>0) buf[pos++] = ' ';
+           pos += VG_(sprintf)(buf + pos, "%s", eg->name[j]);
+       }
+    }
+    buf[pos] = 0;
 
-  return pos;
+    return pos;
 }
 
+
 /* Get cost array for an event set */
 ULong* CLG_(get_eventset_cost)(EventSet* es)
 {
-  return CLG_(get_costarray)(es->capacity);
+    return CLG_(get_costarray)(es->size);
 }
 
 /* Set all costs of an event set to zero */
 void CLG_(init_cost)(EventSet* es, ULong* cost)
 {
-  Int i;
+    Int i;
 
-  if (!cost) return;
+    if (!cost) return;
 
-  for(i=0;i<es->capacity;i++)
-    cost[i] = 0;
+    for(i=0; i<es->size; i++)
+       cost[i] = 0;
 }
 
 /* Set all costs of an event set to zero */
 void CLG_(init_cost_lz)(EventSet* es, ULong** cost)
 {
-  Int i;
+    Int i;
 
-  CLG_ASSERT(cost != 0);
-  if (!(*cost))
-    *cost = CLG_(get_eventset_cost)(es);
+    CLG_ASSERT(cost != 0);
+    if (!(*cost))
+       *cost = CLG_(get_eventset_cost)(es);
 
-  for(i=0;i<es->capacity;i++)
-    (*cost)[i] = 0;
+    for(i=0; i<es->size; i++)
+       (*cost)[i] = 0;
 }
 
 void CLG_(zero_cost)(EventSet* es, ULong* cost)
 {
-  Int i;
+    Int i;
 
-  if (!cost) return;
+    if (!cost) return;
 
-  for(i=0;i<es->size;i++)
-    cost[i] = 0;
+    for(i=0;i<es->size;i++)
+       cost[i] = 0;
 }
   
 Bool CLG_(is_zero_cost)(EventSet* es, ULong* cost)
 {
-  Int i = 0;
+    Int i;
 
-  if (!cost) return True;
+    if (!cost) return True;
 
-  while(i<es->size) {
-    if (cost[i] != 0) return False;
-    i = es->e[i].nextTop;
-  }
-  return True;
+    for(i=0; i<es->size; i++)
+       if (cost[i] != 0) return False;
+
+    return True;
 }
 
 Bool CLG_(is_equal_cost)(EventSet* es, ULong* c1, ULong* c2)
 {
-  Int i = 0;
+    Int i;
 
-  if (!c1) return CLG_(is_zero_cost)(es,c2);
-  if (!c2) return CLG_(is_zero_cost)(es,c1);
+    if (!c1) return CLG_(is_zero_cost)(es, c2);
+    if (!c2) return CLG_(is_zero_cost)(es, c1);
 
-  while(i<es->size) {
-    if (c1[i] != c2[i]) return False;
-    if (c1[i] == 0)
-      i = es->e[i].nextTop;
-    else
-      i++;
-  }
-  return True;
+    for(i=0; i<es->size; i++)
+       if (c1[i] != c2[i]) return False;
+
+    return True;
 }
 
 void CLG_(copy_cost)(EventSet* es, ULong* dst, ULong* src)
 {
-  Int i;
+    Int i;
 
-  if (!src) {
-    CLG_(zero_cost)(es, dst);
-    return;
-  }
-  CLG_ASSERT(dst != 0);
+    if (!src) {
+       CLG_(zero_cost)(es, dst);
+       return;
+    }
+    CLG_ASSERT(dst != 0);
   
-  for(i=0;i<es->size;i++)
-    dst[i] = src[i];
+    for(i=0;i<es->size;i++)
+       dst[i] = src[i];
 }
 
 void CLG_(copy_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
 {
-  Int i;
-  ULong* dst;
+    Int i;
+    ULong* dst;
 
-  CLG_ASSERT(pdst != 0);
+    CLG_ASSERT(pdst != 0);
 
-  if (!src) {
-    CLG_(zero_cost)(es, *pdst);
-    return;
-  }
-  dst = *pdst;
-  if (!dst)
-    dst = *pdst = CLG_(get_eventset_cost)(es);
+    if (!src) {
+       CLG_(zero_cost)(es, *pdst);
+       return;
+    }
+    dst = *pdst;
+    if (!dst)
+       dst = *pdst = CLG_(get_eventset_cost)(es);
   
-  for(i=0;i<es->size;i++)
-    dst[i] = src[i];
+    for(i=0;i<es->size;i++)
+       dst[i] = src[i];
 }
 
 void CLG_(add_cost)(EventSet* es, ULong* dst, ULong* src)
 {
-  Int i = 0;
+    Int i;
 
-  if (!src) return;
-  CLG_ASSERT(dst != 0);
+    if (!src) return;
+    CLG_ASSERT(dst != 0);
 
-  while(i<es->size) {
-    if (src[i] == 0)
-      i = es->e[i].nextTop;
-    else {
-      dst[i] += src[i];
-      i++;
-    }
-  }
+    for(i=0; i<es->size; i++)
+       dst[i] += src[i];
 }
 
 void CLG_(add_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
 {
-  Int i;
-  ULong* dst;
-
-  if (!src) return;
-  CLG_ASSERT(pdst != 0);
-
-  dst = *pdst;
-  if (!dst) {
-    dst = *pdst = CLG_(get_eventset_cost)(es);
-    CLG_(copy_cost)(es,dst,src);
-    return;
-  }
-
-  i = 0;
-  while(i<es->size) {
-    if (src[i] == 0)
-      i = es->e[i].nextTop;
-    else {
-      dst[i] += src[i];
-      i++;
+    Int i;
+    ULong* dst;
+
+    if (!src) return;
+    CLG_ASSERT(pdst != 0);
+
+    dst = *pdst;
+    if (!dst) {
+       dst = *pdst = CLG_(get_eventset_cost)(es);
+       CLG_(copy_cost)(es, dst, src);
+       return;
     }
-  }
+
+    for(i=0; i<es->size; i++)
+       dst[i] += src[i];
 }
 
 /* Adds src to dst and zeros src. Returns false if nothing changed */
 Bool CLG_(add_and_zero_cost)(EventSet* es, ULong* dst, ULong* src)
 {
-  Int i = 0, j = 0;
-
-  CLG_DEBUGIF(6) {
-    CLG_DEBUG(6, "   add_and_zero_cost(%s, dst %p, src %p)\n", es->name, dst, src);
-    CLG_(print_cost)(-5, es, src);
-  }
+    Int i;
+    Bool is_nonzero = False;
 
-  if (!es || !src) return False;
+    CLG_ASSERT((es != 0) && (dst != 0));
+    if (!src) return False;
 
-  while(i<es->size) {
-    if (src[i] == 0)
-      i = es->e[i].nextTop;
-    else {
-      dst[i] += src[i];
-      src[i] = 0;
-      i++;
-      j++;
+    for(i=0; i<es->size; i++) {
+       if (src[i]==0) continue;
+       dst[i] += src[i];
+       src[i] = 0;
+       is_nonzero = True;
     }
-  }
 
-  return (j>0);
+    return is_nonzero;
 }
 
 /* Adds src to dst and zeros src. Returns false if nothing changed */
-Bool CLG_(add_and_zero_cost_lz)(EventSet* es, ULong** pdst, ULong* src)
-{
-  Int i;
-  ULong* dst;
-
-  if (!src) return False;
-
-  i = 0;
-  while(1) {
-    if (i >= es->size) return False;
-    if (src[i] != 0) break;
-    i = es->e[i].nextTop;
-  }
-
-  CLG_ASSERT(pdst != 0);
-  dst = *pdst;
-  if (!dst) {
-    dst = *pdst = CLG_(get_eventset_cost)(es);
-    CLG_(copy_cost)(es,dst,src);
-    CLG_(zero_cost)(es,src);
-    return True;
-  }
-
-  dst[i] += src[i];
-  src[i] = 0;
-  i++;
-
-  while(i<es->size) {
-    if (src[i] == 0)
-      i = es->e[i].nextTop;
-    else {
-      dst[i] += src[i];
-      src[i] = 0;
+Bool CLG_(add_and_zero_cost2)(EventSet* esDst, ULong* dst,
+                             EventSet* esSrc, ULong* src)
+{
+    Int i,j;
+    Bool is_nonzero = False;
+    UInt mask;
+    EventGroup *eg;
+    ULong *egDst, *egSrc;
+
+    CLG_ASSERT((esDst != 0) && (dst != 0) && (esSrc != 0));
+    if (!src) return False;
+
+    for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
+       if ((esSrc->mask & mask)==0) continue;
+       if (eventGroup[i] ==0) continue;
+
+       /* if src has a subset, dst must have, too */
+       CLG_ASSERT((esDst->mask & mask)>0);
+       eg = eventGroup[i];
+       egSrc = src + esSrc->offset[i];
+       egDst = dst + esDst->offset[i];
+       for(j=0; j<eg->size; j++) {
+           if (egSrc[j]==0) continue;
+           egDst[j] += egSrc[j];
+           egSrc[j] = 0;
+           is_nonzero = True;
+       }
     }
-  }
 
-  return True;
+    return is_nonzero;
 }
 
+
+
 /* Adds difference of new and old to dst, and set old to new.
  * Returns false if nothing changed */
 Bool CLG_(add_diff_cost)(EventSet* es, ULong* dst, ULong* old, ULong* new_cost)
 {
-  Int i = 0, j = 0;
+    Int i;
+    Bool is_nonzero = False;
 
-  while(i<es->size) {
-    if (new_cost[i] == old[i])
-      i = es->e[i].nextTop;
-    else {
-      dst[i] += new_cost[i] - old[i];
-      old[i] = new_cost[i];
-      i++;
-      j++;
+    CLG_ASSERT((es != 0) && (dst != 0));
+    CLG_ASSERT(old && new_cost);
+
+    for(i=0; i<es->size; i++) {
+       if (new_cost[i] == old[i]) continue;
+       dst[i] += new_cost[i] - old[i];
+       old[i] = new_cost[i];
+       is_nonzero = True;
     }
-  }
 
-  return (j>0);
+    return is_nonzero;
 }
 
-/* Adds difference of new and old to dst, and set old to new.
- * Returns false if nothing changed */
-Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst, 
-                           ULong* old, ULong* new_cost)
-{
-  Int i;
-  ULong* dst;
-
-  if (!old && !new_cost) return False;
-  CLG_ASSERT(old && new_cost);
-
-  i = 0;
-  while(1) {
-    if (i >= es->size) return False;
-    if (old[i] != new_cost[i]) break;
-    i = es->e[i].nextTop;
-  }
-
-  CLG_ASSERT(pdst != 0);
-  dst = *pdst;
-  if (!dst) {
-    dst = *pdst = CLG_(get_eventset_cost)(es);
-    CLG_(zero_cost)(es,dst);
-  }
-
-  dst[i] += new_cost[i] - old[i];
-  old[i] = new_cost[i];
-  i++;
-
-  while(i<es->size) {
-    if (new_cost[i] == old[i])
-      i = es->e[i].nextTop;
-    else {
-      dst[i] += new_cost[i] - old[i];
-      old[i] = new_cost[i];
-      i++;
+Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst, ULong* old, ULong* new_cost)
+{
+    Int i;
+    ULong* dst;
+    Bool is_nonzero = False;
+
+    CLG_ASSERT((es != 0) && (pdst != 0));
+    CLG_ASSERT(old && new_cost);
+
+    dst = *pdst;
+    if (!dst) {
+       dst = *pdst = CLG_(get_eventset_cost)(es);
+       CLG_(zero_cost)(es, dst);
     }
-  }
 
-  return True;
+    for(i=0; i<es->size; i++) {
+       if (new_cost[i] == old[i]) continue;
+       dst[i] += new_cost[i] - old[i];
+       old[i] = new_cost[i];
+       is_nonzero = True;
+    }
+
+    return is_nonzero;
 }
 
+
 /* Returns number of characters written */
 Int CLG_(sprint_cost)(Char* buf, EventSet* es, ULong* c)
 {
-  Int i, pos, skipped = 0;
+    Int i, pos, skipped = 0;
 
-  if (!c || es->size==0) return 0;
+    if (!c || es->size==0) return 0;
 
-  /* At least one entry */
-  pos = VG_(sprintf)(buf, "%llu", c[0]);
-  i = 1;
-
-  while(i<es->size) {
-    if (c[i] == 0) {
-      skipped  += es->e[i].nextTop - i;
-      i = es->e[i].nextTop;
-    }
-    else {
-      while(skipped>0) {
+    /* At least one entry */
+    pos = VG_(sprintf)(buf, "%llu", c[0]);
+    for(i=1; i<es->size; i++) {
+       if (c[i] == 0) {
+           skipped++;
+           continue;
+       }
+       while(skipped>0) {
+           buf[pos++] = ' ';
+           buf[pos++] = '0';
+           skipped--;
+       }
        buf[pos++] = ' ';
-       buf[pos++] = '0';
-       skipped--;
-      }
-      buf[pos++] = ' ';
-      pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
-      i++;
+       pos += VG_(sprintf)(buf+pos, "%llu", c[i]);
     }
-  }
 
-  return pos;
+    return pos;
 }
 
 
 /* Allocate space for an event mapping */
 EventMapping* CLG_(get_eventmapping)(EventSet* es)
 {
-  EventMapping* em;
+    EventMapping* em;
 
-  CLG_ASSERT(es != 0);
+    CLG_ASSERT(es != 0);
 
-  em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
-                                   sizeof(EventMapping) +
-                                  es->capacity * sizeof(Int));
-  em->capacity = es->capacity;
-  em->size = 0;
-  em->set = es;
+    em = (EventMapping*) CLG_MALLOC("cl.events.geMapping.1",
+                                   sizeof(EventMapping) +
+                                   sizeof(struct EventMappingEntry) *
+                                   es->size);
+    em->capacity = es->size;
+    em->size = 0;
+    em->es = es;
 
-  return em;
+    return em;
 }
 
 void CLG_(append_event)(EventMapping* em, Char* n)
 {
-  Int i;
-
-  CLG_ASSERT(em != 0);
-
-  for(i=0; i<em->set->size; i++)
-    if (VG_(strcmp)(n, em->set->e[i].type->name)==0)
-      break;
-  
-  if (i == em->set->size) return;
-
-  CLG_ASSERT(em->capacity > em->size);
-
-  em->index[em->size] = i;
-  em->size++;
+    Int i, j, offset = 0;
+    UInt mask;
+    EventGroup* eg;
+
+    CLG_ASSERT(em != 0);
+    for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
+       if ((em->es->mask & mask)==0) continue;
+       if (eventGroup[i] ==0) continue;
+
+       eg = eventGroup[i];
+       for(j=0; j<eg->size; j++, offset++) {
+           if (VG_(strcmp)(n, eg->name[j])!=0)
+                   continue;
+
+           CLG_ASSERT(em->capacity > em->size);
+           em->entry[em->size].group = i;
+           em->entry[em->size].index = j;
+           em->entry[em->size].offset = offset;
+           em->size++;
+           return;
+       }
+    }
 }
 
 
 /* Returns number of characters written */
 Int CLG_(sprint_eventmapping)(Char* buf, EventMapping* em)
 {
-  Int i, pos = 0;
+    Int i, pos = 0;
+    EventGroup* eg;
 
-  CLG_ASSERT(em != 0);
+    CLG_ASSERT(em != 0);
 
-  for(i=0; i< em->size; i++) {
-    if (pos>0) buf[pos++] = ' ';
-    pos += VG_(sprintf)(buf + pos, "%s", em->set->e[em->index[i]].type->name);
-  }
-  buf[pos] = 0;
+    for(i=0; i< em->size; i++) {
+       if (pos>0) buf[pos++] = ' ';
+       eg = eventGroup[em->entry[i].group];
+       CLG_ASSERT(eg != 0);
+       pos += VG_(sprintf)(buf + pos, "%s", eg->name[em->entry[i].index]);
+    }
+    buf[pos] = 0;
 
-  return pos;
+    return pos;
 }
 
 /* Returns number of characters written */
 Int CLG_(sprint_mappingcost)(Char* buf, EventMapping* em, ULong* c)
 {
-  Int i, pos, skipped = 0;
+    Int i, pos, skipped = 0;
 
-  if (!c || em->size==0) return 0;
+    if (!c || em->size==0) return 0;
 
     /* At least one entry */
-  pos = VG_(sprintf)(buf, "%llu", c[em->index[0]]);
-  i = 1;
-
-  while(i<em->size) {
-    if (c[em->index[i]] == 0) {
-      skipped++;
-      i++;
-    }
-    else {
-      while(skipped>0) {
+    pos = VG_(sprintf)(buf, "%llu", c[em->entry[0].offset]);
+
+    for(i=1; i<em->size; i++) {
+       if (c[em->entry[i].offset] == 0) {
+           skipped++;
+           continue;
+       }
+       while(skipped>0) {
+           buf[pos++] = ' ';
+           buf[pos++] = '0';
+           skipped--;
+       }
        buf[pos++] = ' ';
-       buf[pos++] = '0';
-       skipped--;
-      }
-      buf[pos++] = ' ';
-      pos += VG_(sprintf)(buf+pos, "%llu", c[em->index[i]]);
-      i++;
+       pos += VG_(sprintf)(buf+pos, "%llu", c[em->entry[i].offset]);
     }
-  }
 
-  return pos;
+    return pos;
 }
index c3ddbe36c5400ac47bb24dded1cd74f1fa379192..d892ccb050643ae03055b878d85a29c045ff2944 100644 (file)
@@ -1,86 +1,90 @@
 /*--------------------------------------------------------------------*/
 /*--- Callgrind                                                    ---*/
 /*---                                                     events.h ---*/
-/*--- (C) 2004-2005, Josef Weidendorfer                            ---*/
 /*--------------------------------------------------------------------*/
 
+/*
+   This file is part of Callgrind, a Valgrind tool for call tracing.
+
+   Copyright (C) 2002-2010, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
 
 /* Abstractions for 64-bit cost lists (events.h) */
 
-#ifndef CG_EVENTS
-#define CG_EVENTS
+#ifndef CLG_EVENTS
+#define CLG_EVENTS
 
 #include "pub_tool_basics.h"
 
 #define CLG_(str) VGAPPEND(vgCallgrind_,str)
 
-/* An event type */
-typedef struct _EventType EventType;
-struct _EventType {
-  Char* name;
-  Char* description;
-  Int id;
-};
+/* Event groups consist of one or more named event types.
+ * Event sets are constructed from such event groups.
+ *
+ * Event groups have to be registered globally with a unique ID
+ * before they can be used in an event set.
+ * A group can appear at most once in a event set.
+ */
 
-EventType* CLG_(register_eventtype)(Char*);
-EventType* CLG_(get_eventtype)(Char*);
-EventType* CLG_(get_eventtype_byindex)(Int id);
+#define MAX_EVENTGROUP_COUNT 10
 
-/* An event set is a ordered list of event types, which comes down
- * to some description for ordered lists of costs.
- * Often, costs of 2 event types are related, e.g. one is always smaller
- * than the other. This is useful to speed up arithmetics on cost lists:
- * Each event type in the set has a <nextTop>. All indexes before are
- * promised to hold smaller values than the current.
- */
-typedef struct _EventSetEntry EventSetEntry;
-struct _EventSetEntry {
-  EventType* type;
-  Int nextTop;
-};
-typedef struct _EventSet EventSet;
-struct _EventSet {
-  Char* name;
-  Int size;
-  Int capacity;
-  EventSetEntry e[0];
+typedef struct _EventGroup EventGroup;
+struct _EventGroup {
+    Int size;
+    Char* name[0];
 };
 
+/* return 0 if event group can not be registered */
+EventGroup* CLG_(register_event_group) (int id, Char*);
+EventGroup* CLG_(register_event_group2)(int id, Char*, Char*);
+EventGroup* CLG_(register_event_group3)(int id, Char*, Char*, Char*);
+EventGroup* CLG_(register_event_group4)(int id, Char*, Char*, Char*, Char*);
+EventGroup* CLG_(get_event_group)(int id);
 
-/* Some events out of an event set.
- * Used to print out part of an EventSet, or in another order.
- */
-typedef struct _EventMapping EventMapping;
-struct _EventMapping {
-  EventSet* set;
-  Int size;
-  Int capacity;
-  Int index[0];
-};
+/* Event sets are defined by event groups they consist of. */
 
-  
-/* Allocate space for an event set */
-EventSet* CLG_(get_eventset)(Char* n, Int capacity);
-/* Incorporate a event type into a set, get start offset */
-Int CLG_(add_eventtype)(EventSet* dst, EventType*);
-/* Incorporate event types into a set, with ... < second < first */
-Int CLG_(add_dep_event2)(EventSet* dst, EventType* e1, EventType* e2);
-Int CLG_(add_dep_event3)(EventSet* dst,
-                       EventType* e1, EventType* e2, EventType* e3);
-Int CLG_(add_dep_event4)(EventSet* dst,
-                       EventType* e1, EventType* e2, EventType* e3,
-                       EventType* e4);
-/* Incorporate one event set into another, get start offset */
-Int CLG_(add_eventset)(EventSet* dst, EventSet* src);
-/* Returns number of characters written */
+typedef struct _EventSet EventSet;
+struct _EventSet {
+    /* if subset with ID x is in the set, then bit x is set */
+    UInt mask;
+    Int count;
+    Int size;
+    Int offset[MAX_EVENTGROUP_COUNT];
+ };
+
+/* Same event set is returned when requesting same event groups */
+EventSet* CLG_(get_event_set)(Int id);
+EventSet* CLG_(get_event_set2)(Int id1, Int id2);
+EventSet* CLG_(get_event_set3)(Int id1, Int id2, Int id3);
+EventSet* CLG_(add_event_group)(EventSet*, Int id);
+EventSet* CLG_(add_event_group2)(EventSet*, Int id1, Int id2);
+EventSet* CLG_(add_event_set)(EventSet*, EventSet*);
+/* Writes event names into buf. Returns number of characters written */
 Int CLG_(sprint_eventset)(Char* buf, EventSet*);
-/* Allocate cost array for an event set */
-ULong* CLG_(get_eventset_cost)(EventSet*);
+
 
 /* Operations on costs. A cost pointer of 0 means zero cost.
- * Functions ending in _lz allocate costs lazy if needed
+ * Functions ending in _lz allocate cost arrays only when needed
  */
-/* Set costs according full capacity of event set to 0 */
+ULong* CLG_(get_eventset_cost)(EventSet*);
+/* Set costs of event set to 0 */
 void CLG_(init_cost)(EventSet*,ULong*);
 /* This always allocates counter and sets them to 0 */
 void CLG_(init_cost_lz)(EventSet*,ULong**);
@@ -94,7 +98,7 @@ void CLG_(add_cost)(EventSet*,ULong* dst, ULong* src);
 void CLG_(add_cost_lz)(EventSet*,ULong** pdst, ULong* src);
 /* Adds src to dst and zeros src. Returns false if nothing changed */
 Bool CLG_(add_and_zero_cost)(EventSet*,ULong* dst, ULong* src);
-Bool CLG_(add_and_zero_cost_lz)(EventSet*,ULong** pdst, ULong* src);
+Bool CLG_(add_and_zero_cost2)(EventSet*,ULong* dst,EventSet*,ULong* src);
 /* Adds difference of new and old to to dst, and set old to new.
  * Returns false if nothing changed */
 Bool CLG_(add_diff_cost)(EventSet*,ULong* dst, ULong* old, ULong* new_cost);
@@ -102,6 +106,22 @@ Bool CLG_(add_diff_cost_lz)(EventSet*,ULong** pdst, ULong* old, ULong* new_cost)
 /* Returns number of characters written */
 Int CLG_(sprint_cost)(Char* buf, EventSet*, ULong*);
 
+/* EventMapping: An ordered subset of events from an event set.
+ * This is used to print out part of an EventSet, or in another order.
+ */
+struct EventMappingEntry {
+    Int group;
+    Int index;
+    Int offset;
+};
+typedef struct _EventMapping EventMapping;
+struct _EventMapping {
+  EventSet* es;
+  Int size;
+  Int capacity;
+  struct EventMappingEntry entry[0];
+};
+
 /* Allocate space for an event mapping */
 EventMapping* CLG_(get_eventmapping)(EventSet*);
 void CLG_(append_event)(EventMapping*, Char*);
@@ -110,4 +130,4 @@ Int CLG_(sprint_eventmapping)(Char* buf, EventMapping*);
 /* Returns number of characters written */
 Int CLG_(sprint_mappingcost)(Char* buf, EventMapping*, ULong*);
 
-#endif /* CG_EVENTS */
+#endif /* CLG_EVENTS */
index 367f2d7d34684cbc529772b38dd6a11c86e810e4..8f33ff34f94b3b4646eba2a5564260858760f702 100644 (file)
@@ -671,6 +671,21 @@ struct cachesim_if
     Char *log_0I1Dr_name, *log_0I1Dw_name;
 };
 
+// Event groups
+#define EG_USE   0
+#define EG_IR    1
+#define EG_DR    2
+#define EG_DW    3
+#define EG_ALLOC 4
+#define EG_SYS   5
+
+struct event_sets {
+    EventSet *base, *full;
+};
+extern struct event_sets CLG_(sets);
+
+#define fullOffset(group) (CLG_(sets).full->offset[group])
+
 
 /*------------------------------------------------------------*/
 /*--- Functions                                            ---*/
@@ -685,20 +700,8 @@ void CLG_(print_usage)(void);
 void CLG_(print_debug_usage)(void);
 
 /* from sim.c */
-struct event_sets {
-  EventSet *Use, *Ir, *Dr, *Dw;
-  EventSet *UIr, *UIrDr, *UIrDrDw, *UIrDw, *UIrDwDr;
-  EventSet *full;
-
-  /* offsets into eventsets */  
-  Int off_full_Ir, off_full_Dr, off_full_Dw;
-  Int off_full_alloc, off_full_systime;
-};
-
-extern struct event_sets CLG_(sets);
 extern struct cachesim_if CLG_(cachesim);
-
-void CLG_(init_eventsets)(Int user);
+void CLG_(init_eventsets)(void);
 
 /* from main.c */
 Bool CLG_(get_debug_info)(Addr, Char filename[FILENAME_LEN],
index 3f02517b0927f5f7f39a6ddbd53090f29e46651c..4aa3ce7e2ab53bb26ee07831e63e7ec117d2410d 100644 (file)
@@ -273,34 +273,18 @@ static void flushEvents ( ClgState* clgs )
           case Ev_Ir:
               // Ir event always is first for a guest instruction
               CLG_ASSERT(ev->inode->eventset == 0);
-              ev->inode->eventset = CLG_(sets).UIr;
+              ev->inode->eventset = CLG_(sets).base;
               break;
           case Ev_Dr:
               // extend event set by Dr counter
-              if ((ev->inode->eventset == CLG_(sets).UIrDr)   ||
-                  (ev->inode->eventset == CLG_(sets).UIrDrDw) ||
-                  (ev->inode->eventset == CLG_(sets).UIrDwDr))
-                  break;
-              if (ev->inode->eventset == CLG_(sets).UIrDw) {
-                  ev->inode->eventset = CLG_(sets).UIrDwDr;
-                  break;
-              }
-              CLG_ASSERT(ev->inode->eventset == CLG_(sets).UIr);
-              ev->inode->eventset = CLG_(sets).UIrDr;
+              ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
+                                                          EG_DR);
               break;
           case Ev_Dw:
           case Ev_Dm:
               // extend event set by Dw counter
-              if ((ev->inode->eventset == CLG_(sets).UIrDw)   ||
-                  (ev->inode->eventset == CLG_(sets).UIrDwDr) ||
-                  (ev->inode->eventset == CLG_(sets).UIrDrDw))
-                  break;
-              if (ev->inode->eventset == CLG_(sets).UIrDr) {
-                  ev->inode->eventset = CLG_(sets).UIrDrDw;
-                  break;
-              }
-              CLG_ASSERT(ev->inode->eventset == CLG_(sets).UIr);
-              ev->inode->eventset = CLG_(sets).UIrDw;
+              ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
+                                                          EG_DW);
               break;
           default:
               tl_assert(0);
@@ -1161,7 +1145,7 @@ void CLG_(post_syscalltime)(ThreadId tid, UInt syscallno,
 {
   if (CLG_(clo).collect_systime &&
       CLG_(current_state).bbcc) {
-    Int o = CLG_(sets).off_full_systime;
+      Int o;
 #if CLG_MICROSYSTIME
     struct vki_timeval tv_now;
     ULong diff;
@@ -1171,11 +1155,12 @@ void CLG_(post_syscalltime)(ThreadId tid, UInt syscallno,
 #else
     UInt diff = VG_(read_millisecond_timer)() - syscalltime[tid];
 #endif  
-    
+
+    /* offset o is for "SysCount", o+1 for "SysTime" */
+    o = fullOffset(EG_SYS);
+    CLG_ASSERT(o>=0);
     CLG_DEBUG(0,"   Time (Off %d) for Syscall %d: %ull\n", o, syscallno, diff);
     
-    if (o<0) return;
-
     CLG_(current_state).cost[o] ++;
     CLG_(current_state).cost[o+1] += diff;
     if (!CLG_(current_state).bbcc->skipped)
@@ -1333,7 +1318,7 @@ void CLG_(post_clo_init)(void)
 
    (*CLG_(cachesim).post_clo_init)();
 
-   CLG_(init_eventsets)(0);
+   CLG_(init_eventsets)();
    CLG_(init_statistics)(& CLG_(stat));
    CLG_(init_cost_lz)( CLG_(sets).full, &CLG_(total_cost) );
 
index e79d9e2ad66daeb488afe2dec95ed8b3a5867330..a69f7603a91bb973addda412d9820da31311050d 100644 (file)
@@ -1,4 +1,3 @@
-
 /*--------------------------------------------------------------------*/
 /*--- Cache simulation.                                            ---*/
 /*---                                                        sim.c ---*/
@@ -8,7 +7,7 @@
    This file is part of Callgrind, a Valgrind tool for call graph
    profiling programs.
 
-   Copyright (C) 2003-2005, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
+   Copyright (C) 2003-2010, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
 
    This tool is derived from and contains code from Cachegrind
    Copyright (C) 2002-2010 Nicholas Nethercote (njn@valgrind.org)
@@ -113,15 +112,6 @@ static Bool clo_collect_cacheuse = False;
  * - BBCC*  nonskipped  (only != 0 when in a function not skipped)
  */
 
-/* Offset to events in event set, used in log_* functions
- * <off_EventSet_BasicEventSet>: offset where basic set is found
- */
-static Int off_UIr_Ir;
-static Int off_UIrDr_Ir,   off_UIrDr_Dr;
-static Int off_UIrDrDw_Ir, off_UIrDrDw_Dr, off_UIrDrDw_Dw;
-static Int off_UIrDw_Ir,   off_UIrDw_Dw;
-static Int off_UIrDwDr_Ir, off_UIrDwDr_Dr, off_UIrDwDr_Dw;
-
 static Addr   bb_base;
 static ULong* cost_base;
 static InstrInfo* current_ii;
@@ -1071,12 +1061,12 @@ static void log_1I0D(InstrInfo* ii)
        ULong* cost_Ir;
 
        if (CLG_(current_state).nonskipped)
-           cost_Ir = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Ir;
+           cost_Ir = CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
        else
-           cost_Ir = cost_base + ii->cost_offset + off_UIr_Ir;
+           cost_Ir = cost_base + ii->cost_offset + ii->eventset->offset[EG_IR];
 
        inc_costs(IrRes, cost_Ir, 
-                 CLG_(current_state).cost + CLG_(sets).off_full_Ir );
+                 CLG_(current_state).cost + fullOffset(EG_IR) );
     }
 }
 
@@ -1097,17 +1087,20 @@ static void log_2I0D(InstrInfo* ii1, InstrInfo* ii2)
 
     if (!CLG_(current_state).collect) return;
 
-    global_cost_Ir = CLG_(current_state).cost + CLG_(sets).off_full_Ir;
+    global_cost_Ir = CLG_(current_state).cost + fullOffset(EG_IR);
     if (CLG_(current_state).nonskipped) {
-       ULong* skipped_cost_Ir = CLG_(current_state).nonskipped->skipped +
-                                CLG_(sets).off_full_Ir;
+       ULong* skipped_cost_Ir =
+           CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
+
        inc_costs(Ir1Res, global_cost_Ir, skipped_cost_Ir);
        inc_costs(Ir2Res, global_cost_Ir, skipped_cost_Ir);
        return;
     }
 
-    inc_costs(Ir1Res, global_cost_Ir, cost_base + ii1->cost_offset + off_UIr_Ir);
-    inc_costs(Ir2Res, global_cost_Ir, cost_base + ii2->cost_offset + off_UIr_Ir);
+    inc_costs(Ir1Res, global_cost_Ir,
+             cost_base + ii1->cost_offset + ii1->eventset->offset[EG_IR]);
+    inc_costs(Ir2Res, global_cost_Ir,
+             cost_base + ii2->cost_offset + ii2->eventset->offset[EG_IR]);
 }
 
 VG_REGPARM(3)
@@ -1130,19 +1123,22 @@ static void log_3I0D(InstrInfo* ii1, InstrInfo* ii2, InstrInfo* ii3)
 
     if (!CLG_(current_state).collect) return;
 
-    global_cost_Ir = CLG_(current_state).cost + CLG_(sets).off_full_Ir;
+    global_cost_Ir = CLG_(current_state).cost + fullOffset(EG_IR);
     if (CLG_(current_state).nonskipped) {
-       ULong* skipped_cost_Ir = CLG_(current_state).nonskipped->skipped +
-                                CLG_(sets).off_full_Ir;
+       ULong* skipped_cost_Ir =
+           CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
        inc_costs(Ir1Res, global_cost_Ir, skipped_cost_Ir);
        inc_costs(Ir2Res, global_cost_Ir, skipped_cost_Ir);
        inc_costs(Ir3Res, global_cost_Ir, skipped_cost_Ir);
        return;
     }
 
-    inc_costs(Ir1Res, global_cost_Ir, cost_base + ii1->cost_offset + off_UIr_Ir);
-    inc_costs(Ir2Res, global_cost_Ir, cost_base + ii2->cost_offset + off_UIr_Ir);
-    inc_costs(Ir3Res, global_cost_Ir, cost_base + ii3->cost_offset + off_UIr_Ir);
+    inc_costs(Ir1Res, global_cost_Ir,
+             cost_base + ii1->cost_offset + ii1->eventset->offset[EG_IR]);
+    inc_costs(Ir2Res, global_cost_Ir,
+             cost_base + ii2->cost_offset + ii2->eventset->offset[EG_IR]);
+    inc_costs(Ir3Res, global_cost_Ir,
+             cost_base + ii3->cost_offset + ii3->eventset->offset[EG_IR]);
 }
 
 /* Instruction doing a read access */
@@ -1164,21 +1160,18 @@ static void log_1I1Dr(InstrInfo* ii, Addr data_addr, Word data_size)
        ULong *cost_Ir, *cost_Dr;
        
        if (CLG_(current_state).nonskipped) {
-           cost_Ir = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Ir;
-           cost_Dr = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Dr;
+           cost_Ir = CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
+           cost_Dr = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DR);
        }
        else {
-           // event set must be UIrDr or extension
-           CLG_ASSERT((ii->eventset == CLG_(sets).UIrDr) ||
-                      (ii->eventset == CLG_(sets).UIrDrDw));
-           cost_Ir = cost_base + ii->cost_offset + off_UIrDr_Ir;
-           cost_Dr = cost_base + ii->cost_offset + off_UIrDr_Dr;
+           cost_Ir = cost_base + ii->cost_offset + ii->eventset->offset[EG_IR];
+           cost_Dr = cost_base + ii->cost_offset + ii->eventset->offset[EG_DR];
        }
        
        inc_costs(IrRes, cost_Ir, 
-                 CLG_(current_state).cost + CLG_(sets).off_full_Ir );
+                 CLG_(current_state).cost + fullOffset(EG_IR) );
        inc_costs(DrRes, cost_Dr,
-                 CLG_(current_state).cost + CLG_(sets).off_full_Dr );
+                 CLG_(current_state).cost + fullOffset(EG_DR) );
     }
 }
 
@@ -1197,21 +1190,13 @@ static void log_0I1Dr(InstrInfo* ii, Addr data_addr, Word data_size)
     if (CLG_(current_state).collect) {
        ULong *cost_Dr;
        
-       if (CLG_(current_state).nonskipped) {
-           cost_Dr = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Dr;
-       }
-       else {
-           Int off_Dr;
-           if      (ii->eventset == CLG_(sets).UIrDr)   off_Dr = off_UIrDr_Dr;
-           else if (ii->eventset == CLG_(sets).UIrDrDw) off_Dr = off_UIrDrDw_Dr;
-           else if (ii->eventset == CLG_(sets).UIrDwDr) off_Dr = off_UIrDwDr_Dr;
-           else CLG_ASSERT(0);
-
-           cost_Dr = cost_base + ii->cost_offset + off_Dr;
-       }
+       if (CLG_(current_state).nonskipped)
+           cost_Dr = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DR);
+       else
+           cost_Dr = cost_base + ii->cost_offset + ii->eventset->offset[EG_DR];
 
        inc_costs(DrRes, cost_Dr,
-                 CLG_(current_state).cost + CLG_(sets).off_full_Dr );
+                 CLG_(current_state).cost + fullOffset(EG_DR) );
     }
 }
 
@@ -1235,22 +1220,18 @@ static void log_1I1Dw(InstrInfo* ii, Addr data_addr, Word data_size)
        ULong *cost_Ir, *cost_Dw;
        
        if (CLG_(current_state).nonskipped) {
-           cost_Ir = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Ir;
-           cost_Dw = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Dw;
+           cost_Ir = CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
+           cost_Dw = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DW);
        }
        else {
-           // This helper is called when a Dr event follows Ir;
-           // Event set must be UIrDw or extension
-           CLG_ASSERT((ii->eventset == CLG_(sets).UIrDw) ||
-                      (ii->eventset == CLG_(sets).UIrDwDr));
-           cost_Ir = cost_base + ii->cost_offset + off_UIrDw_Ir;
-           cost_Dw = cost_base + ii->cost_offset + off_UIrDw_Dw;
+           cost_Ir = cost_base + ii->cost_offset + ii->eventset->offset[EG_IR];
+           cost_Dw = cost_base + ii->cost_offset + ii->eventset->offset[EG_DW];
        }
        
        inc_costs(IrRes, cost_Ir,
-                 CLG_(current_state).cost + CLG_(sets).off_full_Ir );
+                 CLG_(current_state).cost + fullOffset(EG_IR) );
        inc_costs(DwRes, cost_Dw,
-                 CLG_(current_state).cost + CLG_(sets).off_full_Dw );
+                 CLG_(current_state).cost + fullOffset(EG_DW) );
     }
 }
 
@@ -1268,21 +1249,13 @@ static void log_0I1Dw(InstrInfo* ii, Addr data_addr, Word data_size)
     if (CLG_(current_state).collect) {
        ULong *cost_Dw;
        
-       if (CLG_(current_state).nonskipped) {
-           cost_Dw = CLG_(current_state).nonskipped->skipped + CLG_(sets).off_full_Dw;
-       }
-       else {
-           Int off_Dw;
-           if      (ii->eventset == CLG_(sets).UIrDw)   off_Dw = off_UIrDw_Dw;
-           else if (ii->eventset == CLG_(sets).UIrDwDr) off_Dw = off_UIrDwDr_Dw;
-           else if (ii->eventset == CLG_(sets).UIrDrDw) off_Dw = off_UIrDrDw_Dw;
-           else CLG_ASSERT(0);
-
-           cost_Dw = cost_base + ii->cost_offset + off_Dw;
-       }
+       if (CLG_(current_state).nonskipped)
+           cost_Dw = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DW);
+       else
+           cost_Dw = cost_base + ii->cost_offset + ii->eventset->offset[EG_DW];
        
        inc_costs(DwRes, cost_Dw,
-                 CLG_(current_state).cost + CLG_(sets).off_full_Dw );
+                 CLG_(current_state).cost + fullOffset(EG_DW) );
     }
 }
 
@@ -1663,28 +1636,28 @@ void cachesim_printstat(void)
 
   /* I cache results.  Use the I_refs value to determine the first column
    * width. */
-  l1 = commify(total[CLG_(sets).off_full_Ir], 0, buf1);
+  l1 = commify(total[fullOffset(EG_IR)], 0, buf1);
   VG_(message)(Vg_UserMsg, "I   refs:      %s\n", buf1);
 
   if (!CLG_(clo).simulate_cache) return;
 
-  commify(total[CLG_(sets).off_full_Ir +1], l1, buf1);
+  commify(total[fullOffset(EG_IR) +1], l1, buf1);
   VG_(message)(Vg_UserMsg, "I1  misses:    %s\n", buf1);
 
-  commify(total[CLG_(sets).off_full_Ir +2], l1, buf1);
+  commify(total[fullOffset(EG_IR) +2], l1, buf1);
   VG_(message)(Vg_UserMsg, "L2i misses:    %s\n", buf1);
 
   p = 100;
 
-  if (0 == total[CLG_(sets).off_full_Ir]) 
-    total[CLG_(sets).off_full_Ir] = 1;
+  if (0 == total[fullOffset(EG_IR)])
+    total[fullOffset(EG_IR)] = 1;
 
-  percentify(total[CLG_(sets).off_full_Ir+1] * 100 * p /
-            total[CLG_(sets).off_full_Ir], p, l1+1, buf1);
+  percentify(total[fullOffset(EG_IR)+1] * 100 * p /
+            total[fullOffset(EG_IR)], p, l1+1, buf1);
   VG_(message)(Vg_UserMsg, "I1  miss rate: %s\n", buf1);
        
-  percentify(total[CLG_(sets).off_full_Ir+2] * 100 * p /
-            total[CLG_(sets).off_full_Ir], p, l1+1, buf1);
+  percentify(total[fullOffset(EG_IR)+2] * 100 * p /
+            total[fullOffset(EG_IR)], p, l1+1, buf1);
   VG_(message)(Vg_UserMsg, "L2i miss rate: %s\n", buf1);
   VG_(message)(Vg_UserMsg, "\n");
    
@@ -1694,46 +1667,47 @@ void cachesim_printstat(void)
 
   D_total = CLG_(get_eventset_cost)( CLG_(sets).full );
   CLG_(init_cost)( CLG_(sets).full, D_total);
-  CLG_(copy_cost)( CLG_(sets).Dr, D_total, total + CLG_(sets).off_full_Dr );
-  CLG_(add_cost) ( CLG_(sets).Dw, D_total, total + CLG_(sets).off_full_Dw );
+  // we only use the first 3 values of D_total, adding up Dr and Dw costs
+  CLG_(copy_cost)( CLG_(get_event_set)(EG_DR), D_total, total + fullOffset(EG_DR) );
+  CLG_(add_cost) ( CLG_(get_event_set)(EG_DW), D_total, total + fullOffset(EG_DW) );
 
   commify( D_total[0], l1, buf1);
-  l2 = commify(total[CLG_(sets).off_full_Dr], 0,  buf2);
-  l3 = commify(total[CLG_(sets).off_full_Dw], 0,  buf3);
+  l2 = commify(total[fullOffset(EG_DR)], 0,  buf2);
+  l3 = commify(total[fullOffset(EG_DW)], 0,  buf3);
   VG_(message)(Vg_UserMsg, "D   refs:      %s  (%s rd + %s wr)\n",
               buf1,  buf2,  buf3);
 
   commify( D_total[1], l1, buf1);
-  commify(total[CLG_(sets).off_full_Dr+1], l2, buf2);
-  commify(total[CLG_(sets).off_full_Dw+1], l3, buf3);
+  commify(total[fullOffset(EG_DR)+1], l2, buf2);
+  commify(total[fullOffset(EG_DW)+1], l3, buf3);
   VG_(message)(Vg_UserMsg, "D1  misses:    %s  (%s rd + %s wr)\n",
               buf1, buf2, buf3);
 
   commify( D_total[2], l1, buf1);
-  commify(total[CLG_(sets).off_full_Dr+2], l2, buf2);
-  commify(total[CLG_(sets).off_full_Dw+2], l3, buf3);
+  commify(total[fullOffset(EG_DR)+2], l2, buf2);
+  commify(total[fullOffset(EG_DW)+2], l3, buf3);
   VG_(message)(Vg_UserMsg, "L2d misses:    %s  (%s rd + %s wr)\n",
               buf1, buf2, buf3);
 
   p = 10;
   
   if (0 == D_total[0])   D_total[0] = 1;
-  if (0 == total[CLG_(sets).off_full_Dr]) total[CLG_(sets).off_full_Dr] = 1;
-  if (0 == total[CLG_(sets).off_full_Dw]) total[CLG_(sets).off_full_Dw] = 1;
+  if (0 == total[fullOffset(EG_DR)]) total[fullOffset(EG_DR)] = 1;
+  if (0 == total[fullOffset(EG_DW)]) total[fullOffset(EG_DW)] = 1;
   
   percentify( D_total[1] * 100 * p / D_total[0],  p, l1+1, buf1);
-  percentify(total[CLG_(sets).off_full_Dr+1] * 100 * p /
-            total[CLG_(sets).off_full_Dr], p, l2+1, buf2);
-  percentify(total[CLG_(sets).off_full_Dw+1] * 100 * p /
-            total[CLG_(sets).off_full_Dw], p, l3+1, buf3);
+  percentify(total[fullOffset(EG_DR)+1] * 100 * p /
+            total[fullOffset(EG_DR)], p, l2+1, buf2);
+  percentify(total[fullOffset(EG_DW)+1] * 100 * p /
+            total[fullOffset(EG_DW)], p, l3+1, buf3);
   VG_(message)(Vg_UserMsg, "D1  miss rate: %s (%s   + %s  )\n", 
                buf1, buf2,buf3);
   
   percentify( D_total[2] * 100 * p / D_total[0],  p, l1+1, buf1);
-  percentify(total[CLG_(sets).off_full_Dr+2] * 100 * p /
-            total[CLG_(sets).off_full_Dr], p, l2+1, buf2);
-  percentify(total[CLG_(sets).off_full_Dw+2] * 100 * p /
-            total[CLG_(sets).off_full_Dw], p, l3+1, buf3);
+  percentify(total[fullOffset(EG_DR)+2] * 100 * p /
+            total[fullOffset(EG_DR)], p, l2+1, buf2);
+  percentify(total[fullOffset(EG_DW)+2] * 100 * p /
+            total[fullOffset(EG_DW)], p, l3+1, buf3);
   VG_(message)(Vg_UserMsg, "L2d miss rate: %s (%s   + %s  )\n", 
                buf1, buf2,buf3);
   VG_(message)(Vg_UserMsg, "\n");
@@ -1743,13 +1717,13 @@ void cachesim_printstat(void)
   /* L2 overall results */
   
   L2_total   =
-    total[CLG_(sets).off_full_Dr +1] +
-    total[CLG_(sets).off_full_Dw +1] +
-    total[CLG_(sets).off_full_Ir +1];
+    total[fullOffset(EG_DR) +1] +
+    total[fullOffset(EG_DW) +1] +
+    total[fullOffset(EG_IR) +1];
   L2_total_r =
-    total[CLG_(sets).off_full_Dr +1] +
-    total[CLG_(sets).off_full_Ir +1];
-  L2_total_w = total[CLG_(sets).off_full_Dw +1];
+    total[fullOffset(EG_DR) +1] +
+    total[fullOffset(EG_IR) +1];
+  L2_total_w = total[fullOffset(EG_DW) +1];
   commify(L2_total,   l1, buf1);
   commify(L2_total_r, l2, buf2);
   commify(L2_total_w, l3, buf3);
@@ -1757,13 +1731,13 @@ void cachesim_printstat(void)
               buf1, buf2, buf3);
   
   L2_total_m  =
-    total[CLG_(sets).off_full_Dr +2] +
-    total[CLG_(sets).off_full_Dw +2] +
-    total[CLG_(sets).off_full_Ir +2];
+    total[fullOffset(EG_DR) +2] +
+    total[fullOffset(EG_DW) +2] +
+    total[fullOffset(EG_IR) +2];
   L2_total_mr =
-    total[CLG_(sets).off_full_Dr +2] +
-    total[CLG_(sets).off_full_Ir +2];
-  L2_total_mw = total[CLG_(sets).off_full_Dw +2];
+    total[fullOffset(EG_DR) +2] +
+    total[fullOffset(EG_IR) +2];
+  L2_total_mw = total[fullOffset(EG_DW) +2];
   commify(L2_total_m,  l1, buf1);
   commify(L2_total_mr, l2, buf2);
   commify(L2_total_mw, l3, buf3);
@@ -1771,12 +1745,12 @@ void cachesim_printstat(void)
               buf1, buf2, buf3);
   
   percentify(L2_total_m  * 100 * p /
-            (total[CLG_(sets).off_full_Ir] + D_total[0]),  p, l1+1, buf1);
+            (total[fullOffset(EG_IR)] + D_total[0]),  p, l1+1, buf1);
   percentify(L2_total_mr * 100 * p /
-            (total[CLG_(sets).off_full_Ir] + total[CLG_(sets).off_full_Dr]),
+            (total[fullOffset(EG_IR)] + total[fullOffset(EG_DR)]),
             p, l2+1, buf2);
   percentify(L2_total_mw * 100 * p /
-            total[CLG_(sets).off_full_Dw], p, l3+1, buf3);
+            total[fullOffset(EG_DW)], p, l3+1, buf3);
   VG_(message)(Vg_UserMsg, "L2 miss rate:  %s (%s   + %s  )\n",
               buf1, buf2,buf3);
 }
@@ -1788,237 +1762,80 @@ void cachesim_printstat(void)
 
 struct event_sets CLG_(sets);
 
-void CLG_(init_eventsets)(Int max_user)
+void CLG_(init_eventsets)()
 {
-  EventType * e1, *e2, *e3, *e4;
-  // Basic event sets from which others are composed
-  EventSet *Use, *Ir, *Dr, *Dw;
-  // Compositions of basic sets used for per-instruction counters
-  EventSet *UIr, *UIrDr, *UIrDrDw, *UIrDw, *UIrDwDr;
-  // Composition used for global counters and aggregation
-  EventSet *full;
-  int sizeOfUseIr;
-
-  // the "Use" events types only are used with "cacheuse" simulation
-  Use = CLG_(get_eventset)("Use", 4);
-  if (clo_collect_cacheuse) {
-    /* if TUse is 0, there was never a load, and no loss, too */
-    e1 = CLG_(register_eventtype)("AcCost1");
-    CLG_(add_eventtype)(Use, e1);
-    e1 = CLG_(register_eventtype)("SpLoss1");
-    CLG_(add_eventtype)(Use, e1);
-    e1 = CLG_(register_eventtype)("AcCost2");
-    CLG_(add_eventtype)(Use, e1);
-    e1 = CLG_(register_eventtype)("SpLoss2");
-    CLG_(add_eventtype)(Use, e1);
-  }
-
-  Ir = CLG_(get_eventset)("Ir", 4);
-  Dr = CLG_(get_eventset)("Dr", 4);
-  Dw = CLG_(get_eventset)("Dw", 4);
-  if (CLG_(clo).simulate_cache) {
-    e1 = CLG_(register_eventtype)("Ir");
-    e2 = CLG_(register_eventtype)("I1mr");
-    e3 = CLG_(register_eventtype)("I2mr");
-    if (clo_simulate_writeback) {
-      e4 = CLG_(register_eventtype)("I2dmr");
-      CLG_(add_dep_event4)(Ir, e1,e2,e3,e4);
+    // Event groups from which the event sets are composed
+    // the "Use" group only is used with "cacheuse" simulation
+    if (clo_collect_cacheuse)
+       CLG_(register_event_group4)(EG_USE,
+                                   "AcCost1", "SpLoss1", "AcCost2", "SpLoss2");
+
+    if (!CLG_(clo).simulate_cache)
+       CLG_(register_event_group)(EG_IR, "Ir");
+    else if (!clo_simulate_writeback) {
+       CLG_(register_event_group3)(EG_IR, "Ir", "I1mr", "I2mr");
+       CLG_(register_event_group3)(EG_DR, "Dr", "D1mr", "D2mr");
+       CLG_(register_event_group3)(EG_DW, "Dw", "D1mw", "D2mw");
     }
-    else
-      CLG_(add_dep_event3)(Ir, e1,e2,e3);
-
-    e1 = CLG_(register_eventtype)("Dr");
-    e2 = CLG_(register_eventtype)("D1mr");
-    e3 = CLG_(register_eventtype)("D2mr");
-    if (clo_simulate_writeback) {
-      e4 = CLG_(register_eventtype)("D2dmr");
-      CLG_(add_dep_event4)(Dr, e1,e2,e3,e4);
-    }
-    else
-      CLG_(add_dep_event3)(Dr, e1,e2,e3);
-    
-    e1 = CLG_(register_eventtype)("Dw");
-    e2 = CLG_(register_eventtype)("D1mw");
-    e3 = CLG_(register_eventtype)("D2mw");
-    if (clo_simulate_writeback) {
-      e4 = CLG_(register_eventtype)("D2dmw");
-      CLG_(add_dep_event4)(Dw, e1,e2,e3,e4);
+    else { // clo_simulate_writeback
+       CLG_(register_event_group4)(EG_IR, "Ir", "I1mr", "I2mr", "I2dmr");
+       CLG_(register_event_group4)(EG_DR, "Dr", "D1mr", "D2mr", "I2dmr");
+       CLG_(register_event_group4)(EG_DW, "Dw", "D1mw", "D2mw", "I2dmw");
     }
-    else
-      CLG_(add_dep_event3)(Dw, e1,e2,e3);
 
-  }
-  else {
-    e1 = CLG_(register_eventtype)("Ir");
-    CLG_(add_eventtype)(Ir, e1);
-  }
+    if (CLG_(clo).collect_alloc)
+       CLG_(register_event_group2)(EG_ALLOC, "allocCount", "allocSize");
 
-  // Self cost event sets per guest instruction (U used only for cacheUse).
-  // Each basic event set only appears once, as eg. multiple different Dr's
-  // in one guest instruction are counted in the same counter.
-
-  sizeOfUseIr =  Use->size + Ir->size;
-  UIr = CLG_(get_eventset)("UIr", sizeOfUseIr);
-  CLG_(add_eventset)(UIr, Use);
-  off_UIr_Ir  = CLG_(add_eventset)(UIr, Ir);
-
-  UIrDr = CLG_(get_eventset)("UIrDr", sizeOfUseIr + Dr->size);
-  CLG_(add_eventset)(UIrDr, Use);
-  off_UIrDr_Ir = CLG_(add_eventset)(UIrDr, Ir);
-  off_UIrDr_Dr = CLG_(add_eventset)(UIrDr, Dr);
-
-  UIrDrDw  = CLG_(get_eventset)("IrDrDw", sizeOfUseIr + Dr->size + Dw->size);
-  CLG_(add_eventset)(UIrDrDw, Use);
-  off_UIrDrDw_Ir    = CLG_(add_eventset)(UIrDrDw, Ir);
-  off_UIrDrDw_Dr    = CLG_(add_eventset)(UIrDrDw, Dr);
-  off_UIrDrDw_Dw    = CLG_(add_eventset)(UIrDrDw, Dw);
-
-  UIrDw = CLG_(get_eventset)("UIrDw", sizeOfUseIr + Dw->size);
-  CLG_(add_eventset)(UIrDw, Use);
-  off_UIrDw_Ir   = CLG_(add_eventset)(UIrDw, Ir);
-  off_UIrDw_Dw   = CLG_(add_eventset)(UIrDw, Dw);
-
-  UIrDwDr  = CLG_(get_eventset)("IrDwDr", sizeOfUseIr + Dw->size + Dr->size);
-  CLG_(add_eventset)(UIrDwDr, Use);
-  off_UIrDwDr_Ir    = CLG_(add_eventset)(UIrDrDw, Ir);
-  off_UIrDwDr_Dw    = CLG_(add_eventset)(UIrDrDw, Dw);
-  off_UIrDwDr_Dr    = CLG_(add_eventset)(UIrDrDw, Dr);
-
-
-  // the "full" event set is used as global counter and for aggregation
-  if (CLG_(clo).collect_alloc)   max_user += 2;
-  if (CLG_(clo).collect_systime) max_user += 2;
-  full = CLG_(get_eventset)("full",
-                           sizeOfUseIr + Dr->size + Dw->size + max_user);
-  CLG_(add_eventset)(full, Use);
-  CLG_(sets).off_full_Ir   = CLG_(add_eventset)(full, Ir);
-  CLG_(sets).off_full_Dr   = CLG_(add_eventset)(full, Dr);
-  CLG_(sets).off_full_Dw   = CLG_(add_eventset)(full, Dw);
-  if (CLG_(clo).collect_alloc) {
-      e1 = CLG_(register_eventtype)("allocCount");
-      e2 = CLG_(register_eventtype)("allocSize");
-      CLG_(sets).off_full_alloc =  CLG_(add_dep_event2)(full, e1,e2);
-  }
-  if (CLG_(clo).collect_systime) {
-      e1 = CLG_(register_eventtype)("sysCount");
-      e2 = CLG_(register_eventtype)("sysTime");
-      CLG_(sets).off_full_systime =  CLG_(add_dep_event2)(full, e1,e2);
-  }
+    if (CLG_(clo).collect_systime)
+       CLG_(register_event_group2)(EG_SYS, "sysCount", "sysTime");
 
-  CLG_(sets).Use = Use;
-  CLG_(sets).Ir  = Ir;
-  CLG_(sets).Dr  = Dr;
-  CLG_(sets).Dw  = Dw;
-  CLG_(sets).UIr  = UIr;
-  CLG_(sets).UIrDr = UIrDr;
-  CLG_(sets).UIrDrDw  = UIrDrDw;
-  CLG_(sets).UIrDw = UIrDw;
-  CLG_(sets).UIrDwDr  = UIrDwDr;
-  CLG_(sets).full = full;
-
-
-  CLG_DEBUGIF(1) {
-    CLG_DEBUG(1, "EventSets:\n");
-    CLG_(print_eventset)(-2, Use);
-    CLG_(print_eventset)(-2, Ir);
-    CLG_(print_eventset)(-2, Dr);
-    CLG_(print_eventset)(-2, Dw);
-    CLG_(print_eventset)(-2, full);
-  }
+    // event set used as base for instruction self cost
+    CLG_(sets).base = CLG_(get_event_set2)(EG_USE, EG_IR);
 
-  /* Not-existing events are silently ignored */
-  CLG_(dumpmap) = CLG_(get_eventmapping)(full);
-  CLG_(append_event)(CLG_(dumpmap), "Ir");
-  CLG_(append_event)(CLG_(dumpmap), "Dr");
-  CLG_(append_event)(CLG_(dumpmap), "Dw");
-  CLG_(append_event)(CLG_(dumpmap), "I1mr");
-  CLG_(append_event)(CLG_(dumpmap), "D1mr");
-  CLG_(append_event)(CLG_(dumpmap), "D1mw");
-  CLG_(append_event)(CLG_(dumpmap), "I2mr");
-  CLG_(append_event)(CLG_(dumpmap), "D2mr");
-  CLG_(append_event)(CLG_(dumpmap), "D2mw");
-  CLG_(append_event)(CLG_(dumpmap), "I2dmr");
-  CLG_(append_event)(CLG_(dumpmap), "D2dmr");
-  CLG_(append_event)(CLG_(dumpmap), "D2dmw");
-  CLG_(append_event)(CLG_(dumpmap), "AcCost1");
-  CLG_(append_event)(CLG_(dumpmap), "SpLoss1");
-  CLG_(append_event)(CLG_(dumpmap), "AcCost2");
-  CLG_(append_event)(CLG_(dumpmap), "SpLoss2");
-  CLG_(append_event)(CLG_(dumpmap), "allocCount");
-  CLG_(append_event)(CLG_(dumpmap), "allocSize");
-  CLG_(append_event)(CLG_(dumpmap), "sysCount");
-  CLG_(append_event)(CLG_(dumpmap), "sysTime");
+    // event set comprising all event groups, used for inclusive cost
+    CLG_(sets).full = CLG_(add_event_group2)(CLG_(sets).base, EG_DR, EG_DW);
+    CLG_(sets).full = CLG_(add_event_group2)(CLG_(sets).full, EG_ALLOC, EG_SYS);
 
-}
-
-
-
-static
-void add_and_zero_Dx(EventSet* es, SimCost dst, ULong* cost)
-{
-  /* if eventset use is defined, it is always first (hardcoded!) */
-  CLG_(add_and_zero_cost)( CLG_(sets).Use, dst, cost);
+    CLG_DEBUGIF(1) {
+       CLG_DEBUG(1, "EventSets:\n");
+       CLG_(print_eventset)(-2, CLG_(sets).base);
+       CLG_(print_eventset)(-2, CLG_(sets).full);
+    }
 
-  if (es == CLG_(sets).UIr) {
-    CLG_(add_and_zero_cost)( CLG_(sets).Ir, dst + CLG_(sets).off_full_Ir,
-                           cost + off_UIr_Ir);
-  }
-  else if (es == CLG_(sets).UIrDr) {
-    CLG_(add_and_zero_cost)( CLG_(sets).Ir, dst + CLG_(sets).off_full_Ir,
-                           cost + off_UIrDr_Ir);
-    CLG_(add_and_zero_cost)( CLG_(sets).Dr, dst + CLG_(sets).off_full_Dr,
-                           cost + off_UIrDr_Dr);
-  }
-  else if (es == CLG_(sets).UIrDrDw) {
-    CLG_(add_and_zero_cost)( CLG_(sets).Ir, dst + CLG_(sets).off_full_Ir,
-                           cost + off_UIrDrDw_Ir);
-    CLG_(add_and_zero_cost)( CLG_(sets).Dr, dst + CLG_(sets).off_full_Dr,
-                           cost + off_UIrDrDw_Dr);
-    CLG_(add_and_zero_cost)( CLG_(sets).Dw, dst + CLG_(sets).off_full_Dw,
-                           cost + off_UIrDrDw_Dw);
-  }
-  else if (es == CLG_(sets).UIrDw) {
-      CLG_(add_and_zero_cost)( CLG_(sets).Ir, dst + CLG_(sets).off_full_Ir,
-                              cost + off_UIrDw_Ir);
-      CLG_(add_and_zero_cost)( CLG_(sets).Dw, dst + CLG_(sets).off_full_Dw,
-                              cost + off_UIrDw_Dw);
-  }
-  else if (es == CLG_(sets).UIrDwDr) {
-    CLG_(add_and_zero_cost)( CLG_(sets).Ir, dst + CLG_(sets).off_full_Ir,
-                           cost + off_UIrDwDr_Ir);
-    CLG_(add_and_zero_cost)( CLG_(sets).Dw, dst + CLG_(sets).off_full_Dw,
-                           cost + off_UIrDwDr_Dw);
-    CLG_(add_and_zero_cost)( CLG_(sets).Dr, dst + CLG_(sets).off_full_Dr,
-                            cost + off_UIrDwDr_Dr);
-  }
-  else CLG_ASSERT(0);
+    /* Not-existing events are silently ignored */
+    CLG_(dumpmap) = CLG_(get_eventmapping)(CLG_(sets).full);
+    CLG_(append_event)(CLG_(dumpmap), "Ir");
+    CLG_(append_event)(CLG_(dumpmap), "Dr");
+    CLG_(append_event)(CLG_(dumpmap), "Dw");
+    CLG_(append_event)(CLG_(dumpmap), "I1mr");
+    CLG_(append_event)(CLG_(dumpmap), "D1mr");
+    CLG_(append_event)(CLG_(dumpmap), "D1mw");
+    CLG_(append_event)(CLG_(dumpmap), "I2mr");
+    CLG_(append_event)(CLG_(dumpmap), "D2mr");
+    CLG_(append_event)(CLG_(dumpmap), "D2mw");
+    CLG_(append_event)(CLG_(dumpmap), "I2dmr");
+    CLG_(append_event)(CLG_(dumpmap), "D2dmr");
+    CLG_(append_event)(CLG_(dumpmap), "D2dmw");
+    CLG_(append_event)(CLG_(dumpmap), "AcCost1");
+    CLG_(append_event)(CLG_(dumpmap), "SpLoss1");
+    CLG_(append_event)(CLG_(dumpmap), "AcCost2");
+    CLG_(append_event)(CLG_(dumpmap), "SpLoss2");
+    CLG_(append_event)(CLG_(dumpmap), "allocCount");
+    CLG_(append_event)(CLG_(dumpmap), "allocSize");
+    CLG_(append_event)(CLG_(dumpmap), "sysCount");
+    CLG_(append_event)(CLG_(dumpmap), "sysTime");
 }
 
+
 /* this is called at dump time for every instruction executed */
 static void cachesim_add_icost(SimCost cost, BBCC* bbcc,
                               InstrInfo* ii, ULong exe_count)
 {
-  if (!CLG_(clo).simulate_cache)
-      cost[CLG_(sets).off_full_Ir] += exe_count;
-  else {
-
-#if 0
-/* There is always a trivial case where exe_count and Ir can be
- * slightly different because ecounter is updated when executing
- * the next BB. E.g. for last BB executed, or when toggling collection
- */
-      /* FIXME: Hardcoded that each eventset has Ir as first */
-      if ((bbcc->cost + ii->cost_offset)[0] != exe_count) {
-         VG_(printf)("==> Ir %llu, exe %llu\n",
-                     (bbcc->cost + ii->cost_offset)[0], exe_count);
-         CLG_(print_bbcc_cost)(-2, bbcc);
-         //CLG_ASSERT((bbcc->cost + ii->cost_offset)[0] == exe_count);
-      }
-#endif
-
-      add_and_zero_Dx(ii->eventset, cost,
-                     bbcc->cost + ii->cost_offset);
-  }
+    if (!CLG_(clo).simulate_cache)
+       cost[ fullOffset(EG_IR) ] += exe_count;
+    else
+       CLG_(add_and_zero_cost2)( CLG_(sets).full, cost,
+                                 ii->eventset, bbcc->cost + ii->cost_offset);
 }
 
 static