-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang][Interp] Emit const references for Float arguments #79753
Conversation
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesThe 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. Full diff: https://github.com/llvm/llvm-project/pull/79753.diff 2 Files Affected:
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 24747b6b98c163..6283e388d7a526 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,7 +44,7 @@ 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 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 02d5f9512d9051..1c41301ab3aeeb 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";
|
For reference, the generated code with this patch looks like this: #if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)
bool emitConstFloat(const Floating &, const SourceInfo &);
#endif
#ifdef GET_LINK_IMPL
bool ByteCodeEmitter::emitConstFloat(const Floating &A0, const SourceInfo &L) {
return emitOp<Floating>(OP_ConstFloat, A0, L);
}
#endif
#ifdef GET_EVAL_IMPL
bool EvalEmitter::emitConstFloat(const Floating &A0, const SourceInfo &L) {
if (!isActive()) return true;
CurrentSource = L;
return Const<PT_Float>(S, OpPC, A0);
}
#endif Where all those #if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)
bool emitConstFloat(Floating, const SourceInfo &);
#endif
#ifdef GET_LINK_IMPL
bool ByteCodeEmitter::emitConstFloat(Floating A0, const SourceInfo &L) {
return emitOp<Floating>(OP_ConstFloat, A0, L);
}
#endif
#ifdef GET_EVAL_IMPL
bool EvalEmitter::emitConstFloat(Floating A0, const SourceInfo &L) {
if (!isActive()) return true;
CurrentSource = L;
return Const<PT_Float>(S, OpPC, A0);
}
#endif |
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.
Ping |
1 similar comment
Ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
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.