[clang] [clang][bytecode] Use `CopyArray` for primitive ArrayInitLoops (PR #191956)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 13 23:50:51 PDT 2026


https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/191956

>From 2f94499f8a4bf40cb45c0098bd048a97cb563a06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 13 Apr 2026 21:38:02 +0200
Subject: [PATCH] copyarray

This reduces the bytecode output for the copy constructor of a struct
such as:

```c++
struct Buffer {
  struct {
    char D[N];
  } V;

  Buffer() = default;
};
```
from
```
Buffer<5>::(unnamed struct)::(unnamed struct at array.cpp:873:3) 0x7d38d2de3f80
frame size: 104
arg size:   96
rvo:        0
this arg:   1
0      GetPtrThisField          16
16     GetParamPtr              0
32     GetPtrFieldPop           16
48     InitScope                0
64     SetLocalPtr              40
80     GetLocalPtr              40
96     ArrayDecay
104    ExpandPtr
112    ConstUint64              0
128    ArrayElemPtrPopUint64
136    LoadPopSint8
144    InitElemSint8            0
160    GetLocalPtr              40
176    ArrayDecay
184    ExpandPtr
192    ConstUint64              1
208    ArrayElemPtrPopUint64
216    LoadPopSint8
224    InitElemSint8            1
240    GetLocalPtr              40
256    ArrayDecay
264    ExpandPtr
272    ConstUint64              2
288    ArrayElemPtrPopUint64
296    LoadPopSint8
304    InitElemSint8            2
320    GetLocalPtr              40
336    ArrayDecay
344    ExpandPtr
352    ConstUint64              3
368    ArrayElemPtrPopUint64
376    LoadPopSint8
384    InitElemSint8            3
400    GetLocalPtr              40
416    ArrayDecay
424    ExpandPtr
432    ConstUint64              4
448    ArrayElemPtrPopUint64
456    LoadPopSint8
464    InitElemSint8            4
480    FinishInitPop
488    Destroy                  0
504    Destroy                  0
520    RetVoid
```
(where `N = 5`).

to:
```
Buffer<5>::(unnamed struct)::(unnamed struct at array.cpp:873:3) 0x7c85b9fe3f80
frame size: 0
arg size:   96
rvo:        0
this arg:   1
0     GetPtrThisField    16
16    GetParamPtr        0
32    GetPtrFieldPop     16
48    CopyArraySint8     0 0 5
80    FinishInitPop
88    RetVoid
```
---
 clang/lib/AST/ByteCode/Compiler.cpp | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 15651b9de9e91..59510612d9617 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2726,16 +2726,27 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
   assert(Initializing);
   assert(!DiscardResult);
 
+  const Expr *Common = E->getCommonExpr();
+  const Expr *SubExpr = E->getSubExpr();
+  OptPrimType SubExprT = classify(SubExpr);
+  size_t Size = E->getArraySize().getZExtValue();
+
+  if (SubExprT) {
+    // Unwrap the OpaqueValueExpr so we don't cache something we won't reuse.
+    Common = cast<OpaqueValueExpr>(Common)->getSourceExpr();
+
+    if (!this->visit(Common))
+      return false;
+    return this->emitCopyArray(*SubExprT, 0, 0, Size, E);
+  }
+
   // We visit the common opaque expression here once so we have its value
   // cached.
-  if (!this->discard(E->getCommonExpr()))
+  if (!this->discard(Common))
     return false;
 
   // TODO: This compiles to quite a lot of bytecode if the array is larger.
   //   Investigate compiling this to a loop.
-  const Expr *SubExpr = E->getSubExpr();
-  size_t Size = E->getArraySize().getZExtValue();
-  OptPrimType SubExprT = classify(SubExpr);
 
   // So, every iteration, we execute an assignment here
   // where the LHS is on the stack (the target array)



More information about the cfe-commits mailing list