[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