Inverse the logic of ProcessAllBindings function.
Instead of creating lots of structs that represent bindings data and
then calling ProcessBindings once we are now calling callback on them
in sequence.
This brings many benefits:
• No risc of hittin fold expression limit: https://reviews.llvm.org/D86936
• Makes it possible pass additiona info into callback
• Simplifies the generation logic a tiny bit
• Makes it simpler for the compiler to optimize code
• Make it possible to remove GenerateAsmCallBase class in the future.
Bug: 278812060
Test: m berberis_all
Change-Id: Id8c870476d910a51ac2bf87917ea9863579afa0d
diff --git a/intrinsics/common_to_x86/make_intrinsics.cc b/intrinsics/common_to_x86/make_intrinsics.cc
index d904766..c49e62e 100644
--- a/intrinsics/common_to_x86/make_intrinsics.cc
+++ b/intrinsics/common_to_x86/make_intrinsics.cc
@@ -795,17 +795,20 @@
EmitFunctionType emit_;
};
-template <typename... AsmCallGenerator>
-void ProcessBindings(FILE* out, AsmCallGenerator... asm_call_generator) {
+#define INTRINSIC_FUNCTION_NAME(func_name) #func_name
+#include "make_intrinsics-inl.h"
+#undef INTRINSIC_FUNCTION_NAME
+
+void GenerateAsmCalls(FILE* out) {
GenerateAsmCallBase::SSERestrictionEnum cpuid_restriction = GenerateAsmCallBase::kNoCPUIDRestriction;
bool if_opened = false;
std::string running_name;
- (
+ ProcessBindings<MacroAssembler<berberis::TextAssembler>, x86::OperandClass>(
[&running_name, &if_opened, &cpuid_restriction, out](auto&& asm_call_generator) {
std::string full_name =
- asm_call_generator->name.substr(0, asm_call_generator->name.length() - 1) +
+ asm_call_generator.name.substr(0, asm_call_generator.name.length() - 1) +
", kUseCppImplementation>";
- if (size_t arguments_count = asm_call_generator->GetArgumentsCount()) {
+ if (size_t arguments_count = asm_call_generator.GetArgumentsCount()) {
full_name += "(in0";
for (size_t i = 1; i < arguments_count; ++i) {
full_name += ", in" + std::to_string(i);
@@ -825,11 +828,11 @@
}
// Final line of function.
fprintf(out, "};\n\n");
- asm_call_generator->GenerateFunctionHeader(out, 0);
+ asm_call_generator.GenerateFunctionHeader(out, 0);
running_name = full_name;
}
- if (asm_call_generator->cpuid_restriction != cpuid_restriction) {
- if (asm_call_generator->cpuid_restriction == GenerateAsmCallBase::kNoCPUIDRestriction) {
+ if (asm_call_generator.cpuid_restriction != cpuid_restriction) {
+ if (asm_call_generator.cpuid_restriction == GenerateAsmCallBase::kNoCPUIDRestriction) {
fprintf(out, " } else {\n");
} else {
if (if_opened) {
@@ -838,7 +841,7 @@
fprintf(out, " if (");
if_opened = true;
}
- switch (asm_call_generator->cpuid_restriction) {
+ switch (asm_call_generator.cpuid_restriction) {
case GenerateAsmCallBase::kIsAuthenticAMD:
fprintf(out, "host_platform::kIsAuthenticAMD");
break;
@@ -870,11 +873,10 @@
}
fprintf(out, ") {\n");
}
- cpuid_restriction = asm_call_generator->cpuid_restriction;
+ cpuid_restriction = asm_call_generator.cpuid_restriction;
}
- asm_call_generator->GenerateFunctionBody(out, 2 + 2 * if_opened);
- }(asm_call_generator),
- ...);
+ asm_call_generator.GenerateFunctionBody(out, 2 + 2 * if_opened);
+ });
if (if_opened) {
fprintf(out, " }\n");
}
@@ -882,10 +884,6 @@
fprintf(out, "};\n\n");
}
-#define INTRINSIC_FUNCTION_NAME(func_name) #func_name
-#include "make_intrinsics-inl.h"
-#undef INTRINSIC_FUNCTION_NAME
-
} // namespace berberis
int main(int argc, char* argv[]) {
@@ -936,8 +934,7 @@
? "using berberis::constants_pool::kBerberisMacroAssemblerConstants;"
: "");
- berberis::ProcessAllBindings<berberis::MacroAssembler<berberis::TextAssembler>,
- berberis::x86::OperandClass>(out);
+ berberis::GenerateAsmCalls(out);
berberis::MakeExtraGuestFunctions(out);
fprintf(out,
diff --git a/intrinsics/gen_intrinsics.py b/intrinsics/gen_intrinsics.py
index d4b41a7..9e15fec 100755
--- a/intrinsics/gen_intrinsics.py
+++ b/intrinsics/gen_intrinsics.py
@@ -720,18 +720,12 @@
print("""%s
template <typename MacroAssembler,
typename OperandClass,
+ typename Callback,
typename... Args>
-void ProcessAllBindings(Args&&... args) {
- ProcessBindings(
- std::forward<Args>(args)...""" % AUTOGEN, end="", file=f)
+void ProcessBindings(Callback callback, Args&&... args) {""" % AUTOGEN, file=f)
for line in _gen_c_intrinsics_generator(intrs):
- if line.startswith(','):
- print(',\n'+line[1:], end='', file=f)
- else:
- print('\n'+line, end='', file=f)
- print("""
- );
-}""", file=f)
+ print(line, file=f)
+ print("}", file=f)
def _gen_c_intrinsics_generator(intrs):
@@ -815,21 +809,21 @@
restriction = [cpuid_restriction, nan_restriction]
- yield ', std::unique_ptr<GenerateAsmCallBase>('
+ yield ' callback('
def get_c_type_tuple(arguments):
return 'std::tuple<%s>' % ', '.join(
_get_c_type(argument) for argument in arguments).replace(
'Float', 'intrinsics::Float')
- yield ' new GenerateAsmCall<%s>(' % (
- ',\n '.join(
+ yield ' GenerateAsmCall<%s>(' % (
+ ',\n '.join(
['true' if _intr_has_side_effects(intr) else 'false'] +
[get_c_type_tuple(intr['in'])] + [get_c_type_tuple(intr['out'])] +
[_get_reg_operand_info(arg, 'typename OperandClass')
for arg in asm['args']]))
- one_line = ' &MacroAssembler::%s%s, %s))' % (
+ one_line = ' &MacroAssembler::%s%s, %s),' % (
'template ' if '<' in asm['asm'] else '',
asm['asm'],
', '.join(['INTRINSIC_FUNCTION_NAME((%s))' % name] + restriction))
@@ -843,9 +837,10 @@
values = ['INTRINSIC_FUNCTION_NAME((%s))' % name] + restriction
for index, value in enumerate(values):
if index + 1 == len(values):
- yield ' %s))' % value
+ yield ' %s),' % value
else:
yield ' %s,' % value
+ yield ' std::forward<Args>(args)...);'
def _load_intrs_def_files(intrs_def_files):