Commit 5366de73 authored by Arthur Eubanks's avatar Arthur Eubanks
Browse files

[SimpleLoopUnswitch] Don't non-trivially unswitch loops with catchswitch exits

SplitBlock() can't handle catchswitch.

Fixes PR50973.

Reviewed By: aheejin

Differential Revision: https://reviews.llvm.org/D105672
parent 0e49c54a
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -2775,14 +2775,15 @@ static bool unswitchBestCondition(
  SmallVector<BasicBlock *, 4> ExitBlocks;
  L.getUniqueExitBlocks(ExitBlocks);

  // We cannot unswitch if exit blocks contain a cleanuppad instruction as we
  // don't know how to split those exit blocks.
  // We cannot unswitch if exit blocks contain a cleanuppad/catchswitch
  // instruction as we don't know how to split those exit blocks.
  // FIXME: We should teach SplitBlock to handle this and remove this
  // restriction.
  for (auto *ExitBB : ExitBlocks) {
    if (isa<CleanupPadInst>(ExitBB->getFirstNonPHI())) {
      LLVM_DEBUG(
          dbgs() << "Cannot unswitch because of cleanuppad in exit block\n");
    auto *I = ExitBB->getFirstNonPHI();
    if (isa<CleanupPadInst>(I) || isa<CatchSwitchInst>(I)) {
      LLVM_DEBUG(dbgs() << "Cannot unswitch because of cleanuppad/catchswitch "
                           "in exit block\n");
      return false;
    }
  }
+3 −1
Original line number Diff line number Diff line
@@ -766,8 +766,10 @@ static BasicBlock *SplitBlockImpl(BasicBlock *Old, Instruction *SplitPt,
                            BBName);
  }
  BasicBlock::iterator SplitIt = SplitPt->getIterator();
  while (isa<PHINode>(SplitIt) || SplitIt->isEHPad())
  while (isa<PHINode>(SplitIt) || SplitIt->isEHPad()) {
    ++SplitIt;
    assert(SplitIt != SplitPt->getParent()->end());
  }
  std::string Name = BBName.str();
  BasicBlock *New = Old->splitBasicBlock(
      SplitIt, Name.empty() ? Old->getName() + ".split" : Name);
+33 −0
Original line number Diff line number Diff line
; RUN: opt -passes=simple-loop-unswitch -enable-nontrivial-unswitch < %s -S | FileCheck %s

; CHECK: if.end{{.*}}:
; CHECK-NOT: if.end{{.*}}:
declare i32 @__gxx_wasm_personality_v0(...)

declare void @foo()

define void @test(i1 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
entry:
  br label %while.body

while.body:                                       ; preds = %cleanup, %entry
  br i1 %arg, label %if.end, label %if.then

if.then:                                          ; preds = %while.body
  br label %if.end

if.end:                                           ; preds = %if.then, %while.body
  invoke void @foo()
          to label %cleanup unwind label %catch.dispatch

catch.dispatch:                                   ; preds = %invoke.cont, %if.end
  %0 = catchswitch within none [label %catch] unwind to caller

catch:                                            ; preds = %catch.dispatch
  %1 = catchpad within %0 [i8* null]
  unreachable

cleanup:                                          ; preds = %invoke.cont
  br label %while.body
}