9ab5245b89
- Fix incorrectly named ALL_INTRINSICS_LIST to ASM_INTRINSICS_LIST and restore setting intrinsic bit for graph intrinsics. - Remove more dead code. TEST=ci Bug: https://github.com/dart-lang/sdk/issues/56007 Change-Id: Iebceaab86509e34f47e3d6918706b0e69ed7dfc5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/374842 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
143 lines
5.1 KiB
C++
143 lines
5.1 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
// Class for intrinsifying functions.
|
|
|
|
#include "vm/compiler/intrinsifier.h"
|
|
|
|
#include "vm/compiler/assembler/assembler.h"
|
|
#include "vm/compiler/backend/flow_graph.h"
|
|
#include "vm/compiler/backend/flow_graph_compiler.h"
|
|
#include "vm/compiler/backend/il_printer.h"
|
|
#include "vm/compiler/backend/linearscan.h"
|
|
#include "vm/compiler/frontend/flow_graph_builder.h"
|
|
#include "vm/compiler/jit/compiler.h"
|
|
#include "vm/cpu.h"
|
|
#include "vm/flags.h"
|
|
#include "vm/object.h"
|
|
#include "vm/parser.h"
|
|
#include "vm/symbols.h"
|
|
|
|
namespace dart {
|
|
|
|
DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
|
|
DEFINE_FLAG(bool, trace_intrinsifier, false, "Trace intrinsifier");
|
|
|
|
namespace compiler {
|
|
|
|
bool Intrinsifier::CanIntrinsify(const ParsedFunction& parsed_function) {
|
|
const Function& function = parsed_function.function();
|
|
|
|
if (FLAG_trace_intrinsifier) {
|
|
THR_Print("CanIntrinsify %s ->", function.ToQualifiedCString());
|
|
}
|
|
if (!FLAG_intrinsify) return false;
|
|
// TODO(regis): We do not need to explicitly filter generic functions here,
|
|
// unless there are errors we don't detect at link time. Revisit if necessary.
|
|
if (function.IsClosureFunction()) {
|
|
if (FLAG_trace_intrinsifier) {
|
|
THR_Print("No, closure function.\n");
|
|
}
|
|
return false;
|
|
}
|
|
// Can occur because of compile-all flag.
|
|
if (function.is_external()) {
|
|
if (FLAG_trace_intrinsifier) {
|
|
THR_Print("No, external function.\n");
|
|
}
|
|
return false;
|
|
}
|
|
if (!function.is_intrinsic()) {
|
|
if (FLAG_trace_intrinsifier) {
|
|
THR_Print("No, not intrinsic function.\n");
|
|
}
|
|
return false;
|
|
}
|
|
switch (function.recognized_kind()) {
|
|
case MethodRecognizer::kInt64ArrayGetIndexed:
|
|
case MethodRecognizer::kInt64ArraySetIndexed:
|
|
case MethodRecognizer::kUint64ArrayGetIndexed:
|
|
case MethodRecognizer::kUint64ArraySetIndexed:
|
|
// TODO(ajcbik): consider 32-bit as well.
|
|
if (target::kBitsPerWord == 64) {
|
|
break;
|
|
}
|
|
if (FLAG_trace_intrinsifier) {
|
|
THR_Print("No, 64-bit int intrinsic on 32-bit platform.\n");
|
|
}
|
|
return false;
|
|
default:
|
|
break;
|
|
}
|
|
if (FLAG_trace_intrinsifier) {
|
|
THR_Print("Yes.\n");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Returns true if fall-through code can be omitted.
|
|
bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
|
|
FlowGraphCompiler* compiler) {
|
|
if (!CanIntrinsify(parsed_function)) {
|
|
return false;
|
|
}
|
|
|
|
if (GraphIntrinsifier::GraphIntrinsify(parsed_function, compiler)) {
|
|
return compiler->intrinsic_slow_path_label()->IsUnused();
|
|
}
|
|
|
|
const Function& function = parsed_function.function();
|
|
#if !defined(HASH_IN_OBJECT_HEADER)
|
|
// These two are more complicated on 32 bit platforms, where the
|
|
// identity hash is not stored in the header of the object. We
|
|
// therefore don't intrinsify them, falling back on the native C++
|
|
// implementations.
|
|
if (function.recognized_kind() == MethodRecognizer::kObject_getHash) {
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(PRODUCT)
|
|
#define EMIT_BREAKPOINT() compiler->assembler()->Breakpoint()
|
|
#else
|
|
#define EMIT_BREAKPOINT()
|
|
#endif
|
|
|
|
#define EMIT_CASE(library, class_name, function_name, enum_name, fp) \
|
|
case MethodRecognizer::k##enum_name: { \
|
|
compiler->assembler()->Comment("Intrinsic"); \
|
|
Label normal_ir_body; \
|
|
const auto size_before = compiler->assembler()->CodeSize(); \
|
|
AsmIntrinsifier::enum_name(compiler->assembler(), &normal_ir_body); \
|
|
const auto size_after = compiler->assembler()->CodeSize(); \
|
|
if (size_before == size_after) return false; \
|
|
if (function.HasUnboxedParameters()) { \
|
|
FATAL("Unsupported unboxed parameters in asm intrinsic %s", \
|
|
function.ToFullyQualifiedCString()); \
|
|
} \
|
|
if (function.HasUnboxedReturnValue()) { \
|
|
FATAL("Unsupported unboxed return value in asm intrinsic %s", \
|
|
function.ToFullyQualifiedCString()); \
|
|
} \
|
|
if (!normal_ir_body.IsBound()) { \
|
|
EMIT_BREAKPOINT(); \
|
|
return true; \
|
|
} \
|
|
return false; \
|
|
}
|
|
|
|
switch (function.recognized_kind()) {
|
|
ASM_INTRINSICS_LIST(EMIT_CASE);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
#undef EMIT_BREAKPOINT
|
|
|
|
#undef EMIT_INTRINSIC
|
|
return false;
|
|
}
|
|
|
|
} // namespace compiler
|
|
} // namespace dart
|