https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81953
kelvin at gcc dot gnu.org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |kelvin at gcc dot gnu.org Assignee|unassigned at gcc dot gnu.org |kelvin at gcc dot gnu.org --- Comment #5 from kelvin at gcc dot gnu.org --- I am going to experiment with better selection of the sink block. Suppose there are multiple blocks C1, C2, ... , CN that are dominated by the original defining expression and post-dominated by the block that uses the defined value. The preferred sink location is the beginning of the basic block Ci, where Ci dominates Cj for 1 <= j <= N. In other words, the sink destination is the first control point at which eventual control flow to the definition's use block is no longer conditional. By sinking to this control point, we "minimize" the lifetimes of any variables that contribute to evaluation of the original definition, and we increase the amount of scheduling flexibility, "maximizing" the amount of time available to finish calculation of value before the definition is used. I'm not entirely confident this is a good tradeoff in general. By moving the sink spot forward, I may be creating a different kind of register pressure. Consider this third variation on the theme: void bar(); int j, x, y, z; void foo (int a, int b) { int l, m, n; l = a + 3 * b; m = a * 5 + b; n = a * 7 + b * 9; if (a != 5) { /* my heuristic moves computations of l, m, n to here, resulting in increased register pressure across call to bar (), since now we have b, l, m, and n in registers. that's no worse than the code as written, but a better solution would have computed these expressions after bar (), maintaining only a and b in registers across the call to bar (). */ bar (); if (b != 3; x = 3; else x = 5; j = l; y = m; z = n; } } I need to ponder further before experimenting. Feel free to share thoughts and advice. This is a new area for me. Am using this "exercise" to become more familiar with middle end.