The tighten pass is currently scheduled before lower, "to avoid splitting naturally paired instructions such as CMP/SET". Doing tighten later benefits from the removal of values enabled by lowering and lowered CSE. Empirically, moving tighten just before phiTighten generates slightly better code: fewer bytes of instructions on average, and as far I have checked, a pareto improvement on stack use.
Moving tighten after lower will allow us to do this TODO in the code:
for _, a := range v.Args {
switch a.Op {
case OpConst8, OpConst16, OpConst32, OpConst64, OpAddr:
// Probably foldable into v, don't count as an argument needing a register.
// TODO: move tighten to a machine-dependent phase and use v.rematerializeable()?
(And as a consequence, probably remove phiTighten, or at least merge it into tighten.)
If we notice problematic split pairs of instructions, like CMP/SET, we can teach tighten explicitly to leave them alone.
cc @randall77 @cherrymui @dr2chase
The tighten pass is currently scheduled before lower, "to avoid splitting naturally paired instructions such as CMP/SET". Doing tighten later benefits from the removal of values enabled by lowering and lowered CSE. Empirically, moving tighten just before phiTighten generates slightly better code: fewer bytes of instructions on average, and as far I have checked, a pareto improvement on stack use.
Moving tighten after lower will allow us to do this TODO in the code:
(And as a consequence, probably remove phiTighten, or at least merge it into tighten.)
If we notice problematic split pairs of instructions, like CMP/SET, we can teach tighten explicitly to leave them alone.
cc @randall77 @cherrymui @dr2chase