Skip to content

Commit 48f1a92

Browse files
committed
8316679: C2 SuperWord: wrong result, load should not be moved before store if not comparable
Reviewed-by: kvn, thartmann
1 parent 0b0f8b5 commit 48f1a92

File tree

2 files changed

+106
-7
lines changed

2 files changed

+106
-7
lines changed

src/hotspot/share/opto/superword.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -2565,18 +2565,18 @@ bool SuperWord::output() {
25652565
if (n->is_Load()) {
25662566
Node* ctl = n->in(MemNode::Control);
25672567
Node* mem = first->in(MemNode::Memory);
2568+
// Set the memory dependency of the LoadVector as early as possible.
2569+
// Walk up the memory chain, and ignore any StoreVector that provably
2570+
// does not have any memory dependency.
25682571
VPointer p1(n->as_Mem(), phase(), lpt(), nullptr, false);
2569-
// Identify the memory dependency for the new loadVector node by
2570-
// walking up through memory chain.
2571-
// This is done to give flexibility to the new loadVector node so that
2572-
// it can move above independent storeVector nodes.
25732572
while (mem->is_StoreVector()) {
25742573
VPointer p2(mem->as_Mem(), phase(), lpt(), nullptr, false);
2575-
int cmp = p1.cmp(p2);
2576-
if (VPointer::not_equal(cmp) || !VPointer::comparable(cmp)) {
2574+
if (p1.not_equal(p2)) {
2575+
// Either Less or Greater -> provably no overlap between the two memory regions.
25772576
mem = mem->in(MemNode::Memory);
25782577
} else {
2579-
break; // dependent memory
2578+
// No proof that there is no overlap. Stop here.
2579+
break;
25802580
}
25812581
}
25822582
Node* adr = first->in(MemNode::Address);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
25+
/**
26+
* @test
27+
* @requires vm.compiler2.enabled
28+
* @bug 8316679
29+
* @summary In SuperWord::output, LoadVector can be moved before StoreVector, but only if it is proven to be safe.
30+
* @key randomness
31+
* @library /test/lib
32+
* @run main/othervm -XX:CompileCommand=compileonly,compiler.loopopts.superword.TestMovingLoadBeforeStore::test*
33+
* -Xbatch -XX:LoopUnrollLimit=100
34+
* -XX:+UnlockDiagnosticVMOptions -XX:+StressLCM
35+
* compiler.loopopts.superword.TestMovingLoadBeforeStore
36+
*/
37+
38+
package compiler.loopopts.superword;
39+
import java.util.Random;
40+
import jdk.test.lib.Utils;
41+
42+
public class TestMovingLoadBeforeStore {
43+
static int RANGE = 1024*64;
44+
45+
private static final Random random = Utils.getRandomInstance();
46+
47+
public static void main(String[] strArr) {
48+
byte a[] = new byte[RANGE];
49+
for (int i = 0; i < 100; i++) {
50+
for (int j = 0; j < a.length; j++) {
51+
a[j] = (byte)random.nextInt();
52+
}
53+
byte[] a_ref = a.clone();
54+
byte[] a_res = a.clone();
55+
ref1(a_ref, a_ref, i % 2);
56+
test1(a_res, a_res, i % 2);
57+
verify("a in test1", a_ref, a_res, a);
58+
}
59+
}
60+
61+
static void verify(String name, byte[] ref, byte[] res, byte[] orig) {
62+
boolean fail = false;
63+
for (int j = 0; j < ref.length; j++) {
64+
if (ref[j] != res[j]) {
65+
System.out.println("Wrong: " + j + ":" + ref[j] + " vs " + res[j] + " from " + orig[j]);
66+
fail = true;
67+
}
68+
}
69+
if (fail) {
70+
throw new RuntimeException("wrong result for array " + name);
71+
}
72+
}
73+
74+
static void test1(byte[] a, byte[] b, int inv) {
75+
for (int i = 0; i < RANGE-4; i+=4) {
76+
a[i + 0]++;
77+
a[i + 1]++;
78+
a[i + 2]++;
79+
a[i + 3]++;
80+
b[inv + i + 0]++;
81+
b[inv + i + 1]++;
82+
b[inv + i + 2]++;
83+
b[inv + i + 3]++;
84+
}
85+
}
86+
87+
static void ref1(byte[] a, byte[] b, int inv) {
88+
for (int i = 0; i < RANGE-4; i+=4) {
89+
a[i + 0]++;
90+
a[i + 1]++;
91+
a[i + 2]++;
92+
a[i + 3]++;
93+
b[inv + i + 0]++;
94+
b[inv + i + 1]++;
95+
b[inv + i + 2]++;
96+
b[inv + i + 3]++;
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)