From 989c35d9b94fcac11dd4f6bf7df9b236765e37e9 Mon Sep 17 00:00:00 2001 From: Hanbum Park Date: Wed, 30 Jul 2025 00:16:51 +0900 Subject: [PATCH] [BreakCritEdges] Check whether IndirectBr is the terminator of the block Critical edges with an IndirectBr terminator cannot be split. We have already handled it with Assertion, but change it to checking whether block has IndirectBr terminator. Fixes : #150229 --- .../Transforms/Utils/BreakCriticalEdges.cpp | 11 +++++------ llvm/test/Transforms/GVN/cond_br.ll | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp index ddd203f3acf71..42b1fdf17f389 100644 --- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -111,15 +111,14 @@ BasicBlock * llvm::SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options, const Twine &BBName) { - assert(!isa(TI) && - "Cannot split critical edge from IndirectBrInst"); - BasicBlock *TIBB = TI->getParent(); BasicBlock *DestBB = TI->getSuccessor(SuccNum); - // Splitting the critical edge to a pad block is non-trivial. Don't do - // it in this generic function. - if (DestBB->isEHPad()) return nullptr; + // Splitting the critical edge to a pad block is non-trivial. + // And we cannot split block with IndirectBr as a terminator. + // Don't do it in this generic function. + if (DestBB->isEHPad() || isa(TI)) + return nullptr; if (Options.IgnoreUnreachableDests && isa(DestBB->getFirstNonPHIOrDbgOrLifetime())) diff --git a/llvm/test/Transforms/GVN/cond_br.ll b/llvm/test/Transforms/GVN/cond_br.ll index 19166d17a8320..fb84b626c7455 100644 --- a/llvm/test/Transforms/GVN/cond_br.ll +++ b/llvm/test/Transforms/GVN/cond_br.ll @@ -53,3 +53,22 @@ if.end: ; preds = %if.else, %if.then } declare void @bar(i32) + +define void @indirectbr_could_not_split() { +; CHECK-LABEL: define void @indirectbr_could_not_split() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: br i1 false, label %[[IBR:.*]], label %[[EXIT:.*]] +; CHECK: [[IBR]]: +; CHECK-NEXT: indirectbr ptr null, [label %[[EXIT]], label %exit] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +entry: + br i1 false, label %ibr, label %exit + +ibr: + indirectbr ptr null, [label %exit, label %exit] + +exit: + ret void +}