Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8249749: modify a primitive array through a stream and a for cycle ca…
…uses jre crash

Check align_to_ref for NULL early and bailout SuperWord optimization.

Reviewed-by: vlivanov, thartmann
  • Loading branch information
Vladimir Kozlov committed Aug 10, 2020
1 parent 4e9881f commit 84057fea557823918b6d7899422e560ed6eb88ea
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 11 deletions.
@@ -499,6 +499,10 @@ void SuperWord::SLP_extract() {

find_adjacent_refs();

if (align_to_ref() == NULL) {
return; // Did not find memory reference to align vectors
}

extend_packlist();

if (_do_vector_loop) {
@@ -575,6 +579,9 @@ void SuperWord::find_adjacent_refs() {
}
}
}
if (TraceSuperWord) {
tty->print_cr("\nfind_adjacent_refs found %d memops", memops.size());
}

Node_List align_to_refs;
int max_idx;
@@ -3229,15 +3236,15 @@ void SuperWord::compute_vector_element_type() {
//------------------------------memory_alignment---------------------------
// Alignment within a vector memory reference
int SuperWord::memory_alignment(MemNode* s, int iv_adjust) {
#ifndef PRODUCT
if(TraceSuperWord && Verbose) {
tty->print("SuperWord::memory_alignment within a vector memory reference for %d: ", s->_idx); s->dump();
}
#endif
#ifndef PRODUCT
if ((TraceSuperWord && Verbose) || is_trace_alignment()) {
tty->print("SuperWord::memory_alignment within a vector memory reference for %d: ", s->_idx); s->dump();
}
#endif
NOT_PRODUCT(SWPointer::Tracer::Depth ddd(0);)
SWPointer p(s, this, NULL, false);
if (!p.valid()) {
NOT_PRODUCT(if(is_trace_alignment()) tty->print("SWPointer::memory_alignment: SWPointer p invalid, return bottom_align");)
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SWPointer::memory_alignment: SWPointer p invalid, return bottom_align");)
return bottom_align;
}
int vw = get_vw_bytes_special(s);
@@ -3249,9 +3256,11 @@ int SuperWord::memory_alignment(MemNode* s, int iv_adjust) {
offset += iv_adjust*p.memory_size();
int off_rem = offset % vw;
int off_mod = off_rem >= 0 ? off_rem : off_rem + vw;
if (TraceSuperWord && Verbose) {
#ifndef PRODUCT
if ((TraceSuperWord && Verbose) || is_trace_alignment()) {
tty->print_cr("SWPointer::memory_alignment: off_rem = %d, off_mod = %d", off_rem, off_mod);
}
#endif
return off_mod;
}

@@ -3766,6 +3775,7 @@ bool SWPointer::invariant(Node* n) {
NOT_PRODUCT(_tracer.invariant_1(n, n_c);)
return !lpt()->is_member(phase()->get_loop(n_c));
}

//------------------------scaled_iv_plus_offset--------------------
// Match: k*iv + offset
// where: k is a constant that maybe zero, and
@@ -3786,20 +3796,20 @@ bool SWPointer::scaled_iv_plus_offset(Node* n) {

int opc = n->Opcode();
if (opc == Op_AddI) {
if (scaled_iv(n->in(1)) && offset_plus_k(n->in(2))) {
if (offset_plus_k(n->in(2)) && scaled_iv_plus_offset(n->in(1))) {
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_4(n);)
return true;
}
if (scaled_iv(n->in(2)) && offset_plus_k(n->in(1))) {
if (offset_plus_k(n->in(1)) && scaled_iv_plus_offset(n->in(2))) {
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_5(n);)
return true;
}
} else if (opc == Op_SubI) {
if (scaled_iv(n->in(1)) && offset_plus_k(n->in(2), true)) {
if (offset_plus_k(n->in(2), true) && scaled_iv_plus_offset(n->in(1))) {
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_6(n);)
return true;
}
if (scaled_iv(n->in(2)) && offset_plus_k(n->in(1))) {
if (offset_plus_k(n->in(1)) && scaled_iv_plus_offset(n->in(2))) {
_scale *= -1;
NOT_PRODUCT(_tracer.scaled_iv_plus_offset_7(n);)
return true;
@@ -3871,6 +3881,7 @@ bool SWPointer::scaled_iv(Node* n) {
int mult = 1 << n->in(2)->get_int();
_scale = tmp._scale * mult;
_offset += tmp._offset * mult;
_invar = tmp._invar;
NOT_PRODUCT(_tracer.scaled_iv_9(n, _scale, _offset, mult);)
return true;
}
@@ -0,0 +1,169 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. 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 8249749
* @summary Test vectorization for complex address expressions
* @requires vm.compMode != "Xint"
* @run main compiler.vectorization.TestComplexAddrExpr test1
* @run main compiler.vectorization.TestComplexAddrExpr test2
* @run main compiler.vectorization.TestComplexAddrExpr test3
* @run main compiler.vectorization.TestComplexAddrExpr test4
* @run main compiler.vectorization.TestComplexAddrExpr test5
* @run main compiler.vectorization.TestComplexAddrExpr test6
*/

package compiler.vectorization;

import java.util.stream.IntStream;

public class TestComplexAddrExpr {

static final int n = 1024;

static void test1(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 0; i < n; i++) {
data[j * n + i]++;
}
});
}

static void test2(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = n - 1; i >= 0; i--) {
data[j * n + i]--;
}
});
}

static void test3(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 1 - n; i < 1; i++) {
data[j * n - i]++;
}
});
}

static void test4(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 0; i >= 1 - n; i--) {
data[j * n - i]--;
}
});
}

static void test5(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = 0; i < n/2; i++) {
data[j * n + (i << 1)]++;
}
for (int i = 0; i < n/2; i++) {
data[j * n + i * 2 + 1]++;
}
});
}

static void test6(int[] data) {
IntStream.range(0, n).forEach(j -> {
for (int i = (n - 1)/2; i >= 0; i--) {
data[j * n + (i << 1)]--;
}
for (int i = (n - 1)/2; i >= 0; i--) {
data[j * n + i * 2 + 1]--;
}
});
}

static void verify(int[] data, int k) {
for (int i = 0; i < n * n; i++) {
if (data[i] != k) {
throw new RuntimeException(" Invalid result: data[" + i + "]: " + data[i] + " != " + k);
}
}
}

public static void main(String[] args) {
// int n = 1024;
int[] data = new int[n * n];

if (args.length == 0) {
throw new RuntimeException(" Missing test name: test1, test2, test3, test4, test5, test6");
}

if (args[0].equals("test1")) {
System.out.println(" Run test1 ...");
for (int k = 0; k < n; k++) {
test1(data);
}
verify(data, n);
System.out.println(" Finished test1.");
}

if (args[0].equals("test2")) {
System.out.println(" Run test2 ...");
for (int k = 0; k < n; k++) {
test2(data);
}
verify(data, -n);
System.out.println(" Finished test2.");
}

if (args[0].equals("test3")) {
System.out.println(" Run test3 ...");
for (int k = 0; k < n; k++) {
test3(data);
}
verify(data, n);
System.out.println(" Finished test3.");
}

if (args[0].equals("test4")) {
System.out.println(" Run test4 ...");
for (int k = 0; k < n; k++) {
test4(data);
}
verify(data, -n);
System.out.println(" Finished test4.");
}

if (args[0].equals("test5")) {
System.out.println(" Run test5 ...");
for (int k = 0; k < n; k++) {
test5(data);
}
verify(data, n);
System.out.println(" Finished test5.");
}

if (args[0].equals("test6")) {
System.out.println(" Run test6 ...");
for (int k = 0; k < n; k++) {
test6(data);
}
verify(data, -n);
System.out.println(" Finished test6.");
}
}
}

0 comments on commit 84057fe

Please sign in to comment.