[CSA][codegen] Add BitcastElision Phase
Turbofan generates bitcast nodes like BitcastWordToTaggedSigned to ensure the value types of definitions and uses are matched. These nodes can be elided after MachineGraphVerifier verifying the graph. This can avoid generating redundant instructions: Before: xorl r15,r15 cmpl [rdx+0xb],r15 After: cmpl [rdx+0xb],0x0 Change-Id: I84bc1b05d77ed9487001e34a93dfe14e45a7a678 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3837161 Commit-Queue: Hao A Xu <hao.a.xu@intel.com> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#83811}
This commit is contained in:
parent
680225d17e
commit
024e5fb4fa
@ -2664,6 +2664,8 @@ filegroup(
|
|||||||
"src/compiler/all-nodes.h",
|
"src/compiler/all-nodes.h",
|
||||||
"src/compiler/allocation-builder.h",
|
"src/compiler/allocation-builder.h",
|
||||||
"src/compiler/allocation-builder-inl.h",
|
"src/compiler/allocation-builder-inl.h",
|
||||||
|
"src/compiler/backend/bitcast-elider.cc",
|
||||||
|
"src/compiler/backend/bitcast-elider.h",
|
||||||
"src/compiler/backend/code-generator.cc",
|
"src/compiler/backend/code-generator.cc",
|
||||||
"src/compiler/backend/code-generator.h",
|
"src/compiler/backend/code-generator.h",
|
||||||
"src/compiler/backend/code-generator-impl.h",
|
"src/compiler/backend/code-generator-impl.h",
|
||||||
|
2
BUILD.gn
2
BUILD.gn
@ -2806,6 +2806,7 @@ v8_header_set("v8_internal_headers") {
|
|||||||
"src/compiler/all-nodes.h",
|
"src/compiler/all-nodes.h",
|
||||||
"src/compiler/allocation-builder-inl.h",
|
"src/compiler/allocation-builder-inl.h",
|
||||||
"src/compiler/allocation-builder.h",
|
"src/compiler/allocation-builder.h",
|
||||||
|
"src/compiler/backend/bitcast-elider.h",
|
||||||
"src/compiler/backend/code-generator-impl.h",
|
"src/compiler/backend/code-generator-impl.h",
|
||||||
"src/compiler/backend/code-generator.h",
|
"src/compiler/backend/code-generator.h",
|
||||||
"src/compiler/backend/frame-elider.h",
|
"src/compiler/backend/frame-elider.h",
|
||||||
@ -4045,6 +4046,7 @@ v8_compiler_sources = [
|
|||||||
"src/compiler/access-info.cc",
|
"src/compiler/access-info.cc",
|
||||||
"src/compiler/add-type-assertions-reducer.cc",
|
"src/compiler/add-type-assertions-reducer.cc",
|
||||||
"src/compiler/all-nodes.cc",
|
"src/compiler/all-nodes.cc",
|
||||||
|
"src/compiler/backend/bitcast-elider.cc",
|
||||||
"src/compiler/backend/code-generator.cc",
|
"src/compiler/backend/code-generator.cc",
|
||||||
"src/compiler/backend/frame-elider.cc",
|
"src/compiler/backend/frame-elider.cc",
|
||||||
"src/compiler/backend/gap-resolver.cc",
|
"src/compiler/backend/gap-resolver.cc",
|
||||||
|
62
src/compiler/backend/bitcast-elider.cc
Normal file
62
src/compiler/backend/bitcast-elider.cc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/compiler/backend/bitcast-elider.h"
|
||||||
|
|
||||||
|
#include "src/compiler/graph.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool IsBitcast(Node* node) {
|
||||||
|
// We can only elide kBitcastTaggedToWordForTagAndSmiBits and
|
||||||
|
// kBitcastWordToTaggedSigned because others might affect GC / safepoint
|
||||||
|
// tables.
|
||||||
|
return node->opcode() == IrOpcode::kBitcastTaggedToWordForTagAndSmiBits ||
|
||||||
|
node->opcode() == IrOpcode::kBitcastWordToTaggedSigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void BitcastElider::Enqueue(Node* node) {
|
||||||
|
if (seen_.Get(node)) return;
|
||||||
|
seen_.Set(node, true);
|
||||||
|
to_visit_.push(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitcastElider::VisitNode(Node* node) {
|
||||||
|
for (int i = 0; i < node->InputCount(); i++) {
|
||||||
|
Node* input = node->InputAt(i);
|
||||||
|
bool should_replace_input = false;
|
||||||
|
while (IsBitcast(input)) {
|
||||||
|
input = input->InputAt(0);
|
||||||
|
should_replace_input = true;
|
||||||
|
}
|
||||||
|
if (should_replace_input) {
|
||||||
|
node->ReplaceInput(i, input);
|
||||||
|
}
|
||||||
|
Enqueue(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitcastElider::ProcessGraph() {
|
||||||
|
Enqueue(graph_->end());
|
||||||
|
while (!to_visit_.empty()) {
|
||||||
|
Node* node = to_visit_.front();
|
||||||
|
to_visit_.pop();
|
||||||
|
VisitNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BitcastElider::BitcastElider(Zone* zone, Graph* graph)
|
||||||
|
: graph_(graph), to_visit_(zone), seen_(graph, 2) {}
|
||||||
|
|
||||||
|
void BitcastElider::Reduce() { ProcessGraph(); }
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
41
src/compiler/backend/bitcast-elider.h
Normal file
41
src/compiler/backend/bitcast-elider.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef V8_COMPILER_BACKEND_BITCAST_ELIDER_H_
|
||||||
|
#define V8_COMPILER_BACKEND_BITCAST_ELIDER_H_
|
||||||
|
|
||||||
|
#include "src/compiler/node-marker.h"
|
||||||
|
#include "src/compiler/node.h"
|
||||||
|
#include "src/zone/zone.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
class Graph;
|
||||||
|
|
||||||
|
// Elide all the Bitcast nodes which are required by MachineGraphVerifier. This
|
||||||
|
// avoid generating redundant move instructions in instruction selection phase.
|
||||||
|
class BitcastElider {
|
||||||
|
public:
|
||||||
|
BitcastElider(Zone* zone, Graph* graph);
|
||||||
|
~BitcastElider() = default;
|
||||||
|
|
||||||
|
void Reduce();
|
||||||
|
|
||||||
|
void Enqueue(Node* node);
|
||||||
|
void VisitNode(Node* node);
|
||||||
|
void ProcessGraph();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Graph* const graph_;
|
||||||
|
ZoneQueue<Node*> to_visit_;
|
||||||
|
NodeMarker<bool> seen_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
||||||
|
|
||||||
|
#endif // V8_COMPILER_BACKEND_BITCAST_ELIDER_H_
|
@ -20,6 +20,7 @@
|
|||||||
#include "src/common/high-allocation-throughput-scope.h"
|
#include "src/common/high-allocation-throughput-scope.h"
|
||||||
#include "src/compiler/add-type-assertions-reducer.h"
|
#include "src/compiler/add-type-assertions-reducer.h"
|
||||||
#include "src/compiler/all-nodes.h"
|
#include "src/compiler/all-nodes.h"
|
||||||
|
#include "src/compiler/backend/bitcast-elider.h"
|
||||||
#include "src/compiler/backend/code-generator.h"
|
#include "src/compiler/backend/code-generator.h"
|
||||||
#include "src/compiler/backend/frame-elider.h"
|
#include "src/compiler/backend/frame-elider.h"
|
||||||
#include "src/compiler/backend/instruction-selector.h"
|
#include "src/compiler/backend/instruction-selector.h"
|
||||||
@ -2383,6 +2384,14 @@ struct InstructionSelectionPhase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BitcastElisionPhase {
|
||||||
|
DECL_PIPELINE_PHASE_CONSTANTS(BitcastElision)
|
||||||
|
|
||||||
|
void Run(PipelineData* data, Zone* temp_zone) {
|
||||||
|
BitcastElider bitcast_optimizer(temp_zone, data->graph());
|
||||||
|
bitcast_optimizer.Reduce();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct MeetRegisterConstraintsPhase {
|
struct MeetRegisterConstraintsPhase {
|
||||||
DECL_PIPELINE_PHASE_CONSTANTS(MeetRegisterConstraints)
|
DECL_PIPELINE_PHASE_CONSTANTS(MeetRegisterConstraints)
|
||||||
@ -3729,6 +3738,10 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
|
|||||||
data->debug_name(), &temp_zone);
|
data->debug_name(), &temp_zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Builtins::IsBuiltinId(data->info()->builtin())) {
|
||||||
|
Run<BitcastElisionPhase>();
|
||||||
|
}
|
||||||
|
|
||||||
data->InitializeInstructionSequence(call_descriptor);
|
data->InitializeInstructionSequence(call_descriptor);
|
||||||
|
|
||||||
// Depending on which code path led us to this function, the frame may or
|
// Depending on which code path led us to this function, the frame may or
|
||||||
|
@ -323,6 +323,7 @@ class RuntimeCallTimer final {
|
|||||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateGeneralRegisters) \
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateGeneralRegisters) \
|
||||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AssembleCode) \
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AssembleCode) \
|
||||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AssignSpillSlots) \
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AssignSpillSlots) \
|
||||||
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BitcastElision) \
|
||||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BranchConditionDuplication) \
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BranchConditionDuplication) \
|
||||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BuildLiveRangeBundles) \
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BuildLiveRangeBundles) \
|
||||||
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BuildLiveRanges) \
|
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BuildLiveRanges) \
|
||||||
|
@ -48,6 +48,7 @@ export const CATEGORIES = new Map([
|
|||||||
'V8.TFAllocateGeneralRegisters',
|
'V8.TFAllocateGeneralRegisters',
|
||||||
'V8.TFAssembleCode',
|
'V8.TFAssembleCode',
|
||||||
'V8.TFAssignSpillSlots',
|
'V8.TFAssignSpillSlots',
|
||||||
|
'V8.TFBitcastElision',
|
||||||
'V8.TFBuildLiveRangeBundles',
|
'V8.TFBuildLiveRangeBundles',
|
||||||
'V8.TFBuildLiveRanges',
|
'V8.TFBuildLiveRanges',
|
||||||
'V8.TFBytecodeGraphBuilder',
|
'V8.TFBytecodeGraphBuilder',
|
||||||
|
Loading…
Reference in New Issue
Block a user