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; ...@@ -224,10 +224,13 @@ class CompactInterpreterFrameState;
V(JumpToInlined) \ V(JumpToInlined) \
V(JumpFromInlined) V(JumpFromInlined)
#define TERMINAL_CONTROL_NODE_LIST(V) \
V(Abort) \
V(Return) \
V(Deopt)
#define CONTROL_NODE_LIST(V) \ #define CONTROL_NODE_LIST(V) \
V(Abort) \ TERMINAL_CONTROL_NODE_LIST(V) \
V(Return) \
V(Deopt) \
CONDITIONAL_CONTROL_NODE_LIST(V) \ CONDITIONAL_CONTROL_NODE_LIST(V) \
UNCONDITIONAL_CONTROL_NODE_LIST(V) UNCONDITIONAL_CONTROL_NODE_LIST(V)
...@@ -282,6 +285,11 @@ static constexpr Opcode kLastUnconditionalControlNodeOpcode = ...@@ -282,6 +285,11 @@ static constexpr Opcode kLastUnconditionalControlNodeOpcode =
static constexpr Opcode kFirstUnconditionalControlNodeOpcode = static constexpr Opcode kFirstUnconditionalControlNodeOpcode =
std::min({UNCONDITIONAL_CONTROL_NODE_LIST(V) kLastOpcode}); 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 = static constexpr Opcode kFirstControlNodeOpcode =
std::min({CONTROL_NODE_LIST(V) kLastOpcode}); std::min({CONTROL_NODE_LIST(V) kLastOpcode});
static constexpr Opcode kLastControlNodeOpcode = static constexpr Opcode kLastControlNodeOpcode =
...@@ -313,6 +321,10 @@ constexpr bool IsUnconditionalControlNode(Opcode opcode) { ...@@ -313,6 +321,10 @@ constexpr bool IsUnconditionalControlNode(Opcode opcode) {
return kFirstUnconditionalControlNodeOpcode <= opcode && return kFirstUnconditionalControlNodeOpcode <= opcode &&
opcode <= kLastUnconditionalControlNodeOpcode; opcode <= kLastUnconditionalControlNodeOpcode;
} }
constexpr bool IsTerminalControlNode(Opcode opcode) {
return kFirstTerminalControlNodeOpcode <= opcode &&
opcode <= kLastTerminalControlNodeOpcode;
}
// Forward-declare NodeBase sub-hierarchies. // Forward-declare NodeBase sub-hierarchies.
class Node; class Node;
...@@ -320,6 +332,7 @@ class ControlNode; ...@@ -320,6 +332,7 @@ class ControlNode;
class ConditionalControlNode; class ConditionalControlNode;
class BranchControlNode; class BranchControlNode;
class UnconditionalControlNode; class UnconditionalControlNode;
class TerminalControlNode;
class ValueNode; class ValueNode;
enum class ValueRepresentation : uint8_t { kTagged, kInt32, kFloat64 }; enum class ValueRepresentation : uint8_t { kTagged, kInt32, kFloat64 };
...@@ -1025,6 +1038,10 @@ template <> ...@@ -1025,6 +1038,10 @@ template <>
constexpr bool NodeBase::Is<UnconditionalControlNode>() const { constexpr bool NodeBase::Is<UnconditionalControlNode>() const {
return IsUnconditionalControlNode(opcode()); return IsUnconditionalControlNode(opcode());
} }
template <>
constexpr bool NodeBase::Is<TerminalControlNode>() const {
return IsTerminalControlNode(opcode());
}
// The Node class hierarchy contains all non-control nodes. // The Node class hierarchy contains all non-control nodes.
class Node : public NodeBase { class Node : public NodeBase {
...@@ -3518,10 +3535,9 @@ class ControlNode : public NodeBase { ...@@ -3518,10 +3535,9 @@ class ControlNode : public NodeBase {
return next_post_dominating_hole_; return next_post_dominating_hole_;
} }
void set_next_post_dominating_hole(ControlNode* node) { void set_next_post_dominating_hole(ControlNode* node) {
DCHECK_IMPLIES(node != nullptr, DCHECK_IMPLIES(node != nullptr, node->Is<UnconditionalControlNode>() ||
node->Is<UnconditionalControlNode>() || node->Is<Abort>() || node->Is<TerminalControlNode>() ||
node->Is<Return>() || node->Is<Deopt>() || node->Is<Switch>());
node->Is<Switch>());
next_post_dominating_hole_ = node; next_post_dominating_hole_ = node;
} }
...@@ -3599,6 +3615,26 @@ class BranchControlNode : public ConditionalControlNode { ...@@ -3599,6 +3615,26 @@ class BranchControlNode : public ConditionalControlNode {
BasicBlockRef if_false_; 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> template <size_t InputCount, class Derived>
class BranchControlNodeT : public BranchControlNode { class BranchControlNodeT : public BranchControlNode {
static_assert(IsBranchControlNode(opcode_of<Derived>)); static_assert(IsBranchControlNode(opcode_of<Derived>));
...@@ -3679,10 +3715,10 @@ class JumpFromInlined : public UnconditionalControlNodeT<JumpFromInlined> { ...@@ -3679,10 +3715,10 @@ class JumpFromInlined : public UnconditionalControlNodeT<JumpFromInlined> {
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS() DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
}; };
class Abort : public ControlNode { class Abort : public TerminalControlNode {
public: public:
explicit Abort(uint64_t bitfield, AbortReason reason) explicit Abort(uint64_t bitfield, AbortReason reason)
: ControlNode(bitfield), reason_(reason) { : TerminalControlNode(bitfield), reason_(reason) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Abort>); DCHECK_EQ(NodeBase::opcode(), opcode_of<Abort>);
} }
...@@ -3694,9 +3730,9 @@ class Abort : public ControlNode { ...@@ -3694,9 +3730,9 @@ class Abort : public ControlNode {
const AbortReason reason_; const AbortReason reason_;
}; };
class Return : public ControlNode { class Return : public TerminalControlNode {
public: public:
explicit Return(uint64_t bitfield) : ControlNode(bitfield) { explicit Return(uint64_t bitfield) : TerminalControlNode(bitfield) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Return>); DCHECK_EQ(NodeBase::opcode(), opcode_of<Return>);
} }
...@@ -3705,10 +3741,10 @@ class Return : public ControlNode { ...@@ -3705,10 +3741,10 @@ class Return : public ControlNode {
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS() DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
}; };
class Deopt : public ControlNode { class Deopt : public TerminalControlNode {
public: public:
explicit Deopt(uint64_t bitfield, DeoptimizeReason reason) explicit Deopt(uint64_t bitfield, DeoptimizeReason reason)
: ControlNode(bitfield), reason_(reason) { : TerminalControlNode(bitfield), reason_(reason) {
DCHECK_EQ(NodeBase::opcode(), opcode_of<Deopt>); DCHECK_EQ(NodeBase::opcode(), opcode_of<Deopt>);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "src/maglev/maglev-graph.h" #include "src/maglev/maglev-graph.h"
#include "src/maglev/maglev-interpreter-frame-state.h" #include "src/maglev/maglev-interpreter-frame-state.h"
#include "src/maglev/maglev-ir-inl.h" #include "src/maglev/maglev-ir-inl.h"
#include "src/maglev/maglev-ir.h"
#include "src/maglev/maglev-regalloc-data.h" #include "src/maglev/maglev-regalloc-data.h"
namespace v8 { namespace v8 {
...@@ -81,11 +82,10 @@ ControlNode* HighestPostDominatingHole(ControlNode* first, ...@@ -81,11 +82,10 @@ ControlNode* HighestPostDominatingHole(ControlNode* first,
// Walk the highest branch to find where it goes. // Walk the highest branch to find where it goes.
if (first->id() > second->id()) std::swap(first, second); 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 // reachable control-node of the longest branch (the second control
// node). // node).
if (first->Is<Return>() || first->Is<Deopt>() || first->Is<Abort>() || if (first->Is<TerminalControlNode>() || first->Is<JumpLoop>()) {
first->Is<JumpLoop>()) {
return second; 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