[llvm-branch-commits] [clang] [CIR] Implement ArgKind::Expand in CallConvLowering (PR #201718)
Andy Kaylor via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jun 15 09:46:55 PDT 2026
================
@@ -328,19 +353,75 @@ void insertArgCoercion(FunctionOpInterface funcOp,
return;
Block &entry = body.front();
- for (auto [idx, ac] : llvm::enumerate(fc.argInfos)) {
- unsigned blockIdx = idx + sretOffset;
- if (blockIdx >= entry.getNumArguments())
+ // Running block argument index. Each non-Expand classification occupies
+ // one block argument slot; each Expand classification occupies N slots
+ // (one per struct field), so the running index must be incremented by N
+ // rather than 1 after processing an Expand arg.
+ unsigned blockArgIdx = sretOffset;
+
+ for (const ArgClassification &ac : fc.argInfos) {
+ assert(blockArgIdx < entry.getNumArguments() &&
+ "classification count must not exceed entry block arguments");
+
+ if (ac.kind == ArgKind::Expand) {
+ // The block arg at blockArgIdx currently has the original struct type.
+ // Replace it with N scalar args (one per field) and store each field
+ // directly into the parameter's own alloca.
+ BlockArgument origArg = entry.getArgument(blockArgIdx);
+ auto recTy = cast<cir::RecordType>(origArg.getType());
+ assert(recTy.isStruct() &&
+ "Expand classification requires a struct type, not a union");
+ unsigned numFields = recTy.getNumElements();
+ assert(numFields > 0 &&
+ "Expand classification requires at least one struct field");
+ Location loc = funcOp.getLoc();
+
+ // CIRGen spills every by-value struct parameter into its local alloca
+ // with a single store before any other use, so the struct block arg's
+ // only use is that store. Capture it and the destination alloca, then
+ // store the expanded fields straight into that alloca and erase the
+ // original store. This keeps the alloca's variable name and `init`
+ // flag and avoids a reassemble-then-reload roundtrip.
+ assert(origArg.hasOneUse() &&
----------------
andykaylor wrote:
We should probably also allow no uses. It's possible DCE could have been run before this and the store may have been eliminated.
https://github.com/llvm/llvm-project/pull/201718
More information about the llvm-branch-commits
mailing list