Skip to content

Commit b5437c8

Browse files
authored
[clang][Interp] Emit const references for Float arguments (#79753)
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.
1 parent dd3e0a4 commit b5437c8

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

clang/lib/AST/Interp/Opcodes.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def FnPtr : Type;
3535
// Types transferred to the interpreter.
3636
//===----------------------------------------------------------------------===//
3737

38-
class ArgType { string Name = ?; }
38+
class ArgType { string Name = ?; bit AsRef = false; }
3939
def ArgSint8 : ArgType { let Name = "int8_t"; }
4040
def ArgUint8 : ArgType { let Name = "uint8_t"; }
4141
def ArgSint16 : ArgType { let Name = "int16_t"; }
@@ -44,9 +44,9 @@ def ArgSint32 : ArgType { let Name = "int32_t"; }
4444
def ArgUint32 : ArgType { let Name = "uint32_t"; }
4545
def ArgSint64 : ArgType { let Name = "int64_t"; }
4646
def ArgUint64 : ArgType { let Name = "uint64_t"; }
47-
def ArgFloat : ArgType { let Name = "Floating"; }
48-
def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; }
49-
def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; }
47+
def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; let AsRef = true; }
48+
def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; let AsRef = true; }
49+
def ArgFloat : ArgType { let Name = "Floating"; let AsRef = true; }
5050
def ArgBool : ArgType { let Name = "bool"; }
5151

5252
def ArgFunction : ArgType { let Name = "const Function *"; }

clang/utils/TableGen/ClangOpcodesEmitter.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,15 @@ void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N,
126126

127127
// Emit calls to read arguments.
128128
for (size_t I = 0, N = Args.size(); I < N; ++I) {
129-
OS << " auto V" << I;
129+
const auto *Arg = Args[I];
130+
bool AsRef = Arg->getValueAsBit("AsRef");
131+
132+
if (AsRef)
133+
OS << " const auto &V" << I;
134+
else
135+
OS << " const auto V" << I;
130136
OS << " = ";
131-
OS << "ReadArg<" << Args[I]->getValueAsString("Name")
137+
OS << "ReadArg<" << Arg->getValueAsString("Name")
132138
<< ">(S, PC);\n";
133139
}
134140

@@ -192,8 +198,14 @@ void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N,
192198

193199
// Emit the list of arguments.
194200
OS << "bool ByteCodeEmitter::emit" << ID << "(";
195-
for (size_t I = 0, N = Args.size(); I < N; ++I)
196-
OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
201+
for (size_t I = 0, N = Args.size(); I < N; ++I) {
202+
const auto *Arg = Args[I];
203+
bool AsRef = Arg->getValueAsBit("AsRef");
204+
auto Name = Arg->getValueAsString("Name");
205+
206+
OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") << "A"
207+
<< I << ", ";
208+
}
197209
OS << "const SourceInfo &L) {\n";
198210

199211
// Emit a call to write the opcodes.
@@ -218,8 +230,14 @@ void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N,
218230
auto Args = R->getValueAsListOfDefs("Args");
219231
Enumerate(R, N, [&OS, &Args](ArrayRef<const Record *> TS, const Twine &ID) {
220232
OS << "bool emit" << ID << "(";
221-
for (auto *Arg : Args)
222-
OS << Arg->getValueAsString("Name") << ", ";
233+
for (size_t I = 0, N = Args.size(); I < N; ++I) {
234+
const auto *Arg = Args[I];
235+
bool AsRef = Arg->getValueAsBit("AsRef");
236+
auto Name = Arg->getValueAsString("Name");
237+
238+
OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "")
239+
<< ", ";
240+
}
223241
OS << "const SourceInfo &);\n";
224242
});
225243

@@ -275,8 +293,14 @@ void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N,
275293
OS << "::" << EmitFuncName << "(";
276294
for (size_t I = 0, N = Types->size(); I < N; ++I)
277295
OS << "PrimType T" << I << ", ";
278-
for (size_t I = 0, N = Args.size(); I < N; ++I)
279-
OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
296+
for (size_t I = 0, N = Args.size(); I < N; ++I) {
297+
const auto *Arg = Args[I];
298+
bool AsRef = Arg->getValueAsBit("AsRef");
299+
auto Name = Arg->getValueAsString("Name");
300+
301+
OS << (AsRef ? "const " : " ") << Name << " " << (AsRef ? "&" : "") << "A"
302+
<< I << ", ";
303+
}
280304
OS << "const SourceInfo &I) {\n";
281305

282306
std::function<void(size_t, const Twine &)> Rec;
@@ -343,8 +367,14 @@ void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N,
343367
auto Args = R->getValueAsListOfDefs("Args");
344368

345369
OS << "bool EvalEmitter::emit" << ID << "(";
346-
for (size_t I = 0, N = Args.size(); I < N; ++I)
347-
OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
370+
for (size_t I = 0, N = Args.size(); I < N; ++I) {
371+
const auto *Arg = Args[I];
372+
bool AsRef = Arg->getValueAsBit("AsRef");
373+
auto Name = Arg->getValueAsString("Name");
374+
375+
OS << (AsRef ? "const " : " ") << Name << " "
376+
<< (AsRef ? "&" : "") << "A" << I << ", ";
377+
}
348378
OS << "const SourceInfo &L) {\n";
349379
OS << " if (!isActive()) return true;\n";
350380
OS << " CurrentSource = L;\n";

0 commit comments

Comments
 (0)