Quoting Richard Sandiford <rdsandif...@googlemail.com>:
> But I think extending the FSM from just being an on-the-fly
transformatino during final (as for ARM) to something that happens
earlier is a pretty major step in terms of the interface between the
backend and the rest of GCC. There are then undocumented restrictions
on what hooks can be called when,
Indeed. I found I have to call extract_constrain_insn_cached to restore
recog_data (the struct, even though gdb will never believe this and insist
on that being a type) if I have recognized other insns (by evaluating
an attribute) from a splitter predicate.
which if broken could lead to the FSM
producing different results during final than it did earlier.
Well, actually, I did find that this happens, and added code to either
compensate for changes or inhibit them. For the most part, these changes
are wanted, we just need to manage them to avoid out-of-range branches
or ADDR_DIFF_VECs.
You could think of this as simulated annealing for ice: some provisions need
to be made to avoid rupturing the vessel, either by anticipating size
increases, containing pressure to limit size increase, or a combination
of both.
E.g., personally, I don't think it's acceptable for ADJUST_INSN_LENGTH
to hard-code an assumption that all instructions are processed in
assembly order, which the ARC one seems to (irrespective of this patch).
It doesn't, at least not for correctness; you might argue that it depends
on this for compilation time performance. It does a scan in
round-robin fashion from the last insn it processed till it reaches
the one that is
to be processed.
But I did develop this stuff when passes were much more rigid than they
are today; I'll look into the feasibility of running the ccfsm in a
machine-specific pass to finalize in rtl whatever COND_EXEC opportunities
are visible at this stage, and calling it after preliminary compare-and-branch
determination, and after delay branch scheduling. Maybe at some other places
too.
One complication is that sometimes a compare-and-branch decision has to be
reversed, so the exact ccfsm description before instruction output is that
it is unlikely to clobber the flags. Thus, a conditionalizing that depends
on the flags surviving through a compare-and-branch cannot be finalized till
the branch is safe. Still, the conditionalizing is likely and we should
take length changes into account, provided that the compare-and-branch stays
in range.
I suppose I could add a note
REG_DEP_TRUE (unspec [<list of brcc insn for required to be short for
conditionalizing>] UNSPEC_CCFSM)
for any instructions subject to such uncertain conditionalizations.
Or probably rather three UNSPEC kinds: one to indicate ccfsm-predicated
deletion (for a branch), one for general conditionalizing
(for arithmetic, branches and calls), and one for equality conditionalizing
(for branches, wider offset ranges are available for short variants,
and for register zeroing, which has a not-equal conditionalized short form).