8373502: C2 SuperWord: speculative check uses VPointer variable was pinned after speculative check, leading to bad graph

Reviewed-by: mhaessig, chagedorn
Backport-of: 00050f84d44f3ec23e9c6da52bffd68770010749
This commit is contained in:
Emanuel Peter 2025-12-23 11:43:23 +00:00
parent cece06f1aa
commit 3db9a5affe
3 changed files with 112 additions and 0 deletions

View File

@ -1060,6 +1060,29 @@ bool VPointer::can_make_speculative_aliasing_check_with(const VPointer& other) c
return false;
}
// The speculative check also needs to create the pointer expressions for both
// VPointers. We must check that we can do that, i.e. that all variables of the
// VPointers are available at the speculative check (and not just pre-loop invariant).
if (!this->can_make_pointer_expression_at_speculative_check()) {
#ifdef ASSERT
if (_vloop.is_trace_speculative_aliasing_analysis()) {
tty->print_cr("VPointer::can_make_speculative_aliasing_check_with: not all variables of VPointer are avaialbe at speculative check!");
this->print_on(tty);
}
#endif
return false;
}
if (!other.can_make_pointer_expression_at_speculative_check()) {
#ifdef ASSERT
if (_vloop.is_trace_speculative_aliasing_analysis()) {
tty->print_cr("VPointer::can_make_speculative_aliasing_check_with: not all variables of VPointer are avaialbe at speculative check!");
other.print_on(tty);
}
#endif
return false;
}
return true;
}
@ -1147,6 +1170,8 @@ BoolNode* VPointer::make_speculative_aliasing_check_with(const VPointer& other,
Node* main_init = new ConvL2INode(main_initL);
phase->register_new_node_with_ctrl_of(main_init, pre_init);
assert(vp1.can_make_pointer_expression_at_speculative_check(), "variables must be available early enough to avoid cycles");
assert(vp2.can_make_pointer_expression_at_speculative_check(), "variables must be available early enough to avoid cycles");
Node* p1_init = vp1.make_pointer_expression(main_init, ctrl);
Node* p2_init = vp2.make_pointer_expression(main_init, ctrl);
Node* size1 = igvn.longcon(vp1.size());

View File

@ -1188,6 +1188,22 @@ private:
return true;
}
// We already know that all non-iv summands are pre loop invariant.
// See init_are_non_iv_summands_pre_loop_invariant
// That is good enough for alignment computations in the pre-loop limit. But it is not
// sufficient if we want to use the variables of the VPointer at the speculative check,
// which is further up before the pre-loop.
bool can_make_pointer_expression_at_speculative_check() const {
bool success = true;
mem_pointer().for_each_non_empty_summand([&] (const MemPointerSummand& s) {
Node* variable = s.variable();
if (variable != _vloop.iv() && !_vloop.is_available_for_speculative_check(variable)) {
success = false;
}
});
return success;
}
// In the pointer analysis, and especially the AlignVector analysis, we assume that
// stride and scale are not too large. For example, we multiply "iv_scale * iv_stride",
// and assume that this does not overflow the int range. We also take "abs(iv_scale)"

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2025, 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 id=with-flags
* @bug 8373502
* @summary Test where a VPointer variable was pinned at the pre-loop, but not available at the
* Auto_Vectorization_Check, and so it should not be used for the auto vectorization
* aliasing check, to avoid a bad (circular) graph.
* @run main/othervm
* -XX:CompileCommand=compileonly,*TestAliasingCheckVPointerVariablesNotAvailable::test
* -XX:-TieredCompilation
* -Xcomp
* ${test.main.class}
*/
/*
* @test id=vanilla
* @bug 8373502
* @run main ${test.main.class}
*/
package compiler.loopopts.superword;
public class TestAliasingCheckVPointerVariablesNotAvailable {
static int iFld;
public static void main(String[] strArr) {
test();
}
static void test() {
int iArr[] = new int[400];
boolean flag = false;
for (int i = 6; i < 50000; i++) { // Trigger OSR
try {
int x = 234 / iFld;
iFld = iArr[3];
} catch (ArithmeticException a_e) {
}
for (int j = i; j < 2; j++) {
if (flag) {
iArr[j] = 117;
} else {
iArr[1] = 34;
}
iArr[1] += i;
}
}
}
}