[Transforms][LICM] Add the ability to undo unprofitable reassociation
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. Reviewed By: huntergr, nikic, paulwalker-arm Differential Revision: https://reviews.llvm.org/D152281
Loading
Please sign in to comment