[llvm] [GlobalISel][RISCV] SelectionDAG like indirect parameter passing (PR #216724)
Gábor Spaits via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 03:19:37 PDT 2026
================
@@ -859,25 +846,44 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
// Now split the registers into the assigned types.
Args[i].OrigRegs.assign(Args[i].Regs.begin(), Args[i].Regs.end());
+ int IndirectFrameIdx = 0;
+ Register IndirectPointerToStackReg{};
+ TypeSize CurrentIndirectChunkSize = TypeSize::getZero();
+ for (unsigned Part = 0; Part < NumParts; Part++) {
+ if (ArgLocs[j + Part].getLocInfo() == CCValAssign::Indirect)
+ CurrentIndirectChunkSize += ArgLocs[j + Part].getValVT().getStoreSize();
+ else if (CurrentIndirectChunkSize != 0)
+ llvm_unreachable("Indirect parameter passing where the middle part of "
+ "a parameter is indirect isn't yet supported!");
+ }
+
if (NumParts != 1 || NewLLT != OrigTy) {
- // If we can't directly assign the register, we need one or more
- // intermediate values.
- Args[i].Regs.resize(NumParts);
-
- // When we have indirect parameter passing we are receiving a pointer,
- // that points to the actual value, so we need one "temporary" pointer.
- if (VA.getLocInfo() == CCValAssign::Indirect) {
- if (Handler.isIncomingArgumentHandler())
- Args[i].Regs[0] = MRI.createGenericVirtualRegister(PointerTy);
- } else {
- // For each split register, create and assign a vreg that will store
- // the incoming component of the larger value. These will later be
- // merged to form the final vreg.
- for (unsigned Part = 0; Part < NumParts; ++Part)
- Args[i].Regs[Part] = MRI.createGenericVirtualRegister(NewLLT);
+ Args[i].Regs.clear();
----------------
spaits wrote:
Clearing the `Regs` vector instead of pre-allocating and later pushing back to it is all the legacy from a previous version of this PR.
Currently, we create a pointer register for each indirect part. We only use one of these registers.
There was a previous version of this PR (I have already throw away that version by squashing long befor ipening this PR) that has avoded this,
and recognized, that for one indirect chunk, we only need one register.
In that case, we only needed one register, even if we had 4 parts. (Then the 4 parts would be loaded individually with the right offsets).
When loading those 4 parts separately, we will need 4 those values in `Regs`, so later they can be merged into one value with `buildCopyFromRegs`.
So the first elemnt of `Regs`, which was a pointer, will be replaced by the value loaded from that pointer.
For the other values, we didn't have an existing place so we have to push them back.
I have abandoned that version, because it has caused some issues with fixed length vector indirect passing and I rewrote things to use this more simple and virtual register inefficient version. The one u can see now. And the current version seems to be working.
Also I wrote this PR in 30-45 min sessions in the past 2-3 months, doing smaller parts each time so that may causes it to be inconsisten.
I could do this because this PR basically consits of three separate parts:
1. Determining how what/many virt regs to use and counting stack space.
2. Handling incoming indirect values.
3. Handling Outgoing indirect values.
I wrote a part, kept it and only changed it if another part wasn't working because of it.
So the end result is a bit inconsistant. I am sorry for that. I haven't yet used AI for this PR, but considering how good AI tools got recently, maybe I should give them a try to help me make the three main parts more consistent with each other. In the next few days hopefully I will have some time for that.
https://github.com/llvm/llvm-project/pull/216724
More information about the llvm-commits
mailing list