[clang] [clang][Interp] Emit const references for Float arguments (PR #79753)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 5 07:16:42 PST 2024
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/79753
>From 0e108e92b3165f95a934895e14f6c330f6c5e3fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 28 Jan 2024 16:13:08 +0100
Subject: [PATCH] [clang][Interp] Emit const references for Float arguments
The Float print type is backed by the Floating class, which
in turn uses APFloat, which might heap-allocate memory, so might be
expensive to copy.
Add an 'AsRef' bit to the ArgType tablegen class, which defines whether
we pass the argument around by copy or by reference.
---
clang/lib/AST/Interp/Opcodes.td | 8 ++--
clang/utils/TableGen/ClangOpcodesEmitter.cpp | 50 ++++++++++++++++----
2 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index e720b95498f17..b33741c0e5a68 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -35,7 +35,7 @@ def FnPtr : Type;
// Types transferred to the interpreter.
//===----------------------------------------------------------------------===//
-class ArgType { string Name = ?; }
+class ArgType { string Name = ?; bit AsRef = false; }
def ArgSint8 : ArgType { let Name = "int8_t"; }
def ArgUint8 : ArgType { let Name = "uint8_t"; }
def ArgSint16 : ArgType { let Name = "int16_t"; }
@@ -44,9 +44,9 @@ def ArgSint32 : ArgType { let Name = "int32_t"; }
def ArgUint32 : ArgType { let Name = "uint32_t"; }
def ArgSint64 : ArgType { let Name = "int64_t"; }
def ArgUint64 : ArgType { let Name = "uint64_t"; }
-def ArgFloat : ArgType { let Name = "Floating"; }
-def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; }
-def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; }
+def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; let AsRef = true; }
+def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; let AsRef = true; }
+def ArgFloat : ArgType { let Name = "Floating"; let AsRef = true; }
def ArgBool : ArgType { let Name = "bool"; }
def ArgFunction : ArgType { let Name = "const Function *"; }
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 02d5f9512d905..1c41301ab3aee 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -126,9 +126,15 @@ void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N,
// Emit calls to read arguments.
for (size_t I = 0, N = Args.size(); I < N; ++I) {
- OS << " auto V" << I;
+ const auto *Arg = Args[I];
+ bool AsRef = Arg->getValueAsBit("AsRef");
+
+ if (AsRef)
+ OS << " const auto &V" << I;
+ else
+ OS << " const auto V" << I;
OS << " = ";
- OS << "ReadArg<" << Args[I]->getValueAsString("Name")
+ OS << "ReadArg<" << Arg->getValueAsString("Name")
<< ">(S, PC);\n";
}
@@ -192,8 +198,14 @@ void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N,
// Emit the list of arguments.
OS << "bool ByteCodeEmitter::emit" << ID << "(";
- for (size_t I = 0, N = Args.size(); I < N; ++I)
- OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
+ for (size_t I = 0, N = Args.size(); I < N; ++I) {
+ const auto *Arg = Args[I];
+ bool AsRef = Arg->getValueAsBit("AsRef");
+ auto Name = Arg->getValueAsString("Name");
+
+ OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") << "A"
+ << I << ", ";
+ }
OS << "const SourceInfo &L) {\n";
// Emit a call to write the opcodes.
@@ -218,8 +230,14 @@ void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N,
auto Args = R->getValueAsListOfDefs("Args");
Enumerate(R, N, [&OS, &Args](ArrayRef<const Record *> TS, const Twine &ID) {
OS << "bool emit" << ID << "(";
- for (auto *Arg : Args)
- OS << Arg->getValueAsString("Name") << ", ";
+ for (size_t I = 0, N = Args.size(); I < N; ++I) {
+ const auto *Arg = Args[I];
+ bool AsRef = Arg->getValueAsBit("AsRef");
+ auto Name = Arg->getValueAsString("Name");
+
+ OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "")
+ << ", ";
+ }
OS << "const SourceInfo &);\n";
});
@@ -275,8 +293,14 @@ void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N,
OS << "::" << EmitFuncName << "(";
for (size_t I = 0, N = Types->size(); I < N; ++I)
OS << "PrimType T" << I << ", ";
- for (size_t I = 0, N = Args.size(); I < N; ++I)
- OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
+ for (size_t I = 0, N = Args.size(); I < N; ++I) {
+ const auto *Arg = Args[I];
+ bool AsRef = Arg->getValueAsBit("AsRef");
+ auto Name = Arg->getValueAsString("Name");
+
+ OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") << "A"
+ << I << ", ";
+ }
OS << "const SourceInfo &I) {\n";
std::function<void(size_t, const Twine &)> Rec;
@@ -343,8 +367,14 @@ void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N,
auto Args = R->getValueAsListOfDefs("Args");
OS << "bool EvalEmitter::emit" << ID << "(";
- for (size_t I = 0, N = Args.size(); I < N; ++I)
- OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
+ for (size_t I = 0, N = Args.size(); I < N; ++I) {
+ const auto *Arg = Args[I];
+ bool AsRef = Arg->getValueAsBit("AsRef");
+ auto Name = Arg->getValueAsString("Name");
+
+ OS << (AsRef ? "const " : " ") << Name << " "
+ << (AsRef ? "&" : "") << "A" << I << ", ";
+ }
OS << "const SourceInfo &L) {\n";
OS << " if (!isActive()) return true;\n";
OS << " CurrentSource = L;\n";
More information about the cfe-commits
mailing list