8293996: C2: fix and simplify IdealLoopTree::do_remove_empty_loop
Reviewed-by: roland, thartmann, chagedorn
This commit is contained in:
parent
14c6ac457d
commit
dd51f7e0b7
@ -3701,29 +3701,21 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
|
||||
}
|
||||
|
||||
// Replace the phi at loop head with the final value of the last
|
||||
// iteration. Then the CountedLoopEnd will collapse (backedge never
|
||||
// taken) and all loop-invariant uses of the exit values will be correct.
|
||||
Node *phi = cl->phi();
|
||||
Node *exact_limit = phase->exact_limit(this);
|
||||
if (exact_limit != cl->limit()) {
|
||||
// We also need to replace the original limit to collapse loop exit.
|
||||
Node* cmp = cl->loopexit()->cmp_node();
|
||||
assert(cl->limit() == cmp->in(2), "sanity");
|
||||
// Duplicate cmp node if it has other users
|
||||
if (cmp->outcnt() > 1) {
|
||||
cmp = cmp->clone();
|
||||
cmp = phase->_igvn.register_new_node_with_optimizer(cmp);
|
||||
BoolNode *bol = cl->loopexit()->in(CountedLoopEndNode::TestValue)->as_Bool();
|
||||
phase->_igvn.replace_input_of(bol, 1, cmp); // put bol on worklist
|
||||
}
|
||||
phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist
|
||||
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
|
||||
}
|
||||
// iteration (exact_limit - stride), to make sure the loop exit value
|
||||
// is correct, for any users after the loop.
|
||||
// Note: the final value after increment should not overflow since
|
||||
// counted loop has limit check predicate.
|
||||
Node *final = new SubINode(exact_limit, cl->stride());
|
||||
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
|
||||
phase->_igvn.replace_node(phi,final);
|
||||
Node* phi = cl->phi();
|
||||
Node* exact_limit = phase->exact_limit(this);
|
||||
Node* final_iv = new SubINode(exact_limit, cl->stride());
|
||||
phase->register_new_node(final_iv, cl->in(LoopNode::EntryControl));
|
||||
phase->_igvn.replace_node(phi, final_iv);
|
||||
|
||||
// Set loop-exit condition to false. Then the CountedLoopEnd will collapse,
|
||||
// because the back edge is never taken.
|
||||
Node* zero = phase->_igvn.intcon(0);
|
||||
phase->_igvn.replace_input_of(cl->loopexit(), CountedLoopEndNode::TestValue, zero);
|
||||
|
||||
phase->C->set_major_progress();
|
||||
return true;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* 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
|
||||
@ -23,7 +24,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8231988
|
||||
* @bug 8231988 8293996
|
||||
* @summary Unexpected test result caused by C2 IdealLoopTree::do_remove_empty_loop
|
||||
*
|
||||
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation
|
||||
@ -34,9 +35,11 @@ package compiler.loopopts;
|
||||
|
||||
public class TestRemoveEmptyLoop {
|
||||
|
||||
public void test() {
|
||||
public void test_cmp_helper() {
|
||||
int i = 34;
|
||||
// The empty loop that collapses
|
||||
for (; i > 0; i -= 11);
|
||||
// If uses same Cmp node as the loop condition
|
||||
if (i < 0) {
|
||||
// do nothing
|
||||
} else {
|
||||
@ -44,12 +47,38 @@ public class TestRemoveEmptyLoop {
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
|
||||
public void test_cmp() {
|
||||
// Loop is OSR compiled, and test_cmp_helper inlined
|
||||
for (int i = 0; i < 50000; i++) {
|
||||
_instance.test();
|
||||
test_cmp_helper();
|
||||
}
|
||||
System.out.println("Test passed.");
|
||||
}
|
||||
|
||||
void test_collapse_helper() {
|
||||
int o = 11;
|
||||
int e = 43542;
|
||||
for (int i = 524; i < 19325; i += 1) {
|
||||
// The empty loop that is supposed to collapse
|
||||
for (int j = 0; j < 32767; j++) {
|
||||
o++;
|
||||
}
|
||||
for (int k = 0; k < o; k++) {
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void test_collapse() {
|
||||
// Loop is OSR compiled, and test_collapse_helper inlined
|
||||
for (int i = 0; i < 50000; i++) {
|
||||
test_collapse_helper();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
|
||||
_instance.test_cmp();
|
||||
_instance.test_collapse();
|
||||
System.out.println("Test passed.");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user