[llvm-branch-commits] [clang] [CIR] Implement Direct+canFlatten in CallConvLowering (PR #201719)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 12 09:05:27 PDT 2026


================
@@ -792,7 +893,21 @@ LogicalResult CIRABIRewriteContext::rewriteCallSite(
     if (ac.kind == ArgKind::Ignore)
       continue;
     Value arg = argOperands[idx];
-    if (ac.kind == ArgKind::Expand) {
+    if (auto flatTy = getFlattenedCoercedType(ac)) {
+      // Direct + canFlatten: coerce the struct to the ABI-coerced struct type
+      // and then extract each field as a separate call argument.  The coercion
+      // is a memory round-trip when the original and coerced types differ in
+      // layout; when they are the same CIR type the coercion is skipped.
+      Value coerced = arg;
+      if (arg.getType() != flatTy)
+        coerced = emitCoercion(builder, call.getLoc(), flatTy, arg,
+                               enclosingFunc, dl);
+      for (unsigned f = 0; f < flatTy.getNumElements(); ++f) {
+        Value field =
+            cir::ExtractMemberOp::create(builder, call.getLoc(), coerced, f);
----------------
adams381 wrote:

Reworked the call site.  When the operand needs coercion it now goes through a coerce slot and reads each field with `cir.get_member` + `cir.load` from that slot, instead of loading the whole coerced struct and extracting from the value.  The shared memory half is factored into `emitCoercionToMemory`, which returns the destination-typed pointer to the slot.  The no-coercion case (the operand already has the coerced type) keeps `cir.extract_member`, since that value has no backing alloca to take member pointers from.


https://github.com/llvm/llvm-project/pull/201719


More information about the llvm-branch-commits mailing list