mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
JDK-8374582: add opaque node
This commit is contained in:
parent
3c466d372b
commit
3c6722d949
@ -282,6 +282,7 @@ macro(OpaqueLoopStride)
|
|||||||
macro(OpaqueMultiversioning)
|
macro(OpaqueMultiversioning)
|
||||||
macro(OpaqueZeroTripGuard)
|
macro(OpaqueZeroTripGuard)
|
||||||
macro(OpaqueNotNull)
|
macro(OpaqueNotNull)
|
||||||
|
macro(OpaqueGuard)
|
||||||
macro(OpaqueInitializedAssertionPredicate)
|
macro(OpaqueInitializedAssertionPredicate)
|
||||||
macro(OpaqueTemplateAssertionPredicate)
|
macro(OpaqueTemplateAssertionPredicate)
|
||||||
macro(ProfileBoolean)
|
macro(ProfileBoolean)
|
||||||
|
|||||||
@ -1235,6 +1235,7 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional,
|
|||||||
}
|
}
|
||||||
if (!bol->is_Bool()) {
|
if (!bol->is_Bool()) {
|
||||||
assert(bol->is_OpaqueNotNull() ||
|
assert(bol->is_OpaqueNotNull() ||
|
||||||
|
bol->is_OpaqueGuard() ||
|
||||||
bol->is_OpaqueTemplateAssertionPredicate() ||
|
bol->is_OpaqueTemplateAssertionPredicate() ||
|
||||||
bol->is_OpaqueInitializedAssertionPredicate() ||
|
bol->is_OpaqueInitializedAssertionPredicate() ||
|
||||||
bol->is_OpaqueMultiversioning(),
|
bol->is_OpaqueMultiversioning(),
|
||||||
|
|||||||
@ -1705,6 +1705,7 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
|
|||||||
!n->is_MergeMem() &&
|
!n->is_MergeMem() &&
|
||||||
!n->is_CMove() &&
|
!n->is_CMove() &&
|
||||||
!n->is_OpaqueNotNull() &&
|
!n->is_OpaqueNotNull() &&
|
||||||
|
!n->is_OpaqueGuard() &&
|
||||||
!n->is_OpaqueInitializedAssertionPredicate() &&
|
!n->is_OpaqueInitializedAssertionPredicate() &&
|
||||||
!n->is_OpaqueTemplateAssertionPredicate() &&
|
!n->is_OpaqueTemplateAssertionPredicate() &&
|
||||||
!is_raw_to_oop_cast && // don't extend live ranges of raw oops
|
!is_raw_to_oop_cast && // don't extend live ranges of raw oops
|
||||||
@ -2228,7 +2229,7 @@ void PhaseIdealLoop::clone_loop_handle_data_uses(Node* old, Node_List &old_new,
|
|||||||
// split if to break.
|
// split if to break.
|
||||||
assert(!use->is_OpaqueTemplateAssertionPredicate(),
|
assert(!use->is_OpaqueTemplateAssertionPredicate(),
|
||||||
"should not clone a Template Assertion Predicate which should be removed once it's useless");
|
"should not clone a Template Assertion Predicate which should be removed once it's useless");
|
||||||
if (use->is_If() || use->is_CMove() || use->is_OpaqueNotNull() || use->is_OpaqueInitializedAssertionPredicate() ||
|
if (use->is_If() || use->is_CMove() || use->is_OpaqueGuard() || use->is_OpaqueNotNull() || use->is_OpaqueInitializedAssertionPredicate() ||
|
||||||
(use->Opcode() == Op_AllocateArray && use->in(AllocateNode::ValidLengthTest) == old)) {
|
(use->Opcode() == Op_AllocateArray && use->in(AllocateNode::ValidLengthTest) == old)) {
|
||||||
// Since this code is highly unlikely, we lazily build the worklist
|
// Since this code is highly unlikely, we lazily build the worklist
|
||||||
// of such Nodes to go split.
|
// of such Nodes to go split.
|
||||||
|
|||||||
@ -2501,6 +2501,7 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
|
|||||||
n->Opcode() == Op_ModD ||
|
n->Opcode() == Op_ModD ||
|
||||||
n->Opcode() == Op_ModF ||
|
n->Opcode() == Op_ModF ||
|
||||||
n->is_OpaqueNotNull() ||
|
n->is_OpaqueNotNull() ||
|
||||||
|
n->is_OpaqueGuard() ||
|
||||||
n->is_OpaqueInitializedAssertionPredicate() ||
|
n->is_OpaqueInitializedAssertionPredicate() ||
|
||||||
n->Opcode() == Op_MaxL ||
|
n->Opcode() == Op_MaxL ||
|
||||||
n->Opcode() == Op_MinL ||
|
n->Opcode() == Op_MinL ||
|
||||||
@ -2556,6 +2557,17 @@ void PhaseMacroExpand::eliminate_opaque_looplimit_macro_nodes() {
|
|||||||
_igvn.replace_node(n, n->in(1));
|
_igvn.replace_node(n, n->in(1));
|
||||||
#else
|
#else
|
||||||
_igvn.replace_node(n, _igvn.intcon(1));
|
_igvn.replace_node(n, _igvn.intcon(1));
|
||||||
|
#endif
|
||||||
|
success = true;
|
||||||
|
} else if (n->is_OpaqueGuard()) {
|
||||||
|
// Tests with OpaqueGuard nodes are implicitly known to be true or false. Replace the node with appropriate value. In debug builds,
|
||||||
|
// we leave the test in the graph to have an additional sanity check at runtime. If the test fails (i.e. a bug),
|
||||||
|
// we will execute a Halt node.
|
||||||
|
#ifdef ASSERT
|
||||||
|
_igvn.replace_node(n, n->in(1));
|
||||||
|
#else
|
||||||
|
bool is_positive = n->as_OpaqueGuard()->is_positive();
|
||||||
|
_igvn.replace_node(n, _igvn.intcon(is_positive?1:0));
|
||||||
#endif
|
#endif
|
||||||
success = true;
|
success = true;
|
||||||
} else if (n->is_OpaqueInitializedAssertionPredicate()) {
|
} else if (n->is_OpaqueInitializedAssertionPredicate()) {
|
||||||
|
|||||||
@ -143,6 +143,7 @@ class OpaqueLoopInitNode;
|
|||||||
class OpaqueLoopStrideNode;
|
class OpaqueLoopStrideNode;
|
||||||
class OpaqueMultiversioningNode;
|
class OpaqueMultiversioningNode;
|
||||||
class OpaqueNotNullNode;
|
class OpaqueNotNullNode;
|
||||||
|
class OpaqueGuardNode;
|
||||||
class OpaqueInitializedAssertionPredicateNode;
|
class OpaqueInitializedAssertionPredicateNode;
|
||||||
class OpaqueTemplateAssertionPredicateNode;
|
class OpaqueTemplateAssertionPredicateNode;
|
||||||
class OuterStripMinedLoopNode;
|
class OuterStripMinedLoopNode;
|
||||||
@ -822,6 +823,7 @@ public:
|
|||||||
DEFINE_CLASS_ID(Move, Node, 20)
|
DEFINE_CLASS_ID(Move, Node, 20)
|
||||||
DEFINE_CLASS_ID(LShift, Node, 21)
|
DEFINE_CLASS_ID(LShift, Node, 21)
|
||||||
DEFINE_CLASS_ID(Neg, Node, 22)
|
DEFINE_CLASS_ID(Neg, Node, 22)
|
||||||
|
DEFINE_CLASS_ID(OpaqueGuard, Node, 23)
|
||||||
|
|
||||||
_max_classes = ClassMask_Neg
|
_max_classes = ClassMask_Neg
|
||||||
};
|
};
|
||||||
@ -997,6 +999,7 @@ public:
|
|||||||
DEFINE_CLASS_QUERY(NeverBranch)
|
DEFINE_CLASS_QUERY(NeverBranch)
|
||||||
DEFINE_CLASS_QUERY(Opaque1)
|
DEFINE_CLASS_QUERY(Opaque1)
|
||||||
DEFINE_CLASS_QUERY(OpaqueNotNull)
|
DEFINE_CLASS_QUERY(OpaqueNotNull)
|
||||||
|
DEFINE_CLASS_QUERY(OpaqueGuard)
|
||||||
DEFINE_CLASS_QUERY(OpaqueInitializedAssertionPredicate)
|
DEFINE_CLASS_QUERY(OpaqueInitializedAssertionPredicate)
|
||||||
DEFINE_CLASS_QUERY(OpaqueTemplateAssertionPredicate)
|
DEFINE_CLASS_QUERY(OpaqueTemplateAssertionPredicate)
|
||||||
DEFINE_CLASS_QUERY(OpaqueLoopInit)
|
DEFINE_CLASS_QUERY(OpaqueLoopInit)
|
||||||
|
|||||||
@ -112,6 +112,10 @@ const Type* OpaqueNotNullNode::Value(PhaseGVN* phase) const {
|
|||||||
return phase->type(in(1));
|
return phase->type(in(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Type* OpaqueGuardNode::Value(PhaseGVN* phase) const {
|
||||||
|
return phase->type(in(1));
|
||||||
|
}
|
||||||
|
|
||||||
OpaqueTemplateAssertionPredicateNode::OpaqueTemplateAssertionPredicateNode(BoolNode* bol, CountedLoopNode* loop_node)
|
OpaqueTemplateAssertionPredicateNode::OpaqueTemplateAssertionPredicateNode(BoolNode* bol, CountedLoopNode* loop_node)
|
||||||
: Node(nullptr, bol),
|
: Node(nullptr, bol),
|
||||||
_loop_node(loop_node),
|
_loop_node(loop_node),
|
||||||
|
|||||||
@ -148,6 +148,31 @@ class OpaqueNotNullNode : public Node {
|
|||||||
virtual const Type* bottom_type() const { return TypeInt::BOOL; }
|
virtual const Type* bottom_type() const { return TypeInt::BOOL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Similar to OpaqueNotNullNode but for guards. Sometimes we know that a size or limit guard is checked
|
||||||
|
// (e.g. there is already a guard in the caller) but the compiler cannot prove it. We could in principle avoid
|
||||||
|
// adding a guard in the intrinsic but in some cases (e.g. when the input is a constant that breaks the guard
|
||||||
|
// and the caller guard is not inlined) the input of the intrinsic can become top and the data path is folded.
|
||||||
|
// Similar to OpaqueNotNullNode to ensure that the control path is also properly folded, we insert a
|
||||||
|
// OpaqueGuardNode before the If node in the guard. During macro expansion, we replace the OpaqueGuardNode with
|
||||||
|
// the corresponding constant (true/false) in product builds such that the actually unneeded guards
|
||||||
|
// are folded and do not end up in the emitted code. In debug builds, we keep the actual checks as additional
|
||||||
|
// verification code (i.e. removing OpaqueGuardNode and use the BoolNode inputs instead).
|
||||||
|
class OpaqueGuardNode : public Node {
|
||||||
|
private:
|
||||||
|
bool _is_positive;
|
||||||
|
public:
|
||||||
|
OpaqueGuardNode(Compile* C, Node* tst, bool is_positive) : Node(nullptr, tst), _is_positive(is_positive) {
|
||||||
|
init_class_id(Class_OpaqueGuard);
|
||||||
|
init_flags(Flag_is_macro);
|
||||||
|
C->add_macro_node(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int Opcode() const;
|
||||||
|
virtual const Type* Value(PhaseGVN* phase) const;
|
||||||
|
virtual const Type* bottom_type() const { return TypeInt::BOOL; }
|
||||||
|
bool is_positive() const { return _is_positive; }
|
||||||
|
};
|
||||||
|
|
||||||
// This node is used for Template Assertion Predicate BoolNodes. A Template Assertion Predicate is always removed
|
// This node is used for Template Assertion Predicate BoolNodes. A Template Assertion Predicate is always removed
|
||||||
// after loop opts and thus is never converted to actual code. In the post loop opts IGVN phase, the
|
// after loop opts and thus is never converted to actual code. In the post loop opts IGVN phase, the
|
||||||
// OpaqueTemplateAssertionPredicateNode is replaced by true in order to fold the Template Assertion Predicate away.
|
// OpaqueTemplateAssertionPredicateNode is replaced by true in order to fold the Template Assertion Predicate away.
|
||||||
|
|||||||
@ -307,7 +307,7 @@ bool PhaseIdealLoop::clone_cmp_down(Node* n, const Node* blk1, const Node* blk2)
|
|||||||
assert( bol->is_Bool(), "" );
|
assert( bol->is_Bool(), "" );
|
||||||
if (bol->outcnt() == 1) {
|
if (bol->outcnt() == 1) {
|
||||||
Node* use = bol->unique_out();
|
Node* use = bol->unique_out();
|
||||||
if (use->is_OpaqueNotNull() || use->is_OpaqueTemplateAssertionPredicate() ||
|
if (use->is_OpaqueNotNull() || use->is_OpaqueGuard() || use->is_OpaqueTemplateAssertionPredicate() ||
|
||||||
use->is_OpaqueInitializedAssertionPredicate()) {
|
use->is_OpaqueInitializedAssertionPredicate()) {
|
||||||
if (use->outcnt() == 1) {
|
if (use->outcnt() == 1) {
|
||||||
Node* iff = use->unique_out();
|
Node* iff = use->unique_out();
|
||||||
@ -331,8 +331,8 @@ bool PhaseIdealLoop::clone_cmp_down(Node* n, const Node* blk1, const Node* blk2)
|
|||||||
// Recursively sink any BoolNode
|
// Recursively sink any BoolNode
|
||||||
for (DUIterator j = bol->outs(); bol->has_out(j); j++) {
|
for (DUIterator j = bol->outs(); bol->has_out(j); j++) {
|
||||||
Node* u = bol->out(j);
|
Node* u = bol->out(j);
|
||||||
// Uses are either IfNodes, CMoves, OpaqueNotNull, or Opaque*AssertionPredicate
|
// Uses are either IfNodes, CMoves, OpaqueNotNull, OpaqueGuard or Opaque*AssertionPredicate
|
||||||
if (u->is_OpaqueNotNull() || u->is_OpaqueTemplateAssertionPredicate() ||
|
if (u->is_OpaqueNotNull() || u->is_OpaqueGuard() || u->is_OpaqueTemplateAssertionPredicate() ||
|
||||||
u->is_OpaqueInitializedAssertionPredicate()) {
|
u->is_OpaqueInitializedAssertionPredicate()) {
|
||||||
assert(u->in(1) == bol, "bad input");
|
assert(u->in(1) == bol, "bad input");
|
||||||
for (DUIterator_Last kmin, k = u->last_outs(kmin); k >= kmin; --k) {
|
for (DUIterator_Last kmin, k = u->last_outs(kmin); k >= kmin; --k) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user