Skip to content
Permalink
Browse files

8235452: Strip mined loop verification fails with assert(is_OuterStri…

…pMinedLoop()) failed: invalid node class

Do not try to verify strip mining if the strip mined loop is malformed.

Reviewed-by: roland, vlivanov
  • Loading branch information
Tobias Hartmann
Tobias Hartmann committed Dec 11, 2019
1 parent f6d5046 commit 642d2ddcbc438a6803727ed2a8efa3e956fa0b36
@@ -1388,9 +1388,8 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
// an early loop exit. Try them with profile data.
while (if_proj_list.size() > 0) {
Node* proj = if_proj_list.pop();
float f = pf.to(proj);
if (proj->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) &&
f * loop_trip_cnt >= 1) {
pf.to(proj) * loop_trip_cnt >= 1) {
hoisted = loop_predication_impl_helper(loop, proj->as_Proj(), profile_predicate_proj, cl, zero, invar, Deoptimization::Reason_profile_predicate) | hoisted;
}
}
@@ -944,8 +944,11 @@ Node *LoopNode::Ideal(PhaseGVN *phase, bool can_reshape) {
return RegionNode::Ideal(phase, can_reshape);
}

void LoopNode::verify_strip_mined(int expect_skeleton) const {
#ifdef ASSERT
void LoopNode::verify_strip_mined(int expect_skeleton) const {
if (!is_valid_counted_loop()) {
return; // Skip malformed counted loop
}
const OuterStripMinedLoopNode* outer = NULL;
const CountedLoopNode* inner = NULL;
if (is_strip_mined()) {
@@ -955,6 +958,7 @@ void LoopNode::verify_strip_mined(int expect_skeleton) const {
} else if (is_OuterStripMinedLoop()) {
outer = this->as_OuterStripMinedLoop();
inner = outer->unique_ctrl_out()->as_CountedLoop();
assert(inner->is_valid_counted_loop(), "OuterStripMinedLoop should have been removed");
assert(!is_strip_mined(), "outer loop shouldn't be marked strip mined");
}
if (inner != NULL || outer != NULL) {
@@ -1024,8 +1028,8 @@ void LoopNode::verify_strip_mined(int expect_skeleton) const {
assert(sfpt->outcnt() == 1, "no data node");
assert(outer_tail->outcnt() == 1 || !has_skeleton, "no data node");
}
#endif
}
#endif

//=============================================================================
//------------------------------Ideal------------------------------------------
@@ -152,7 +152,7 @@ class LoopNode : public RegionNode {
virtual void dump_spec(outputStream *st) const;
#endif

void verify_strip_mined(int expect_skeleton) const;
void verify_strip_mined(int expect_skeleton) const NOT_DEBUG_RETURN;
virtual LoopNode* skip_strip_mined(int expect_skeleton = 1) { return this; }
virtual IfTrueNode* outer_loop_tail() const { ShouldNotReachHere(); return NULL; }
virtual OuterStripMinedLoopEndNode* outer_loop_end() const { ShouldNotReachHere(); return NULL; }
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2019, 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 8235452
* @library /test/lib /
* @summary Test loop strip mining verification with dying outer loop.
* @run main/othervm -Xbatch -XX:-TieredCompilation
* compiler.loopstripmining.TestDeadOuterStripMinedLoop
*/

package compiler.loopstripmining;

import jdk.test.lib.Asserts;

public class TestDeadOuterStripMinedLoop {

public static int test(boolean b) {
int res = 5000;
for (int i = 0; i < 42; i++) {
if (!b) {
break;
}
// Strip mined loop
while (--res > 0) {
if (res < 1) {
throw new RuntimeException("Should not reach here!");
}
}

/*
After parsing:
Loop:
res--;
if (res <= 0) {
goto End;
}
if (res < 1) { <- Treated as loop exit check (res <= 0)
UncommonTrap();
}
goto Loop;
End:
Loop opts convert this into:
// Outer strip mined loop
do {
// Strip mined loop
do {
res--;
if (res <= 0) {
goto End;
}
} while (res > 0); <- Always false due to above res <= 0 check
Safepoint()
} while (false);
UncommonTrap();
End:
The safepoint path dies, because the exit condition of the strip mined loop is always false:
// Strip mined loop
do {
res--;
if (res <= 0) {
goto End;
}
} while (true);
End:
*/
}
return res;
}

public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Asserts.assertEQ(test(true), -41);
}
Asserts.assertEQ(test(false), 5000);
}
}

0 comments on commit 642d2dd

Please sign in to comment.
You can’t perform that action at this time.