Callgrind: event sets now consist of event groups

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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/callgrind/bbcc.c b/callgrind/bbcc.c
index ac7c21e..66d609c 100644
--- a/callgrind/bbcc.c
+++ b/callgrind/bbcc.c
@@ -601,7 +601,7 @@
 	  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;
 	  }
       }
 
diff --git a/callgrind/debug.c b/callgrind/debug.c
index b89b753..966aa74 100644
--- a/callgrind/debug.c
+++ b/callgrind/debug.c
@@ -137,40 +137,46 @@
 
 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 (!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);
+    if (s<0) {
+	s = -s;
+	print_indent(s);
     }
-  }
-  VG_(printf)("\n");
+
+    if (!es) {
+	VG_(printf)("(EventSet not set)\n");
+	return;
+    }
+
+    VG_(printf)("EventSet %d (%d groups, size %d):",
+		es->mask, es->count, es->size);
+
+    if (es->count == 0) {
+	VG_(printf)("-\n");
+	return;
+    }
+
+    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 @@
       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]);
+    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++) {
 
-    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++;
+	    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_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]");
 }
diff --git a/callgrind/events.c b/callgrind/events.c
index c065414..fb5a77a 100644
--- a/callgrind/events.c
+++ b/callgrind/events.c
@@ -28,550 +28,534 @@
 
 #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++;
+    for(i=0; i< MAX_EVENTSET_COUNT; i++)
+	eventSetTable[i] = 0;
 
-  return et;
+    eventSets_initialized = 1;
+ }
+
+static
+EventGroup* new_event_group(int id, int n)
+{
+    EventGroup* eg;
+
+    initialize_event_sets();
+
+    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;
+}
+
+EventGroup* CLG_(register_event_group) (int id, Char* n1)
+{
+    EventGroup* eg = new_event_group(id, 1);
+    eg->name[0] = n1;
+
+    return eg;
+}
+
+EventGroup* CLG_(register_event_group2)(int id, Char* n1, Char* n2)
+{
+    EventGroup* eg = new_event_group(id, 2);
+    eg->name[0] = n1;
+    eg->name[1] = n2;
+
+    return eg;
+}
+
+EventGroup* CLG_(register_event_group3)(int id, Char* n1, Char* n2, Char* n3)
+{
+    EventGroup* eg = new_event_group(id, 3);
+    eg->name[0] = n1;
+    eg->name[1] = n2;
+    eg->name[2] = n3;
+
+    return eg;
+}
+
+EventGroup* CLG_(register_event_group4)(int id,
+					Char* n1, Char* n2, Char* n3, Char* n4)
+{
+    EventGroup* eg = new_event_group(id, 4);
+    eg->name[0] = n1;
+    eg->name[1] = n2;
+    eg->name[2] = n3;
+    eg->name[3] = n4;
+
+    return eg;
+}
+
+EventGroup* CLG_(get_event_group)(int id)
+{
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+
+    return eventGroup[id];
 }
 
 
-EventType* CLG_(get_eventtype)(Char* name)
+static
+EventSet* eventset_from_mask(UInt mask)
 {
-  Int i;
+    EventSet* es;
+    Int i, count, offset;
 
-  for(i=0;i<eventtype_count;i++)
-    if (VG_(strcmp)(eventtype[i].name, name) == 0)
-      return eventtype+i;
-  return 0;
+    if (mask >= MAX_EVENTSET_COUNT) return 0;
+
+    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;
 }
 
-EventType* CLG_(get_eventtype_byindex)(Int id)
+EventSet* CLG_(get_event_set)(Int id)
 {
-  if ((id >= 0) && (id < eventtype_count))
-    return eventtype+id;
-  return 0;
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+    return eventset_from_mask(1u << id);
 }
 
-/* Allocate space for an event set */
-EventSet* CLG_(get_eventset)(Char* n, Int capacity)
+EventSet* CLG_(get_event_set2)(Int id1, Int id2)
 {
-  EventSet* es;
-
-  es = (EventSet*) CLG_MALLOC("cl.events.geSet.1",
-                               sizeof(EventSet) +
-			       capacity * sizeof(EventSetEntry));
-  es->capacity = capacity;
-  es->size = 0;
-  es->name = n;
-
-  return es;
+    CLG_ASSERT(id1>=0 && id1<MAX_EVENTGROUP_COUNT);
+    CLG_ASSERT(id2>=0 && id2<MAX_EVENTGROUP_COUNT);
+    return eventset_from_mask((1u << id1) | (1u << id2));
 }
 
-/* Incorporate a event type into a set, get start offset */
-Int CLG_(add_eventtype)(EventSet* es, EventType* t)
+EventSet* CLG_(get_event_set3)(Int id1, Int id2, Int id3)
 {
-  Int offset = es->size;
-  if (es->capacity - offset < 1) return -1;
-
-  es->size++;
-  es->e[offset].type = t;
-  es->e[offset].nextTop = es->size;
-
-  return offset;
+    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));
 }
 
-/* Incorporate one event set into another, get start offset */
-Int CLG_(add_eventset)(EventSet* dst, EventSet* src)
+EventSet* CLG_(add_event_group)(EventSet* es, Int id)
 {
-  Int offset = dst->size, i;
-  if (!src || (src->size == 0)) return offset;
-
-  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 offset;
+    CLG_ASSERT(id>=0 && id<MAX_EVENTGROUP_COUNT);
+    if (!es) es = eventset_from_mask(0);
+    return eventset_from_mask(es->mask | (1u << id));
 }
 
-/* Incorporate two event types into a set, with second < first */
-Int CLG_(add_dep_event2)(EventSet* es, EventType* e1, EventType* e2)
+EventSet* CLG_(add_event_group2)(EventSet* es, Int id1, Int id2)
 {
-  Int offset = es->size;
-
-  if (es->capacity - offset < 2) return -1;
-
-  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;
+    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));
 }
 
-/* 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_(add_event_set)(EventSet* es1, EventSet* es2)
 {
-  Int offset = es->size;
-
-  if (es->capacity - offset < 3) return -1;
-
-  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;
+    if (!es1) es1 = eventset_from_mask(0);
+    if (!es2) es2 = eventset_from_mask(0);
+    return eventset_from_mask(es1->mask | es2->mask);
 }
 
-Int CLG_(add_dep_event4)(EventSet* es,
-			EventType* e1, EventType* e2,
-			EventType* e3, EventType* e4)
-{
-  Int offset = es->size;
-
-  if (es->capacity - offset < 4) return -1;
-
-  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;
-}
-
-/* Returns number of characters written */
 Int CLG_(sprint_eventset)(Char* buf, EventSet* es)
 {
-  Int i, pos = 0;
+    Int i, j, pos;
+    UInt mask;
+    EventGroup* eg;
 
-  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;
 
-  return pos;
+    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;
 }
 
+
 /* 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;
+    Int i;
+    ULong* dst;
 
-  if (!src) return;
-  CLG_ASSERT(pdst != 0);
+    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++;
+    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;
+    Int i;
+    Bool is_nonzero = False;
 
-  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);
-  }
+    CLG_ASSERT((es != 0) && (dst != 0));
+    if (!src) return False;
 
-  if (!es || !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)
+Bool CLG_(add_and_zero_cost2)(EventSet* esDst, ULong* dst,
+			      EventSet* esSrc, ULong* src)
 {
-  Int i;
-  ULong* dst;
+    Int i,j;
+    Bool is_nonzero = False;
+    UInt mask;
+    EventGroup *eg;
+    ULong *egDst, *egSrc;
 
-  if (!src) return False;
+    CLG_ASSERT((esDst != 0) && (dst != 0) && (esSrc != 0));
+    if (!src) return False;
 
-  i = 0;
-  while(1) {
-    if (i >= es->size) return False;
-    if (src[i] != 0) break;
-    i = es->e[i].nextTop;
-  }
+    for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
+	if ((esSrc->mask & mask)==0) continue;
+	if (eventGroup[i] ==0) continue;
 
-  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;
+	/* 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)
+Bool CLG_(add_diff_cost_lz)(EventSet* es, ULong** pdst, ULong* old, ULong* new_cost)
 {
-  Int i;
-  ULong* dst;
+    Int i;
+    ULong* dst;
+    Bool is_nonzero = False;
 
-  if (!old && !new_cost) return False;
-  CLG_ASSERT(old && new_cost);
+    CLG_ASSERT((es != 0) && (pdst != 0));
+    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++;
+    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;
+    Int i, j, offset = 0;
+    UInt mask;
+    EventGroup* eg;
 
-  CLG_ASSERT(em != 0);
+    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;
 
-  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;
+	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->index[em->size] = i;
-  em->size++;
+	    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;
+    pos = VG_(sprintf)(buf, "%llu", c[em->entry[0].offset]);
 
-  while(i<em->size) {
-    if (c[em->index[i]] == 0) {
-      skipped++;
-      i++;
-    }
-    else {
-      while(skipped>0) {
+    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;
 }
diff --git a/callgrind/events.h b/callgrind/events.h
index c3ddbe3..d892ccb 100644
--- a/callgrind/events.h
+++ b/callgrind/events.h
@@ -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;
-};
-
-EventType* CLG_(register_eventtype)(Char*);
-EventType* CLG_(get_eventtype)(Char*);
-EventType* CLG_(get_eventtype_byindex)(Int id);
-
-/* 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.
+/* 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.
  */
-typedef struct _EventSetEntry EventSetEntry;
-struct _EventSetEntry {
-  EventType* type;
-  Int nextTop;
+
+#define MAX_EVENTGROUP_COUNT 10
+
+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);
+
+/* Event sets are defined by event groups they consist of. */
+
 typedef struct _EventSet EventSet;
 struct _EventSet {
-  Char* name;
-  Int size;
-  Int capacity;
-  EventSetEntry e[0];
-};
+    /* 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];
+ };
 
-
-/* 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];
-};
-
-  
-/* 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 */
+/* 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_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 @@
 /* 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 @@
 /* Returns number of characters written */
 Int CLG_(sprint_mappingcost)(Char* buf, EventMapping*, ULong*);
 
-#endif /* CG_EVENTS */
+#endif /* CLG_EVENTS */
diff --git a/callgrind/global.h b/callgrind/global.h
index 367f2d7..8f33ff3 100644
--- a/callgrind/global.h
+++ b/callgrind/global.h
@@ -671,6 +671,21 @@
     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_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],
diff --git a/callgrind/main.c b/callgrind/main.c
index 3f02517..4aa3ce7 100644
--- a/callgrind/main.c
+++ b/callgrind/main.c
@@ -273,34 +273,18 @@
 	   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 @@
 {
   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 @@
 #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 @@
 
    (*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) );
 
diff --git a/callgrind/sim.c b/callgrind/sim.c
index e79d9e2..a69f760 100644
--- a/callgrind/sim.c
+++ b/callgrind/sim.c
@@ -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 @@
  * - 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 @@
 	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 @@
 
     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 @@
 
     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 @@
 	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 @@
     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 @@
 	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 @@
     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 @@
 
   /* 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 @@
 
   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 @@
   /* 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 @@
 	       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 @@
 	       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 @@
 
 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;
+    // 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");
 
-  // 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);
+    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 { // 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)(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);
+
+    if (CLG_(clo).collect_alloc)
+	CLG_(register_event_group2)(EG_ALLOC, "allocCount", "allocSize");
+
+    if (CLG_(clo).collect_systime)
+	CLG_(register_event_group2)(EG_SYS, "sysCount", "sysTime");
+
+    // event set used as base for instruction self cost
+    CLG_(sets).base = CLG_(get_event_set2)(EG_USE, EG_IR);
+
+    // 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);
+
+    CLG_DEBUGIF(1) {
+	CLG_DEBUG(1, "EventSets:\n");
+	CLG_(print_eventset)(-2, CLG_(sets).base);
+	CLG_(print_eventset)(-2, CLG_(sets).full);
     }
-    else
-      CLG_(add_dep_event3)(Dw, e1,e2,e3);
 
-  }
-  else {
-    e1 = CLG_(register_eventtype)("Ir");
-    CLG_(add_eventtype)(Ir, e1);
-  }
-
-  // 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);
-  }
-
-  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);
-  }
-
-  /* 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");
-
+    /* 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");
 }
 
 
-
-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);
-
-  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);
-}
-
 /* 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