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

Yangfei (Felix) felix.yang at huawei.com
Mon Jun 22 07:37:48 UTC 2020


Hi Roland,

> -----Original Message-----
> From: Roland Westrelin [mailto:rwestrel at redhat.com]
> Sent: Friday, June 19, 2020 10:28 PM
> To: Yangfei (Felix) <felix.yang at huawei.com>; Tobias Hartmann
> <tobias.hartmann at oracle.com>; hotspot-compiler-dev at openjdk.java.net
> Subject: RE: RFR(S): 8243670: Unexpected test result caused by C2
> MergeMemNode::Ideal
> 
> 
> Hi Felix,
> 
> > So I guess it might be safer to go with the initially proposed patch.
> 
> What about a PhiNode::Identity transformation that, for a memory phi, looks
> for phis with identical inputs and if it finds one that has type
> TypePtr::BOTTOM, replaces the current phi with the bottom phi? Wouldn't
> that result in both the LoadI and the MergeMem with the same memory
> input which would fix the problem?

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()) {
+    for (uint i = 0; i < outcnt(); i++) {
+      Node* mmem = raw_out(i);
+      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
 }

With this patch, in MergeMemNode::Ideal we have:
(gdb) p this->dump()
 556    MergeMem        === _  1  660  660  1  660  [[ 559 ]]  { - - - }  Memory: @BotPTR *+bot, idx=Bot; !orig=151 !jvms: TestReplaceEquivPhis::test @ bci:25

Here, node 655 & 657 are both replaced by node 660 and this is reflected the inputs of the MergeMem node.

After MergeMemNode::Ideal, we have:
(gdb) p this->dump()
 556    MergeMem        === _  1  660  1  1  1  [[ 559 ]]  { - - - }  Memory: @BotPTR *+bot, idx=Bot; !orig=151 !jvms: TestReplaceEquivPhis::test @ bci:25

(gdb) p this->find(660)->dump()
 660    Phi     ===  679  752  583  [[ 556  533  516 ]]  #memory  Memory: @BotPTR *+bot, idx=Bot; !orig=[655]

(gdb) p this->find(516)->dump()
 516    LoadI   === _  660  423  [[ 680  799  798  797  796 ]]  @TestReplaceEquivPhis+12 *, name=iFld, idx=5; #int !orig=177 !jvms: TestReplaceEquivPhis::test @ bci:34

Tiered 1-3 tested on x86_64-linux-gnu.  Does it look good?

Thanks,
Felix


More information about the hotspot-compiler-dev mailing list