Consider the following piece of code:
void innermost_loop(int i, double d1, double d2, double delta, int n, double cells[n]) { int j; const double d1d = d1 * delta; const double d2d = d2 * delta; for (j = 0; j <= i; j++) cells[j] = d1d * cells[j + 1] + d2d * cells[j]; }
When compiling at -Ofast level, after the "Reassociate expressions"
pass, this code is transformed into an equivalent of:
int j; for (j = 0; j <= i; j++) cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta;
Effectively, the computation of those loop invariants isn't done
before the loop anymore, we have one extra multiplication on each
loop iteration instead. Sadly, this results in a significant
performance hit.
Similarly, specifically crafted user code will also experience
inability to hoist those invariants.
This patch is solving this issue by adding the ability to undo such
reassociation into the LICM pass. Note that for doing such
transformation this pass requires the same conditions as the
"Reassociate expressions" pass, namely, the involved binary operators
must have the reassociations allowed (e.g. by specifying the fast
attribute) and they must have single use only.
Some parts of this patch were suggested by Nikita Popov.
Up to you but I think "licm-max-num-fp-reassociations" or "licm-fp-reassociation-cap" would be more in keeping with the existing naming of licm options.