171 lines
5.7 KiB
Diff
171 lines
5.7 KiB
Diff
|
|
diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp
|
||
|
|
index 8c59efb..e32b5e7 100644
|
||
|
|
--- a/src/hotspot/share/opto/cfgnode.cpp
|
||
|
|
+++ b/src/hotspot/share/opto/cfgnode.cpp
|
||
|
|
@@ -1192,6 +1192,30 @@ Node* PhiNode::Identity(PhaseGVN* phase) {
|
||
|
|
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 && !adr_type()->is_known_instance()) {
|
||
|
|
+ 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
|
||
|
|
}
|
||
|
|
|
||
|
|
diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp
|
||
|
|
index 9e22011..bc314c0 100644
|
||
|
|
--- a/src/hotspot/share/opto/memnode.cpp
|
||
|
|
+++ b/src/hotspot/share/opto/memnode.cpp
|
||
|
|
@@ -4554,24 +4554,6 @@ Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||
|
|
}
|
||
|
|
// else preceding memory was not a MergeMem
|
||
|
|
|
||
|
|
- // replace equivalent phis (unfortunately, they do not GVN together)
|
||
|
|
- if (new_mem != NULL && new_mem != new_base &&
|
||
|
|
- new_mem->req() == phi_len && new_mem->in(0) == phi_reg) {
|
||
|
|
- if (new_mem->is_Phi()) {
|
||
|
|
- PhiNode* phi_mem = new_mem->as_Phi();
|
||
|
|
- for (uint i = 1; i < phi_len; i++) {
|
||
|
|
- if (phi_base->in(i) != phi_mem->in(i)) {
|
||
|
|
- phi_mem = NULL;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- if (phi_mem != NULL) {
|
||
|
|
- // equivalent phi nodes; revert to the def
|
||
|
|
- new_mem = new_base;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
// maybe store down a new value
|
||
|
|
Node* new_in = new_mem;
|
||
|
|
if (new_in == new_base) new_in = empty_mem;
|
||
|
|
diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp
|
||
|
|
index 8103c6f..5928f44 100644
|
||
|
|
--- a/src/hotspot/share/opto/type.hpp
|
||
|
|
+++ b/src/hotspot/share/opto/type.hpp
|
||
|
|
@@ -453,6 +453,7 @@ public:
|
||
|
|
const Type* maybe_remove_speculative(bool include_speculative) const;
|
||
|
|
|
||
|
|
virtual bool maybe_null() const { return true; }
|
||
|
|
+ virtual bool is_known_instance() const { return false; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
// support arrays
|
||
|
|
@@ -1390,6 +1391,10 @@ public:
|
||
|
|
return _ptrtype;
|
||
|
|
}
|
||
|
|
|
||
|
|
+ bool is_known_instance() const {
|
||
|
|
+ return _ptrtype->is_known_instance();
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
#ifndef PRODUCT
|
||
|
|
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
|
||
|
|
#endif
|
||
|
|
diff --git a/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java b/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java
|
||
|
|
new file mode 100644
|
||
|
|
index 0000000..d4c93b3
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/test/hotspot/jtreg/compiler/c2/TestReplaceEquivPhis.java
|
||
|
|
@@ -0,0 +1,77 @@
|
||
|
|
+/*
|
||
|
|
+ * Copyright (c) 2020, Huawei Technologies Co. Ltd. All rights reserved.
|
||
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||
|
|
+ *
|
||
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
||
|
|
+ * published by the Free Software Foundation.
|
||
|
|
+ *
|
||
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
||
|
|
+ * accompanied this code).
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License version
|
||
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
||
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
|
+ *
|
||
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
||
|
|
+ * questions.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+/**
|
||
|
|
+ * @test
|
||
|
|
+ * @bug 8243670
|
||
|
|
+ * @summary Unexpected test result caused by C2 MergeMemNode::Ideal
|
||
|
|
+ *
|
||
|
|
+ * @run main/othervm -Xcomp -XX:-SplitIfBlocks
|
||
|
|
+ * -XX:CompileOnly=compiler.c2.TestReplaceEquivPhis::test
|
||
|
|
+ * -XX:-BackgroundCompilation compiler.c2.TestReplaceEquivPhis
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+package compiler.c2;
|
||
|
|
+
|
||
|
|
+public class TestReplaceEquivPhis {
|
||
|
|
+
|
||
|
|
+ public static final int N = 400;
|
||
|
|
+ public static volatile int instanceCount = 0;
|
||
|
|
+ public int iFld = 0;
|
||
|
|
+ public static int iArrFld[] = new int[N];
|
||
|
|
+
|
||
|
|
+ public int test() {
|
||
|
|
+ int v = 0;
|
||
|
|
+ boolean bArr[] = new boolean[N];
|
||
|
|
+
|
||
|
|
+ for (int i = 1; i < 344; i++) {
|
||
|
|
+ iFld = i;
|
||
|
|
+ for (int j = 2; j <177 ; j++) {
|
||
|
|
+ v = iFld;
|
||
|
|
+ iFld = TestReplaceEquivPhis.instanceCount;
|
||
|
|
+ TestReplaceEquivPhis.iArrFld[i] = 0;
|
||
|
|
+ iFld += TestReplaceEquivPhis.instanceCount;
|
||
|
|
+ TestReplaceEquivPhis.iArrFld[i] = 0;
|
||
|
|
+ bArr[j] = false;
|
||
|
|
+ TestReplaceEquivPhis.instanceCount = 1;
|
||
|
|
+
|
||
|
|
+ for (int k = 1; k < 3; k++) {
|
||
|
|
+ // do nothing
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ return v;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ public static void main(String[] args) {
|
||
|
|
+ TestReplaceEquivPhis obj = new TestReplaceEquivPhis();
|
||
|
|
+ for (int i = 0; i < 5; i++) {
|
||
|
|
+ int result = obj.test();
|
||
|
|
+ if (result != 2) {
|
||
|
|
+ throw new RuntimeException("Test failed.");
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ System.out.println("Test passed.");
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+}
|