Skip to content

Commit b49bdae

Browse files
Bhavana Kilambinick-arm
authored andcommitted
8294816: C2: Math.min/max vectorization miscompilation
Reviewed-by: thartmann, ngasson
1 parent c206f28 commit b49bdae

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

src/hotspot/share/opto/superword.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,12 @@ bool SuperWord::implemented(Node_List* p) {
20932093
}
20942094
} else if (VectorNode::is_convert_opcode(opc)) {
20952095
retValue = VectorCastNode::implemented(opc, size, velt_basic_type(p0->in(1)), velt_basic_type(p0));
2096+
} else if (VectorNode::is_minmax_opcode(opc) && is_subword_type(velt_basic_type(p0))) {
2097+
// Java API for Math.min/max operations supports only int, long, float
2098+
// and double types. Thus, avoid generating vector min/max nodes for
2099+
// integer subword types with superword vectorization.
2100+
// See JDK-8294816 for miscompilation issues with shorts.
2101+
return false;
20962102
} else {
20972103
// Vector unsigned right shift for signed subword types behaves differently
20982104
// from Java Spec. But when the shift amount is a constant not greater than

src/hotspot/share/opto/vectornode.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ bool VectorNode::is_convert_opcode(int opc) {
476476
}
477477
}
478478

479+
bool VectorNode::is_minmax_opcode(int opc) {
480+
return opc == Op_MinI || opc == Op_MaxI;
481+
}
482+
479483
bool VectorNode::is_shift(Node* n) {
480484
return is_shift_opcode(n->Opcode());
481485
}

src/hotspot/share/opto/vectornode.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class VectorNode : public TypeNode {
8484
static bool is_shift_opcode(int opc);
8585
static bool can_transform_shift_op(Node* n, BasicType bt);
8686
static bool is_convert_opcode(int opc);
87+
static bool is_minmax_opcode(int opc);
8788

8889
static bool is_vshift_cnt_opcode(int opc);
8990

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright (c) 2022, Arm Limited. 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+
package compiler.c2;
25+
26+
import compiler.lib.ir_framework.*;
27+
import jdk.test.lib.Asserts;
28+
import jdk.test.lib.Utils;
29+
import java.util.Random;
30+
31+
/*
32+
* @test
33+
* @bug 8294816
34+
* @summary Test Math.min/max vectorization miscompilation for integer subwords
35+
* @library /test/lib /
36+
* @requires vm.compiler2.enabled
37+
* @run driver compiler.c2.TestMinMaxSubword
38+
*/
39+
40+
public class TestMinMaxSubword {
41+
private static final int LENGTH = 256;
42+
private static final Random RANDOM = Utils.getRandomInstance();
43+
private static int val = 65536;
44+
private static short[] sa;
45+
private static short[] sb;
46+
private static byte[] ba;
47+
private static byte[] bb;
48+
49+
static {
50+
sa = new short[LENGTH];
51+
sb = new short[LENGTH];
52+
ba = new byte[LENGTH];
53+
bb = new byte[LENGTH];
54+
for(int i = 0; i < LENGTH; i++) {
55+
sa[i] = (short) (RANDOM.nextInt(999) + 1);
56+
ba[i] = (byte) (RANDOM.nextInt(99) + 1);
57+
}
58+
}
59+
60+
// Ensure vector max/min instructions are not generated for integer subword types
61+
// as Java APIs for Math.min/max do not support integer subword types and superword
62+
// should not generate vectorized Min/Max nodes for them.
63+
@Test
64+
@IR(failOn = {IRNode.MIN_V})
65+
public static void testMinShort() {
66+
for (int i = 0; i < LENGTH; i++) {
67+
sb[i] = (short) Math.min(sa[i], val);
68+
}
69+
}
70+
71+
@Run(test = "testMinShort")
72+
public static void testMinShort_runner() {
73+
testMinShort();
74+
for (int i = 0; i < LENGTH; i++) {
75+
Asserts.assertEquals(sb[i], sa[i]);
76+
}
77+
}
78+
79+
@Test
80+
@IR(failOn = {IRNode.MAX_V})
81+
public static void testMaxShort() {
82+
for (int i = 0; i < LENGTH; i++) {
83+
sb[i] = (short) Math.max(sa[i], val);
84+
}
85+
}
86+
@Run(test = "testMaxShort")
87+
public static void testMaxShort_runner() {
88+
testMaxShort();
89+
for (int i = 0; i < LENGTH; i++) {
90+
Asserts.assertEquals(sb[i], (short) 0);
91+
}
92+
}
93+
94+
@Test
95+
@IR(failOn = {IRNode.MIN_V})
96+
public static void testMinByte() {
97+
for (int i = 0; i < LENGTH; i++) {
98+
bb[i] = (byte) Math.min(ba[i], val);
99+
}
100+
}
101+
102+
@Run(test = "testMinByte")
103+
public static void testMinByte_runner() {
104+
testMinByte();
105+
for (int i = 0; i < LENGTH; i++) {
106+
Asserts.assertEquals(bb[i], ba[i]);
107+
}
108+
}
109+
110+
@Test
111+
@IR(failOn = {IRNode.MAX_V})
112+
public static void testMaxByte() {
113+
for (int i = 0; i < LENGTH; i++) {
114+
bb[i] = (byte) Math.max(ba[i], val);
115+
}
116+
}
117+
@Run(test = "testMaxByte")
118+
public static void testMaxByte_runner() {
119+
testMaxByte();
120+
for (int i = 0; i < LENGTH; i++) {
121+
Asserts.assertEquals(bb[i], (byte) 0);
122+
}
123+
}
124+
125+
public static void main(String[] args) {
126+
TestFramework.run();
127+
}
128+
}

0 commit comments

Comments
 (0)