Skip to content

Commit

Permalink
[LoopSimplifyCFG] Fix inconsistency in live blocks markup
Browse files Browse the repository at this point in the history
When we choose whether or not we should mark block as dead, we have an
inconsistent logic in markup of live blocks.
- We take candidate IF its terminator branches on constant AND it is immediately
  in current loop;
- We mark successor live IF its terminator doesn't branch by constant OR it branches
  by constant and the successor is its always taken block.

What we are missing here is that when the terminator branches on a constant but is
not taken as a candidate because is it not immediately in the current loop, we will
mark only one (always taken) successor as live. Therefore, we do NOT do the actual
folding but may NOT mark one of the successors as live. So the result of markup is
wrong in this case, and we may then hit various asserts.

Thanks Jordan Rupprech for reporting this!

Differential Revision: https://reviews.llvm.org/D57095
Reviewed By: rupprecht

llvm-svn: 352024
  • Loading branch information
Max Kazantsev committed Jan 24, 2019
1 parent 11d3314 commit 56515a2
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
Expand Up @@ -207,12 +207,13 @@ class ConstantTerminatorFoldingImpl {
// folding. Only handle blocks from current loop: branches in child loops
// are skipped because if they can be folded, they should be folded during
// the processing of child loops.
if (TheOnlySucc && LI.getLoopFor(BB) == &L)
bool TakeFoldCandidate = TheOnlySucc && LI.getLoopFor(BB) == &L;
if (TakeFoldCandidate)
FoldCandidates.push_back(BB);

// Handle successors.
for (BasicBlock *Succ : successors(BB))
if (!TheOnlySucc || TheOnlySucc == Succ) {
if (!TakeFoldCandidate || TheOnlySucc == Succ) {
if (L.contains(Succ))
LiveLoopBlocks.insert(Succ);
else
Expand Down
24 changes: 22 additions & 2 deletions llvm/test/Transforms/LoopSimplifyCFG/live_block_marking.ll
@@ -1,4 +1,4 @@
; XFAIL: *
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; REQUIRES: asserts
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -indvars -loop-simplifycfg -debug-only=loop-simplifycfg -verify-loop-info -verify-dom-info -verify-loop-lcssa 2>&1 < %s | FileCheck %s
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require<domtree>,loop(indvars,simplify-cfg)' -debug-only=loop-simplifycfg -verify-loop-info -verify-dom-info -verify-loop-lcssa 2>&1 < %s | FileCheck %s
Expand All @@ -7,8 +7,28 @@
; This test demonstrates a bug in live blocks markup that is only catchable in
; inter-pass interaction.
define void @test(i1 %c) {

; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[OUTER:%.*]]
; CHECK: outer:
; CHECK-NEXT: br i1 [[C:%.*]], label [[TO_FOLD:%.*]], label [[LATCH:%.*]]
; CHECK: to_fold:
; CHECK-NEXT: br i1 [[C]], label [[LATCH]], label [[INNER_PREHEADER:%.*]]
; CHECK: inner.preheader:
; CHECK-NEXT: br label [[INNER:%.*]]
; CHECK: inner:
; CHECK-NEXT: br i1 false, label [[INNER_LATCH:%.*]], label [[UNDEAD:%.*]]
; CHECK: inner_latch:
; CHECK-NEXT: br i1 true, label [[INNER]], label [[LATCH_LOOPEXIT:%.*]]
; CHECK: undead:
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch.loopexit:
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: br i1 true, label [[OUTER]], label [[DEAD_EXIT:%.*]]
; CHECK: dead_exit:
; CHECK-NEXT: ret void
;

entry:
br label %outer
Expand Down

0 comments on commit 56515a2

Please sign in to comment.