Description
In #3233 we discussed various simplifications we could perform to reduce the number of CLIF opcodes that exist. In general, we should strive for simplicity -- fewer opcodes mean less cost for every consumer of the IR -- as long as simplifications don't impose other overheads, such as unnecessary expansion and pattern-matching.
The "flags"-related opcodes, such as ifcmp
/ ffcmp
, brif
/ brff
, trapif
/ trapff
, and those that communicate carry/borrow flags via the full flags value, seem to be good candidates for removal. This is for at least a few reasons:
- A flag value behaves differently than most others in the IR, and as such, imposes complexity cost. For example, only one flag value may be live at a time. This constraint, enforced by the validator, is meant to allow the flags value to be directly lowered onto a machine's CPU flags register, but our backends no longer work this way. For another example, a flag value cannot be stored/loaded to/from memory.
- The flags do not have a well-defined value but rather serve as a sort of opaque connection between producer (e.g., a compare) and consumer (e.g., a branch). For example, a bitcast/raw-bitcast from a flag value to an integer is undefined (and disallowed by the validator).
- There is redundancy in the instruction set, as some conditions can also be materialized as bools. For example, we have both
iadd_carry
, which produces the carry flag as a bool, andiadd_ifcout
, which produces a flags value with the carry embedded in it.
With better pattern-matching in the backends (both as they stand today and potentially with a DSL to help as proposed in bytecodealliance/rfcs#15), it is less important for the CLIF to directly correspond to machine code; we can pattern-match a producer and consumer (e.g. a compare and a branch) that communicate via a b1
(bool) just as well as we can those that communicate via opaque flags values.
Thus, we should look into removing all uses of "flags" values, instead consuming the flags where they are produced to generate a bool condition as appropriate.
One downside of this approach is that we cannot directly express reuse of flags for more than one condition (e.g. ifcmp
then multiple trueif
s with multiple flag conditions). Potentially we could instead pattern-match on multiple compare instructions with the same arguments and merge them instead, so e.g. icmp ge v0, v1
and icmp eq v0, v1
become a comopare-setcc-setcc three-instruction sequence.
cc @abrown @afonso360 @bjorn3 from earlier discussion
Metadata
Metadata
Assignees
Type
Projects
Status
No status