Hi Michiel,
> Hi Jeff, Jin,
>
> > I have not found an ideal way to balance accurate modeling with generic
> > reuse. Could you suggest what abstraction GCC would prefer in this
> > case, or whether there is a better way to represent these constraint
> > differences between microarchitectures?
>
> We have encountered the same issue.
> Many of the pre-existing fusion matchers almost fit our needs but
> can't be reused because of differing constraints.
>
> Currently we are trying to reuse as much as possible by
> A) outlining parts of the matcher that are the same;
> e.g. reuse the RTL maching but separate destination register checking
> B) splitting up matchers; e.g; split up BFEXT into one for srli and srai
>
> However, splitting up some fusion matchers to ensure maximum reusability
> can make things needlessly complicated and we just accept the overlap.
>
> I propose to focus for now on providing generic building blocks (util
> functions)
> for building matchers and not focus too much on making the RISCV_FUSE_* enum
> itself reusable.
>
Thanks for sharing this. It seems that our thinking is largely aligned:
we should prioritize reusable generic building blocks while allowing
matchers for different microarchitectural constraints to retain
necessary overlap in the RTL they accept, rather than requiring the
RISCV_FUSE_* enum itself to be fully reusable. Cheers to that!
This is also the motivation for my current refactoring of some functions
and comments:
1) Extract helpers that handle only common RTL parsing and matching,
while leaving each fusion pair's specific constraints in its
corresponding checker.
2) Keep the implementation as simple as possible. The RTL accepted by
different checkers may overlap, but each fusion bit controls
exactly one checker, with a clear one-to-one relationship among
enablement, the checker, and the dump name. This avoids mixing
multiple fusion capabilities in a single checker.
3) Rework the comments so that they describe each matcher's
distinctive details as precisely as possible in terms of actual RTL
forms and constraints, rather than using broad prose descriptions.
> Somewhat related: I'm planning on making RA aware of these register
> constraints
> and then these would need to be separated out anyway. Haven't checked yet
> whether that's actually worth the effort though.
>
I am working in the same area of making RA aware of these register
constraints. More specifically, I am implementing for RISC-V the GCC IRA
hooks that model the trade-off between callee-saved registers and
spilling. These hooks were introduced by the following commit:
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b191e8bdecf881d11c1544c441e38f4c18392a15
The work covers RISCV_FUSE_LDST_PAIR_INC, RISCV_FUSE_LDST_PAIR_DEC,
RISCV_FUSE_FLDFST_PAIR_INC, RISCV_FUSE_FLDFST_PAIR_DEC,
RISCV_FUSE_PREINDEX_ST, and RISCV_FUSE_POSTINDEX_LD. These fusion cases
are intended to optimize spill code and the register save/restore
sequences in function prologues and epilogues. The RISC-V implementation
of these hooks is based mainly on the AArch64 approach. In fact, I
already have a local patch ready and plan to submit it after the
current fusion patch is accepted. Local testing is complete and has
shown the expected code-generation improvements. However, I am not
yet sure whether this approach is the right one, and I would appreciate
any suggestions for improving it. Does this direction resonate with
what you have in mind for making RA aware of these register constraints?
If you have a better idea, or would like someone to help move it
forward, I would be happy to participate.
If useful, I can also append the IRA patch to the current fusion series
for review and discussion.
As an aside, the following patch fixes a prerequisite issue for
implementing these hooks. It is still under review, and comments on it
would be very welcome:
https://patchwork.sourceware.org/project/gcc/patch/[email protected]/
> Thanks,
> Michiel
Thanks,
Jin