New custom DAG nodes were added to represent operations on CSR. These
nodes are lowered to corresponding pseudo instruction. Using the pseudo
instructions allows to specify different scheduling information for
operations on different system registers. It also make possible to
specify dependencies of instructions on specific system registers.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
CSR addresses are uimm12s not simm12s
llvm/lib/Target/RISCV/RISCVISelLowering.h | ||
---|---|---|
236 | Hm, modify isn't a great name when WRITE_CSR exists |
Updated patch
- used uimm12 to represent system register number,
- renamed 'modify' component of new names to 'swap',
- removed prefix 'Pseudo' in new instructions.
So to provide alternate scheduling information, we need scheduler predicates to inspect the operands to find the system register?
And what pass would be responsible for adding implicit def/use of the rounding mode register?
Updated patch
- Removed asm operands from Read_CSR and friends,
- Added classes for defining operations on specific system registers.
Pseudos that operate on specific registers should get separate definitions, like:
def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; def SwapFRM : SwapSysReg<SysRegFRM, [FRM]>;
And what pass would be responsible for adding implicit def/use of the rounding mode register?
I think the implicit use/def should be a property of FP instructions, but this is a topic for discussion (https://lists.llvm.org/pipermail/llvm-dev/2021-March/149177.html).
Are there ever any cases where you _wouldn't_ want a CSR-specific pseudo in order to have control over the scheduling of it specifically? This feels a bit like a middle-ground that's the worst of both worlds to me.
Updated patch
- uimm12 is now only PatLeaf, not Operand.
- set hasSideEffects for Read_CSR.
There may be cases when using registers to express dependencies is not practical. For hypothetical example, if write to some system register results in cache invalidation or in memory translation change, it is easier to model such dependency as a side effect.
llvm/lib/Target/RISCV/RISCVInstrInfo.td | ||
---|---|---|
155 | Right now it may be ImmLeaf only. Changed the implementation properly. | |
1178 | Indeed. Set hasSideEffects to true. |
Hi @jrtc27 - could you please elaborate a little on the concern that the approach in this path might be the worst of both worlds? I'm not sure I fully follow. Thanks.
If you want to have different scheduling for different CSRs, do you not need per-CSR pseudos in order to express that? This diff is ostensibly to allow for that in future, but is at a much coarser read/write/swap granularity, so doesn't really get you much over and above just scheduling CSRRW itself as a whole, just adds more complexity for little gain. IMO any CSRs we need scheduling info for should just get their own dedicated read/write/swap pseudos as and when they're needed.
The patch D99083 demonstrates the solution for FP state/control resisters. Every register and every access get separate pseudos, each of which can have their own scheduling properties.
That looks like the kind of thing I'm imagining. So can we remove the Read/Write/Swap_CSR defs from this diff and just keep the Read/Write/SwapSysReg classes for use with such pseudos?
No problem. I just thought that putting Read/Write/Swap_CSR defs (which are general purpose definitions) into a patch specific for FP support is not quite logical. But if this is OK, I'll move them.
I meant not having those defs at all, I don't see what they're useful for and are the pseudos I was taking issue with in my earlier comments.
llvm/lib/Target/RISCV/RISCVInstrInfo.td | ||
---|---|---|
1182 | You are right. It is fairly possible and the previous version of this patch contained support for such general case (Read_CSR in https://reviews.llvm.org/D98936?vs=on&id=332569#toc). This pseudo is proposed for a particular case, which can be represented as a reading register. The concrete example is reading floating point control and state registers. | |
1190 | Again, it is true in general case (see the removed pseudo Write_CSR in the previous version). This pseudo is for the special case, when write to system register has no effects other than changing content of the corresponding register. Floating point environment register behave exactly in this way. | |
1198 | This is true for the removed Swap_CSR from the previous version. Maybe we need to put them back. |
Hm, modify isn't a great name when WRITE_CSR exists