Skip to content
Permalink
Browse files

8238178: CTW: C1 compilation fails with assert(sux->loop_depth() != b…

…lock->loop_depth() || sux->loop_index() == block->loop_index() || loop_through_xhandler) failed: Loop index has to be same

Fix verification of C1 IR involving xhandlers in one-time executed loops on the non-exceptional path.

Reviewed-by: thartmann, neliasso
  • Loading branch information
Christian Hagedorn
Christian Hagedorn committed Feb 13, 2020
1 parent b0b8190 commit 8bdb972192a9b26c6a5d1cc6cd160559bf9c1050
@@ -30,6 +30,9 @@
#include "c1/c1_ValueMap.hpp"
#include "ci/ciMethodData.hpp"
#include "runtime/deoptimization.hpp"
#ifdef ASSERT
#include "utilities/bitMap.inline.hpp"
#endif

// Macros for the Trace and the Assertion flag
#ifdef ASSERT
@@ -1050,6 +1053,7 @@ void RangeCheckEliminator::dump_condition_stack(BlockBegin *block) {
}
#endif

#ifdef ASSERT
// Verification or the IR
RangeCheckEliminator::Verification::Verification(IR *ir) : _used(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), false) {
this->_ir = ir;
@@ -1099,21 +1103,16 @@ void RangeCheckEliminator::Verification::block_do(BlockBegin *block) {
BlockList *all_blocks = _ir->linear_scan_order();
assert(block->number_of_preds() >= 1, "Block must have at least one predecessor");
assert(!block->is_set(BlockBegin::exception_entry_flag), "Loop header must not be exception handler!");
// Sometimes, the backbranch comes from an exception handler. In
// this case, loop indexes/loop depths may not appear correct.
bool loop_through_xhandler = false;
for (int i = 0; i < block->number_of_exception_handlers(); i++) {
BlockBegin *xhandler = block->exception_handler_at(i);
for (int j = 0; j < block->number_of_preds(); j++) {
if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) {
loop_through_xhandler = true;
}
}
}

bool loop_through_xhandler = false;
for (int i=0; i<block->number_of_sux(); i++) {
BlockBegin *sux = block->sux_at(i);
assert(sux->loop_depth() != block->loop_depth() || sux->loop_index() == block->loop_index() || loop_through_xhandler, "Loop index has to be same");
if (!loop_through_xhandler) {
if (sux->loop_depth() == block->loop_depth() && sux->loop_index() != block->loop_index()) {
loop_through_xhandler = is_backbranch_from_xhandler(block);
assert(loop_through_xhandler, "Loop indices have to be the same if same depths but no backbranch from xhandler");
}
}
assert(sux->loop_depth() == block->loop_depth() || sux->loop_index() != block->loop_index(), "Loop index has to be different");
}

@@ -1132,6 +1131,54 @@ void RangeCheckEliminator::Verification::block_do(BlockBegin *block) {
}
}

// Called when a successor of a block has the same loop depth but a different loop index. This can happen if a backbranch comes from
// an exception handler of a loop head block, for example, when a loop is only executed once on the non-exceptional path but is
// repeated in case of an exception. In this case, the edge block->sux is not critical and was not split before.
// Check if there is such a backbranch from an xhandler of 'block'.
bool RangeCheckEliminator::Verification::is_backbranch_from_xhandler(BlockBegin* block) {
for (int i = 0; i < block->number_of_exception_handlers(); i++) {
BlockBegin *xhandler = block->exception_handler_at(i);
for (int j = 0; j < block->number_of_preds(); j++) {
if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) {
return true;
}
}
}

// In case of nested xhandlers, we need to walk through the loop (and all blocks belonging to exception handlers)
// to find an xhandler of 'block'.
if (block->number_of_exception_handlers() > 0) {
for (int i = 0; i < block->number_of_preds(); i++) {
BlockBegin* pred = block->pred_at(i);
if (pred->loop_index() == block->loop_index()) {
// Only check blocks that belong to the loop
// Do a BFS to find an xhandler block of 'block' starting from 'pred'
ResourceMark rm;
ResourceBitMap visited(BlockBegin::number_of_blocks());
BlockBeginList list;
list.push(pred);
while (!list.is_empty()) {
BlockBegin* next = list.pop();
if (!visited.at(next->block_id())) {
visited.set_bit(next->block_id());
for (int j = 0; j < block->number_of_exception_handlers(); j++) {
if (next == block->exception_handler_at(j)) {
return true;
}
}
for (int j = 0; j < next->number_of_preds(); j++) {
if (next->pred_at(j) != block) {
list.push(next->pred_at(j));
}
}
}
}
}
}
}
return false;
}

// Loop header must dominate all loop blocks
bool RangeCheckEliminator::Verification::dominates(BlockBegin *dominator, BlockBegin *block) {
BlockBegin *cur = block->dominator();
@@ -1195,6 +1242,7 @@ bool RangeCheckEliminator::Verification::can_reach(BlockBegin *start, BlockBegin

return false;
}
#endif // ASSERT

// Bound
RangeCheckEliminator::Bound::~Bound() {
@@ -43,6 +43,7 @@ class RangeCheckEliminator {
typedef GrowableArray<BlockBegin*> BlockBeginList;
typedef GrowableArray<int> IntegerStack;

#ifdef ASSERT
class Verification : public BlockClosure {
// RangeCheckEliminator::Verification should never get instatiated on the heap.
private:
@@ -51,6 +52,10 @@ class RangeCheckEliminator {
void operator delete(void* p) { ShouldNotReachHere(); }
void operator delete[](void* p) { ShouldNotReachHere(); }

bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL);
bool dominates(BlockBegin *dominator, BlockBegin *block);
bool is_backbranch_from_xhandler(BlockBegin* block);

IR *_ir;
boolArray _used;
BlockBeginList _current;
@@ -59,9 +64,8 @@ class RangeCheckEliminator {
public:
Verification(IR *ir);
virtual void block_do(BlockBegin *block);
bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL);
bool dominates(BlockBegin *dominator, BlockBegin *block);
};
#endif

public:
// Bounds for an instruction in the form x + c which c integer

0 comments on commit 8bdb972

Please sign in to comment.