RFR(S): 8243670: Unexpected test result caused by C2 MergeMemNode::Ideal

Roland Westrelin rwestrel at redhat.com
Mon Jun 22 08:11:53 UTC 2020


Hi Felix,

See comments below

> That sounds promising.  I tried the following patch and looks like it works as expected.
>
> diff -r 2342d5af52b7 src/hotspot/share/opto/cfgnode.cpp
> --- a/src/hotspot/share/opto/cfgnode.cpp        Mon Jun 22 08:09:23 2020 +0200
> +++ b/src/hotspot/share/opto/cfgnode.cpp        Mon Jun 22 15:33:06 2020 +0800
> @@ -1335,6 +1335,43 @@
>      if (id != NULL)  return id;
>    }
>
> +  // replace equivalent phis
> +  if (type()->has_memory()) {

It's likely unsafe to perform that transformation at GVN time so I think
it needs to be performed only if phase->is_IterGVN() != NULL.

> +    for (uint i = 0; i < outcnt(); i++) {
> +      Node* mmem = raw_out(i);

The usual pattern is to use one of the iterators (DUIterator_Fast in
this case).

> +      if (!mmem->is_MergeMem()) {
> +        continue;
> +      }
> +
> +      uint phi_len = req();
> +      Node* phi_reg = region();
> +      // Look at each slice looking for phis with identical inputs.
> +      // If we find one that has type TypePtr::BOTTOM, replace the
> +      // current phi with the bottom phi.
> +      for (uint j = Compile::AliasIdxBot; j < mmem->req(); j++) {
> +        Node* node = mmem->in(j);
> +        if (node == this || !node->is_Phi()) {
> +          continue;
> +        }
> +        if (node->req() == phi_len && node->in(0) == phi_reg) {
> +          PhiNode* phi_mem = node->as_Phi();
> +          if (phi_mem->adr_type() != TypePtr::BOTTOM) {
> +            continue;
> +          }
> +          for (uint k = 1; k < phi_len; k++) {
> +            if (in(k) != phi_mem->in(k)) {
> +              phi_mem = NULL;
> +              break;
> +            }
> +          }
> +          if (phi_mem != NULL) {
> +            return phi_mem;
> +          }
> +        }
> +      }
> +    }
> +  }
> +
>    return this;                     // No identity
>  }

I would make this fully generic:

if (phase->is_IterGVN() && type() == Type::MEMORY && adr_type() != TypePtr::BOTTOM) {
  Node* phi_reg = region();
  for (DUIterator_Fast imax, i = phi_reg->fast_outs(imax); i < imax; i++) {
    Node* u = phi_reg->fast_out(i);
    if (u->is_Phi() && u->in(0) == phi_reg && type() == Type::MEMORY && u->adr_type() == TypePtr::BOTTOM) {
      return u;
    }
  }
}

Roland.



More information about the hotspot-compiler-dev mailing list