# Restoring SSA form

Hello,
for some my use case, I'd like to temporary break SSA property and then ask
LLVM to restore it. Here's more details:

if (i < 0) {
i = -i;
}

This is a C code example. I'm trying to create a value range analysis, which
will determine, that after this code, 'i' is non-negative. In SSA form, this
will become

i = 0;
if (i < 0) {
i.2 = -i;
}
i.3 = phi(i, i.2);

I'll assign value ranges to i, i.2, i.3, do some iteration and get necessary
results. Now consider another case:

i = 0;
if (i > 0) {
foo(i);
}

Here's 'foo' is always called with positive value. However, the value range
assigned to 'i' variable can be only [-inf, +inf], because uses of 'i'
outside of condition can get any value. So, I'd like to convert the above to:

i = 0;
if (i > 0) {
i = change_value_range(i);
foo(i);
}

where 'change_value_range' is some artificial instruction. After that, I'd ask
LLVM to restore SSA property, giving:

i = 0;
if (i > 0) {
i.2 = change_value_range(i);
foo(i.2);
}
i.3 = phi(i, i.2)

And then will do my analysis as usual. This is a long-winded background, and
the question is: how to I "restore SSA property"? Sure, both dominance
frontier and dominator tree are available, so I can just try to impelement
the SSA constructon algorithm by hand, but is there a smarter way? The
Mem2Reg pass is too specialised to work here.

Volodya

Here's 'foo' is always called with positive value. However, the value range
assigned to 'i' variable can be only [-inf, +inf], because uses of 'i'
outside of condition can get any value. So, I'd like to convert the above to:

i = 0;
if (i > 0) {
i = change_value_range(i);
foo(i);
}

I don't know why you said that mem2reg is too specialized to work for your problem, but at least for the example you gave you can make it work. If you converted the above code to the following:

i = 0;
if (i > 0) {
tmp = i;
i = change_value_range(tmp);
tmp = i;
foo(tmp);
}

and then replace i with an alloca'd location, mem2reg should restore SSA just fine (the tmp is needed so that the alloca pointer is not passed to change_value_range() or foo())

I don't know why you said that mem2reg is too specialized to work for
your problem, but at least for the example you gave you can make it
work. If you converted the above code to the following:

i = 0;
if (i > 0) {
tmp = i;
i = change_value_range(tmp);
tmp = i;
foo(tmp);
}

and then replace i with an alloca'd location,

Seems like a good idea!

mem2reg should restore
SSA just fine (the tmp is needed so that the alloca pointer is not
passed to change_value_range() or foo())

Thanks, I'll try this.

- Volodya