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

Yangfei (Felix) felix.yang at huawei.com
Mon Jun 22 11:52:22 UTC 2020


Hi Roland,

  Thanks for the suggestions.

> -----Original Message-----
> From: Roland Westrelin [mailto:rwestrel at redhat.com]
> Sent: Monday, June 22, 2020 4:12 PM
> To: Yangfei (Felix) <felix.yang at huawei.com>; Tobias Hartmann
> <tobias.hartmann at oracle.com>; hotspot-compiler-dev at openjdk.java.net
> Cc: guoge (A) <guoge1 at huawei.com>; zhouyong (V)
> <zhouyong44 at huawei.com>
> Subject: RE: RFR(S): 8243670: Unexpected test result caused by C2
> MergeMemNode::Ideal
> 
> 
> 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.

OK.

> > +    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).

OK.

> > +      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;
>     }
>   }
> }

That looks much better.  I modified accordingly. 
Does the updated patch look better? 
Tier1-3 tested on x86_64-linux-gnu.  Will propose a webrev for that. 

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 18:45:43 2020 +0800
@@ -1335,6 +1335,28 @@
     if (id != NULL)  return id;
   }

+  // Looking for phis with identical inputs.  If we find one that has
+  // type TypePtr::BOTTOM, replace the current phi with the bottom phi.
+  if (phase->is_IterGVN() && type() == Type::MEMORY && adr_type() != TypePtr::BOTTOM) {
+    uint phi_len = req();
+    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->as_Phi()->type() == Type::MEMORY &&
+          u->adr_type() == TypePtr::BOTTOM && u->in(0) == phi_reg && u->req() == phi_len) {
+        for (uint j = 1; j < phi_len; j++) {
+          if (in(j) != u->in(j)) {
+            u = NULL;
+            break;
+          }
+        }
+        if (u != NULL) {
+          return u;
+        }
+      }
+    }
+  }
+
   return this;                     // No identity
 }

Felix


More information about the hotspot-compiler-dev mailing list