From: Max Kazantsev Date: Thu, 24 Jan 2019 05:20:29 +0000 (+0000) Subject: [LoopSimplifyCFG] Fix inconsistency in live blocks markup X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a481519880851ccb5a7f17e688cd596abf843f9;p=llvm [LoopSimplifyCFG] Fix inconsistency in live blocks markup 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@352024 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp index b0fa4f7e0ef..669faf5aa18 100644 --- a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -207,12 +207,13 @@ private: // 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 diff --git a/test/Transforms/LoopSimplifyCFG/live_block_marking.ll b/test/Transforms/LoopSimplifyCFG/live_block_marking.ll index a4c0bac4121..f15f626d5d3 100644 --- a/test/Transforms/LoopSimplifyCFG/live_block_marking.ll +++ b/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,loop(indvars,simplify-cfg)' -debug-only=loop-simplifycfg -verify-loop-info -verify-dom-info -verify-loop-lcssa 2>&1 < %s | FileCheck %s @@ -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