Expand description
Letting a select on a comparison read what the comparison left in the condition state.
Design: spec/10-backend.md section 10.6, and spec/optimizer/37-machine-level-optimization.md
section 37.4.
A rule selects select c, t, f as a test of the byte c and a conditional move on the answer,
because the byte is the only thing a rule can name. When the byte came from a comparison that is
three instructions where the machine wanted one. The comparison sets the condition state, the
byte is written from it, the test of the byte sets the condition state again, and only then
does the move read it:
cmpl %esi, %edi
setg %al cmpl %esi, %edi
testb %al, %al -> cmovgl %edx, %ecx
cmovnel %edx, %ecxThis is the branch crate::layout folds, written as a select, and it is done the same way for
the same reasons. fusable asks before allocation which comparisons have a byte that selects
in the same block are the whole of what reads, because that is a question about a register that
is written once. moves runs after the layout, where nothing is left that could put an
instruction between the comparison and a move reading what it left, and rewrites the comparison
and all of its selects together or none of them.
What it is worth is what phiopt makes. A loop keeping the largest of each of eight slots, which
is if (v > best[k]) best[k] = v and becomes a select once the store is made on both paths,
runs two instructions fewer on every element, and those are two of the four on the path from
the load to the store.
§What stops it
Anything between the comparison and a select that writes the condition state, which the target says of every name it does not know. And anything that writes the register the byte was given, since a select reading that register afterwards is reading something else. Either one ends the walk, and a select the walk did not reach keeps the byte, so the comparison keeps it too and every select behind it stays as it was.
A comparison of floats is not in the table and is left alone. What it leaves in the condition state is two answers, one for whether the operands were ordered at all, and a move can read only one of them.