8297264: C2: Cast node is not processed again in CCP and keeps a wrong too narrow type which is later replaced by top

Reviewed-by: thartmann, rcastanedalo, kvn
This commit is contained in:
Christian Hagedorn 2022-12-05 07:09:04 +00:00
parent b49fd920b6
commit a57392390b
3 changed files with 81 additions and 0 deletions

View File

@ -1847,6 +1847,7 @@ void PhaseCCP::push_more_uses(Unique_Node_List& worklist, Node* parent, const No
push_counted_loop_phi(worklist, parent, use);
push_loadp(worklist, use);
push_and(worklist, parent, use);
push_cast_ii(worklist, parent, use);
}
@ -1950,6 +1951,22 @@ void PhaseCCP::push_and(Unique_Node_List& worklist, const Node* parent, const No
}
}
// CastII::Value() optimizes CmpI/If patterns if the right input of the CmpI has a constant type. If the CastII input is
// the same node as the left input into the CmpI node, the type of the CastII node can be improved accordingly. Add the
// CastII node back to the worklist to re-apply Value() to either not miss this optimization or to undo it because it
// cannot be applied anymore. We could have optimized the type of the CastII before but now the type of the right input
// of the CmpI (i.e. 'parent') is no longer constant. The type of the CastII must be widened in this case.
void PhaseCCP::push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const {
if (use->Opcode() == Op_CmpI && use->in(2) == parent) {
Node* other_cmp_input = use->in(1);
for (DUIterator_Fast imax, i = other_cmp_input->fast_outs(imax); i < imax; i++) {
Node* cast_ii = other_cmp_input->fast_out(i);
if (cast_ii->is_CastII()) {
push_if_not_bottom_type(worklist, cast_ii);
}
}
}
}
//------------------------------do_transform-----------------------------------
// Top level driver for the recursive transformer

View File

@ -595,6 +595,7 @@ class PhaseCCP : public PhaseIterGVN {
void push_loadp(Unique_Node_List& worklist, const Node* use) const;
static void push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* barrier_set, const Node* use);
void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const;
void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const;
public:
PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2022, 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 8297264
* @summary Test that CastII nodes are added to the CCP worklist if they could have been
* optimized due to a CmpI/If pattern.
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.ccp.TestCastIIWrongTypeCCP::*
* compiler.ccp.TestCastIIWrongTypeCCP
*/
package compiler.ccp;
public class TestCastIIWrongTypeCCP {
static int x;
public static void main(String[] args) {
test();
}
static void test() {
int iArr[] = new int[400];
int i = 0;
do {
for (int i5 = 1; i5 < 4; i5++) {
for (int i9 = 2; i9 > i5; i9 -= 3) {
if (x != 0) {
A.unloaded(); // unloaded UCT
}
x = 1;
iArr[5] = 1;
}
}
i++;
} while (i < 10000);
}
}
class A {
public static void unloaded() {
}
}