Skip to content

Commit 369dedb

Browse files
committed
8293996: C2: fix and simplify IdealLoopTree::do_remove_empty_loop
Backport-of: dd51f7e0b75d3a16403608d89cd206ac0bedf882
1 parent 80eecc5 commit 369dedb

File tree

2 files changed

+48
-27
lines changed

2 files changed

+48
-27
lines changed

src/hotspot/share/opto/loopTransform.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,29 +3234,21 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
32343234
}
32353235

32363236
// Replace the phi at loop head with the final value of the last
3237-
// iteration. Then the CountedLoopEnd will collapse (backedge never
3238-
// taken) and all loop-invariant uses of the exit values will be correct.
3239-
Node *phi = cl->phi();
3240-
Node *exact_limit = phase->exact_limit(this);
3241-
if (exact_limit != cl->limit()) {
3242-
// We also need to replace the original limit to collapse loop exit.
3243-
Node* cmp = cl->loopexit()->cmp_node();
3244-
assert(cl->limit() == cmp->in(2), "sanity");
3245-
// Duplicate cmp node if it has other users
3246-
if (cmp->outcnt() > 1) {
3247-
cmp = cmp->clone();
3248-
cmp = phase->_igvn.register_new_node_with_optimizer(cmp);
3249-
BoolNode *bol = cl->loopexit()->in(CountedLoopEndNode::TestValue)->as_Bool();
3250-
phase->_igvn.replace_input_of(bol, 1, cmp); // put bol on worklist
3251-
}
3252-
phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist
3253-
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
3254-
}
3237+
// iteration (exact_limit - stride), to make sure the loop exit value
3238+
// is correct, for any users after the loop.
32553239
// Note: the final value after increment should not overflow since
32563240
// counted loop has limit check predicate.
3257-
Node *final = new SubINode(exact_limit, cl->stride());
3258-
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
3259-
phase->_igvn.replace_node(phi,final);
3241+
Node* phi = cl->phi();
3242+
Node* exact_limit = phase->exact_limit(this);
3243+
Node* final_iv = new SubINode(exact_limit, cl->stride());
3244+
phase->register_new_node(final_iv, cl->in(LoopNode::EntryControl));
3245+
phase->_igvn.replace_node(phi, final_iv);
3246+
3247+
// Set loop-exit condition to false. Then the CountedLoopEnd will collapse,
3248+
// because the back edge is never taken.
3249+
Node* zero = phase->_igvn.intcon(0);
3250+
phase->_igvn.replace_input_of(cl->loopexit(), CountedLoopEndNode::TestValue, zero);
3251+
32603252
phase->C->set_major_progress();
32613253
return true;
32623254
}

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

Lines changed: 35 additions & 6 deletions
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)