Apply peeling for loops like:
for (i = 0; i < n; i++) {
if (i >= *a_bound) assert(0); s += a[i]; if (i >= *b_bound) assert(0); s += b[i];
}
Here load *a_bound is safe to speculate and it should be hoisted out of the loop,
However, *b_bound is not safe to speculate, because this will potentially change program behavior:
If we load "b_bound" before the loop and "b_bound" is null we throw an exception, which is wrong if we exit at "i >= *a_bound".
After peeling *b_bound is safe to speculate and hoist it out of the loop (because if it is null - we throw an exception before the loop):
if (0 >= *a_bound) assert(0);
s += a[0];
if (0 >= *b_bound) assert(0);
s += b[0];
for (i = 1; i < n; i++) {
if (i >= *a_bound) assert(0); s += a[i]; if (i >= *b_bound) assert(0); s += b[i];
}
This will break semantics of this method in case if this block is exit/unreachable/etc.