Skip to content

Commit dd51f7e

Browse files
committed
8293996: C2: fix and simplify IdealLoopTree::do_remove_empty_loop
Reviewed-by: roland, thartmann, chagedorn
1 parent 14c6ac4 commit dd51f7e

File tree

2 files changed

+48
-27
lines changed

2 files changed

+48
-27
lines changed

src/hotspot/share/opto/loopTransform.cpp

+13-21
Original file line numberDiff line numberDiff line change
@@ -3701,29 +3701,21 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
37013701
}
37023702

37033703
// Replace the phi at loop head with the final value of the last
3704-
// iteration. Then the CountedLoopEnd will collapse (backedge never
3705-
// taken) and all loop-invariant uses of the exit values will be correct.
3706-
Node *phi = cl->phi();
3707-
Node *exact_limit = phase->exact_limit(this);
3708-
if (exact_limit != cl->limit()) {
3709-
// We also need to replace the original limit to collapse loop exit.
3710-
Node* cmp = cl->loopexit()->cmp_node();
3711-
assert(cl->limit() == cmp->in(2), "sanity");
3712-
// Duplicate cmp node if it has other users
3713-
if (cmp->outcnt() > 1) {
3714-
cmp = cmp->clone();
3715-
cmp = phase->_igvn.register_new_node_with_optimizer(cmp);
3716-
BoolNode *bol = cl->loopexit()->in(CountedLoopEndNode::TestValue)->as_Bool();
3717-
phase->_igvn.replace_input_of(bol, 1, cmp); // put bol on worklist
3718-
}
3719-
phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist
3720-
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
3721-
}
3704+
// iteration (exact_limit - stride), to make sure the loop exit value
3705+
// is correct, for any users after the loop.
37223706
// Note: the final value after increment should not overflow since
37233707
// counted loop has limit check predicate.
3724-
Node *final = new SubINode(exact_limit, cl->stride());
3725-
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
3726-
phase->_igvn.replace_node(phi,final);
3708+
Node* phi = cl->phi();
3709+
Node* exact_limit = phase->exact_limit(this);
3710+
Node* final_iv = new SubINode(exact_limit, cl->stride());
3711+
phase->register_new_node(final_iv, cl->in(LoopNode::EntryControl));
3712+
phase->_igvn.replace_node(phi, final_iv);
3713+
3714+
// Set loop-exit condition to false. Then the CountedLoopEnd will collapse,
3715+
// because the back edge is never taken.
3716+
Node* zero = phase->_igvn.intcon(0);
3717+
phase->_igvn.replace_input_of(cl->loopexit(), CountedLoopEndNode::TestValue, zero);
3718+
37273719
phase->C->set_major_progress();
37283720
return true;
37293721
}

test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyLoop.java

+35-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2019, Huawei Technologies Co., Ltd. All rights reserved.
3+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +24,7 @@
2324

2425
/**
2526
* @test
26-
* @bug 8231988
27+
* @bug 8231988 8293996
2728
* @summary Unexpected test result caused by C2 IdealLoopTree::do_remove_empty_loop
2829
*
2930
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation
@@ -34,22 +35,50 @@
3435

3536
public class TestRemoveEmptyLoop {
3637

37-
public void test() {
38+
public void test_cmp_helper() {
3839
int i = 34;
40+
// The empty loop that collapses
3941
for (; i > 0; i -= 11);
42+
// If uses same Cmp node as the loop condition
4043
if (i < 0) {
4144
// do nothing
4245
} else {
4346
throw new RuntimeException("Test failed.");
4447
}
4548
}
4649

47-
public static void main(String[] args) {
48-
TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
50+
public void test_cmp() {
51+
// Loop is OSR compiled, and test_cmp_helper inlined
4952
for (int i = 0; i < 50000; i++) {
50-
_instance.test();
53+
test_cmp_helper();
54+
}
55+
}
56+
57+
void test_collapse_helper() {
58+
int o = 11;
59+
int e = 43542;
60+
for (int i = 524; i < 19325; i += 1) {
61+
// The empty loop that is supposed to collapse
62+
for (int j = 0; j < 32767; j++) {
63+
o++;
64+
}
65+
for (int k = 0; k < o; k++) {
66+
e++;
67+
}
68+
}
69+
}
70+
71+
public void test_collapse() {
72+
// Loop is OSR compiled, and test_collapse_helper inlined
73+
for (int i = 0; i < 50000; i++) {
74+
test_collapse_helper();
5175
}
52-
System.out.println("Test passed.");
5376
}
5477

78+
public static void main(String[] args) {
79+
TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
80+
_instance.test_cmp();
81+
_instance.test_collapse();
82+
System.out.println("Test passed.");
83+
}
5584
}

0 commit comments

Comments
 (0)