Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 48 additions & 43 deletions VEX/priv/ir_opt.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,14 @@
hashing, but it's not clear whether or not this would really be any
faster. */

/* The bindings are kept packed in [0 .. used-1]: deleting a binding
moves the last one into the hole rather than leaving a tombstone
behind. That keeps every scan proportional to the number of live
bindings, which matters because the environments are wiped wholesale
(see the |used = 0| sites below) far more often than they are read. */

typedef
struct {
Bool* inuse;
HWord* key;
HWord* val;
Int size;
Expand All @@ -189,21 +194,33 @@ static HashHW* newHHW ( void )
HashHW* h = LibVEX_Alloc_inline(sizeof(HashHW));
h->size = 8;
h->used = 0;
h->inuse = LibVEX_Alloc_inline(h->size * sizeof(Bool));
h->key = LibVEX_Alloc_inline(h->size * sizeof(HWord));
h->val = LibVEX_Alloc_inline(h->size * sizeof(HWord));
return h;
}


/* Delete the binding at index i. The map is unordered, so the hole is
filled with the last binding. Callers iterating over the map must
therefore re-examine index i afterwards. */

static inline void deleteHHW ( HashHW* h, Int i )
{
vassert(i >= 0 && i < h->used);
h->used--;
h->key[i] = h->key[h->used];
h->val[i] = h->val[h->used];
}


/* Look up key in the map. */

static Bool lookupHHW ( const HashHW* h, /*OUT*/HWord* val, HWord key )
{
Int i;
/* vex_printf("lookupHHW(%llx)\n", key ); */
for (i = 0; i < h->used; i++) {
if (h->inuse[i] && h->key[i] == key) {
if (h->key[i] == key) {
if (val)
*val = h->val[i];
return True;
Expand All @@ -217,12 +234,12 @@ static Bool lookupHHW ( const HashHW* h, /*OUT*/HWord* val, HWord key )

static void addToHHW ( HashHW* h, HWord key, HWord val )
{
Int i, j;
Int i;
/* vex_printf("addToHHW(%llx, %llx)\n", key, val); */

/* Find and replace existing binding, if any. */
for (i = 0; i < h->used; i++) {
if (h->inuse[i] && h->key[i] == key) {
if (h->key[i] == key) {
h->val[i] = val;
return;
}
Expand All @@ -231,26 +248,19 @@ static void addToHHW ( HashHW* h, HWord key, HWord val )
/* Ensure a space is available. */
if (h->used == h->size) {
/* Copy into arrays twice the size. */
Bool* inuse2 = LibVEX_Alloc_inline(2 * h->size * sizeof(Bool));
HWord* key2 = LibVEX_Alloc_inline(2 * h->size * sizeof(HWord));
HWord* val2 = LibVEX_Alloc_inline(2 * h->size * sizeof(HWord));
for (i = j = 0; i < h->size; i++) {
if (!h->inuse[i]) continue;
inuse2[j] = True;
key2[j] = h->key[i];
val2[j] = h->val[i];
j++;
for (i = 0; i < h->used; i++) {
key2[i] = h->key[i];
val2[i] = h->val[i];
}
h->used = j;
h->size *= 2;
h->inuse = inuse2;
h->key = key2;
h->val = val2;
}

/* Finally, add it. */
vassert(h->used < h->size);
h->inuse[h->used] = True;
h->key[h->used] = key;
h->val[h->used] = val;
h->used++;
Expand Down Expand Up @@ -594,17 +604,16 @@ static void invalidateOverlaps ( HashHW* h, UInt k_lo, UInt k_hi )
.. k_hi) */
/* vex_printf("invalidate %d .. %d\n", k_lo, k_hi ); */

for (j = 0; j < h->used; j++) {
if (!h->inuse[j])
continue;
for (j = 0; j < h->used; /* see below */) {
e_lo = (((UInt)h->key[j]) >> 16) & 0xFFFF;
e_hi = ((UInt)h->key[j]) & 0xFFFF;
vassert(e_lo <= e_hi);
if (e_hi < k_lo || k_hi < e_lo)
continue; /* no overlap possible */
j++; /* no overlap possible */
else
/* overlap; invalidate */
h->inuse[j] = False;
/* overlap; invalidate. The last binding is moved into slot j,
so re-examine j rather than advancing. */
deleteHHW(h, j);
}
}

Expand Down Expand Up @@ -686,8 +695,7 @@ static void redundant_get_removal_BB ( IRSB* bb )
}
if (writes) {
/* dump the entire env (not clever, but correct ...) */
for (j = 0; j < env->used; j++)
env->inuse[j] = False;
env->used = 0;
if (0) vex_printf("rGET: trash env due to dirty helper\n");
}
}
Expand Down Expand Up @@ -772,8 +780,7 @@ static void handle_gets_Stmt (
case Ist_Dirty:
case Ist_CAS:
case Ist_LLSC:
for (j = 0; j < env->used; j++)
env->inuse[j] = False;
env->used = 0;
break;

/* all other cases are boring. */
Expand Down Expand Up @@ -831,8 +838,7 @@ static void handle_gets_Stmt (
case VexRegUpdAllregsAtMemAccess:
/* Precise exceptions required at mem access.
Flush all guest state. */
for (j = 0; j < env->used; j++)
env->inuse[j] = False;
env->used = 0;
break;
case VexRegUpdSpAtMemAccess:
/* We need to dump the stack pointer
Expand All @@ -841,15 +847,15 @@ static void handle_gets_Stmt (
to verify only the sp is to be checked. */
/* fallthrough */
case VexRegUpdUnwindregsAtMemAccess:
for (j = 0; j < env->used; j++) {
if (!env->inuse[j])
continue;
for (j = 0; j < env->used; /* see below */) {
/* Just flush the minimal amount required, as computed by
preciseMemExnsFn. */
HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
HWord k_hi = env->key[j] & 0xFFFF;
if (preciseMemExnsFn( k_lo, k_hi, pxControl ))
env->inuse[j] = False;
deleteHHW(env, j); /* re-examine slot j */
else
j++;
}
break;
case VexRegUpdAllregsAtEachInsn:
Expand Down Expand Up @@ -886,7 +892,7 @@ static void redundant_put_removal_BB (
VexRegisterUpdates pxControl
)
{
Int i, j;
Int i;
Bool isPut;
IRStmt* st;
UInt key = 0; /* keep gcc -O happy */
Expand Down Expand Up @@ -931,8 +937,7 @@ static void redundant_put_removal_BB (
// typeOfIRConst(st->Ist.Exit.dst));
//re_add = lookupHHW(env, NULL, key);
/* (2) */
for (j = 0; j < env->used; j++)
env->inuse[j] = False;
env->used = 0;
/* (3) */
//if (0 && re_add)
// addToHHW(env, (HWord)key, 0);
Expand Down Expand Up @@ -4578,12 +4583,12 @@ static Bool do_cse_BB ( IRSB* bb, Bool allowLoadsToBeCSEd )
}

if (paranoia > 0) {
for (j = 0; j < aenv->used; j++) {
if (!aenv->inuse[j])
continue;
for (j = 0; j < aenv->used; /* see below */) {
ae = (AvailExpr*)aenv->key[j];
if (ae->tag != GetIt && ae->tag != Load)
if (ae->tag != GetIt && ae->tag != Load) {
j++;
continue;
}
invalidate = False;
if (paranoia >= 2) {
invalidate = True;
Expand Down Expand Up @@ -4623,10 +4628,10 @@ static Bool do_cse_BB ( IRSB* bb, Bool allowLoadsToBeCSEd )
vpanic("do_cse_BB(2)");
}

if (invalidate) {
aenv->inuse[j] = False;
aenv->key[j] = (HWord)NULL; /* be sure */
}
if (invalidate)
deleteHHW(aenv, j); /* re-examine slot j */
else
j++;
} /* for j */
} /* paranoia > 0 */

Expand All @@ -4649,7 +4654,7 @@ static Bool do_cse_BB ( IRSB* bb, Bool allowLoadsToBeCSEd )

/* search aenv for eprime, unfortunately the hard way */
for (j = 0; j < aenv->used; j++)
if (aenv->inuse[j] && eq_AvailExpr(eprime, (AvailExpr*)aenv->key[j]))
if (eq_AvailExpr(eprime, (AvailExpr*)aenv->key[j]))
break;

if (j < aenv->used) {
Expand Down
Loading