8219902: C2: MemNode::can_see_stored_value() ignores casts which carry control dependency

Reviewed-by: kvn
This commit is contained in:
Vladimir Ivanov 2019-05-06 12:15:55 -07:00
parent 75d4f24c97
commit 2e0c5db11d
3 changed files with 20 additions and 14 deletions

View File

@ -1047,11 +1047,11 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
// Try harder before giving up. Unify base pointers with casts (e.g., raw/non-raw pointers).
intptr_t st_off = 0;
Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_off);
if (ld_base == NULL) return NULL;
if (st_base == NULL) return NULL;
if (ld_base->uncast() != st_base->uncast()) return NULL;
if (ld_off != st_off) return NULL;
if (ld_off == Type::OffsetBot) return NULL;
if (ld_base == NULL) return NULL;
if (st_base == NULL) return NULL;
if (!ld_base->eqv_uncast(st_base, /*keep_deps=*/true)) return NULL;
if (ld_off != st_off) return NULL;
if (ld_off == Type::OffsetBot) return NULL;
// Same base, same offset.
// Possible improvement for arrays: check index value instead of absolute offset.
@ -1062,6 +1062,7 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
// (Actually, we haven't yet proven the Q's are the same.)
// In other words, we are loading from a casted version of
// the same pointer-and-offset that we stored to.
// Casted version may carry a dependency and it is respected.
// Thus, we are able to replace L by V.
}
// Now prove that we have a LoadQ matched to a StoreQ, for some Q.

View File

@ -891,13 +891,15 @@ int Node::disconnect_inputs(Node *n, Compile* C) {
//-----------------------------uncast---------------------------------------
// %%% Temporary, until we sort out CheckCastPP vs. CastPP.
// Strip away casting. (It is depth-limited.)
Node* Node::uncast() const {
// Optionally, keep casts with dependencies.
Node* Node::uncast(bool keep_deps) const {
// Should be inline:
//return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
if (is_ConstraintCast())
return uncast_helper(this);
else
if (is_ConstraintCast()) {
return uncast_helper(this, keep_deps);
} else {
return (Node*) this;
}
}
// Find out of current node that matches opcode.
@ -929,7 +931,7 @@ bool Node::has_out_with(int opcode1, int opcode2, int opcode3, int opcode4) {
//---------------------------uncast_helper-------------------------------------
Node* Node::uncast_helper(const Node* p) {
Node* Node::uncast_helper(const Node* p, bool keep_deps) {
#ifdef ASSERT
uint depth_count = 0;
const Node* orig_p = p;
@ -947,6 +949,9 @@ Node* Node::uncast_helper(const Node* p) {
if (p == NULL || p->req() != 2) {
break;
} else if (p->is_ConstraintCast()) {
if (keep_deps && p->as_ConstraintCast()->carry_dependency()) {
break; // stop at casts with dependencies
}
p = p->in(1);
} else {
break;

View File

@ -456,10 +456,10 @@ protected:
void setup_is_top();
// Strip away casting. (It is depth-limited.)
Node* uncast() const;
Node* uncast(bool keep_deps = false) const;
// Return whether two Nodes are equivalent, after stripping casting.
bool eqv_uncast(const Node* n) const {
return (this->uncast() == n->uncast());
bool eqv_uncast(const Node* n, bool keep_deps = false) const {
return (this->uncast(keep_deps) == n->uncast(keep_deps));
}
// Find out of current node that matches opcode.
@ -470,7 +470,7 @@ protected:
bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
private:
static Node* uncast_helper(const Node* n);
static Node* uncast_helper(const Node* n, bool keep_deps);
// Add an output edge to the end of the list
void add_out( Node *n ) {