Commit 9438113d authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add control node class for terminal nodes

Allow distinguishing control nodes that do and don't allow continued
execution.

Bug: v8:7700
Change-Id: Ifa13b64821484584929bd62a0d8585aee160c19e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3891255
Commit-Queue: Jakob Linke <jgruber@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarJakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83143}
parent 66b788de
......@@ -224,10 +224,13 @@ class CompactInterpreterFrameState;
V(JumpToInlined) \
V(JumpFromInlined)
#define TERMINAL_CONTROL_NODE_LIST(V) \
V(Abort) \
V(Return) \
V(Deopt)
#define CONTROL_NODE_LIST(V) \
V(Abort) \
V(Return) \
V(Deopt) \
TERMINAL_CONTROL_NODE_LIST(V) \
CONDITIONAL_CONTROL_NODE_LIST(V) \
UNCONDITIONAL_CONTROL_NODE_LIST(V)
......@@ -282,6 +285,11 @@ static constexpr Opcode kLastUnconditionalControlNodeOpcode =
static constexpr Opcode kFirstUnconditionalControlNodeOpcode =
std::min({UNCONDITIONAL_CONTROL_NODE_LIST(V) kLastOpcode});
static constexpr Opcode kLastTerminalControlNodeOpcode =
std::max({TERMINAL_CONTROL_NODE_LIST(V) kFirstOpcode});
static constexpr Opcode kFirstTerminalControlNodeOpcode =
std::min({TERMINAL_CONTROL_NODE_LIST(V) kLastOpcode});
static constexpr Opcode kFirstControlNodeOpcode =
std::min({CONTROL_NODE_LIST(V) kLastOpcode});
static constexpr Opcode kLastControlNodeOpcode =
......@@ -313,6 +321,10 @@ constexpr bool IsUnconditionalControlNode(Opcode opcode) {
return kFirstUnconditionalControlNodeOpcode <= opcode &&
opcode <= kLastUnconditionalControlNodeOpcode;
}
constexpr bool IsTerminalControlNode(Opcode opcode) {
return kFirstTerminalControlNodeOpcode <= opcode &&
opcode <= kLastTerminalControlNodeOpcode;
}
// Forward-declare NodeBase sub-hierarchies.
class Node;
......@@ -320,6 +332,7 @@ class ControlNode;
class ConditionalControlNode;
class BranchControlNode;
class UnconditionalControlNode;
class TerminalControlNode;
class ValueNode;
enum class ValueRepresentation : uint8_t { kTagged, kInt32, kFloat64 };
......@@ -1025,6 +1038,10 @@ template <>
constexpr bool NodeBase::Is<UnconditionalControlNode>() const {
return IsUnconditionalControlNode(opcode());
}
template <>
constexpr bool NodeBase::Is<TerminalControlNode>() const {
return IsTerminalControlNode(opcode());
}
// The Node class hierarchy contains all non-control nodes.
class Node : public NodeBase {
......@@ -3518,10 +3535,9 @@ class ControlNode : public NodeBase {
return next_post_dominating_hole_;
}
void set_next_post_dominating_hole(ControlNode* node) {
DCHECK_IMPLIES(node != nullptr,
node->Is<UnconditionalControlNode>() || node->Is<Abort>() ||
node->Is<Return>() || node->Is<Deopt>() ||
node->Is<Switch>());
DCHECK_IMPLIES(node != nullptr, node->Is<UnconditionalControlNode>() ||
node->Is<TerminalControlNode>() ||
node->Is<Switch>());
next_post_dominating_hole_ = node;
}
......@@ -3599,6 +3615,26 @@ class BranchControlNode : public ConditionalControlNode {
BasicBlockRef if_false_;
};
class TerminalControlNode : public ControlNode {
protected:
explicit TerminalControlNode(uint64_t bitfield) : ControlNode(bitfield) {}
};
template <class Derived>
class TerminalControlNodeT : public TerminalControlNode {
static_assert(IsTerminalControlNode(opcode_of<Derived>));
public:
// Shadowing for static knowledge.
constexpr Opcode opcode() const { return NodeBase::opcode_of<Derived>; }
protected:
explicit TerminalControlNodeT(uint64_t bitfield)
: TerminalControlNode(bitfield) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Derived>);
}
};
template <size_t InputCount, class Derived>
class BranchControlNodeT : public BranchControlNode {
static_assert(IsBranchControlNode(opcode_of<Derived>));
......@@ -3679,10 +3715,10 @@ class JumpFromInlined : public UnconditionalControlNodeT<JumpFromInlined> {
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
};
class Abort : public ControlNode {
class Abort : public TerminalControlNode {
public:
explicit Abort(uint64_t bitfield, AbortReason reason)
: ControlNode(bitfield), reason_(reason) {
: TerminalControlNode(bitfield), reason_(reason) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Abort>);
}
......@@ -3694,9 +3730,9 @@ class Abort : public ControlNode {
const AbortReason reason_;
};
class Return : public ControlNode {
class Return : public TerminalControlNode {
public:
explicit Return(uint64_t bitfield) : ControlNode(bitfield) {
explicit Return(uint64_t bitfield) : TerminalControlNode(bitfield) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Return>);
}
......@@ -3705,10 +3741,10 @@ class Return : public ControlNode {
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
};
class Deopt : public ControlNode {
class Deopt : public TerminalControlNode {
public:
explicit Deopt(uint64_t bitfield, DeoptimizeReason reason)
: ControlNode(bitfield), reason_(reason) {
: TerminalControlNode(bitfield), reason_(reason) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Deopt>);
}
......
......@@ -20,6 +20,7 @@
#include "src/maglev/maglev-graph.h"
#include "src/maglev/maglev-interpreter-frame-state.h"
#include "src/maglev/maglev-ir-inl.h"
#include "src/maglev/maglev-ir.h"
#include "src/maglev/maglev-regalloc-data.h"
namespace v8 {
......@@ -81,11 +82,10 @@ ControlNode* HighestPostDominatingHole(ControlNode* first,
// Walk the highest branch to find where it goes.
if (first->id() > second->id()) std::swap(first, second);
// If the first branch returns or jumps back, we've found highest
// If the first branch terminates or jumps back, we've found highest
// reachable control-node of the longest branch (the second control
// node).
if (first->Is<Return>() || first->Is<Deopt>() || first->Is<Abort>() ||
first->Is<JumpLoop>()) {
if (first->Is<TerminalControlNode>() || first->Is<JumpLoop>()) {
return second;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment