First, thanks. This is a very very long time coming

Second, for those watching, note that pretty much all of the improvements and missing cases, including load forwarding/coercion, etc, actually are done.

It’s more a matter of cleaning them up, breaking it down, and submitting it, than “implementing them”.

The main experimentation at this point is “can we do it cleaner” not “can we do it”

It’s also important to note that this new GVN also treats loads/stores in a unified way with scalars, unlike current GVN (which has no load or store value numbering).

So it will happily discover complex load/store relations (though there is some improvements we can still make here)

For example:

int vnum_test8(int *data)

{

int i;

int stop = data[3];

int m = data[4];

int n = m;

int p;

for (i=0; i<stop; i++) {

int k = data[2];

data[k] = 2;

data[0] = m - n;

k = data[1];

m = m + k;

n = n + k;

p = data[0];

}

return p;

}

LLVM’s current GVN will eliminate a single load here[1]

NewGVN will calculate that m and n are equal, that m-n is 0, that p is 0

It’s not quite perfect yet, i haven’t fixed store handling, so the following is missed:

int a;

int *p;

// LLVM is too smart and if we don’t do this, realizes *p is a store to undef

void foo(){

p = &a;

}

int main(int argc, char **argv) {

int result;

foo();

*p = 2;

if (argc)

*p = 2;

result = *p;

return result;

}

Here, current LLVM GVN will do nothing, because it can’t understand anything really about the stores.

GCC’s GVN will determine result is 2.

NewGVN is not quite that smart yet (it require a little work to what we do to stores, and value numbering memory ssa versions)

This issue compounds if you have conditional stores of the same value.

So, for example, if you add:

if (i < 30)

data[0] = 0;

to the first case.

GCC can still determine p is 0.

Currently, NewGVN cannot.

–Dan