[llvm] [SEH] Ensure unreachable blocks are placed in EHScopeMembership (PR #175550)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 12 06:36:08 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: David Green (davemgreen)

<details>
<summary>Changes</summary>

The attached function has an unreachable block bb.2 leading to an unreachable infinite loop bb.3. As BlockFolding removes the unreachable bb.2, bb.3 is left only referencing itself. This block is then not marked as unreachable and so left out of EHScopeMembership. This patch makes sure that blocks not otherwise collected are added to EHScopeMembership in the same way as unreachable blocks.

This also adds some basic parsing for ehscope-entry, needed for the mir test.

---
Full diff: https://github.com/llvm/llvm-project/pull/175550.diff


6 Files Affected:

- (modified) llvm/lib/CodeGen/Analysis.cpp (+8) 
- (modified) llvm/lib/CodeGen/MIRParser/MILexer.cpp (+1) 
- (modified) llvm/lib/CodeGen/MIRParser/MILexer.h (+1) 
- (modified) llvm/lib/CodeGen/MIRParser/MIParser.cpp (+6) 
- (modified) llvm/lib/CodeGen/MachineBasicBlock.cpp (+5) 
- (added) llvm/test/CodeGen/AArch64/seh-unreachable-loop.mir (+154) 


``````````diff
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 94ab6c6514869..9ece9f0c187a2 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -814,5 +814,13 @@ llvm::getEHScopeMembership(const MachineFunction &MF) {
        CatchRetSuccessors)
     collectEHScopeMembers(EHScopeMembership, CatchRetPair.second,
                           CatchRetPair.first);
+
+  // Add any remaining blocks in the function to the unreachable set, which
+  // might not otherwise have been identified as unreachable (such as infinite
+  // loops).
+  for (const MachineBasicBlock &MBB : MF)
+    if (!EHScopeMembership.count(&MBB))
+      collectEHScopeMembers(EHScopeMembership, EntryBBNumber, &MBB);
+
   return EHScopeMembership;
 }
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index aa79aad781ee8..f9852c6c889b8 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -271,6 +271,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("landing-pad", MIToken::kw_landing_pad)
       .Case("inlineasm-br-indirect-target",
             MIToken::kw_inlineasm_br_indirect_target)
+      .Case("ehscope-entry", MIToken::kw_ehscope_entry)
       .Case("ehfunclet-entry", MIToken::kw_ehfunclet_entry)
       .Case("liveins", MIToken::kw_liveins)
       .Case("successors", MIToken::kw_successors)
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index ff4c0c6f6d59d..a9dc9af6858da 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -126,6 +126,7 @@ struct MIToken {
     kw_liveout,
     kw_landing_pad,
     kw_inlineasm_br_indirect_target,
+    kw_ehscope_entry,
     kw_ehfunclet_entry,
     kw_liveins,
     kw_successors,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 51862b501cc47..baac77fbd2dc0 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -719,6 +719,7 @@ bool MIParser::parseBasicBlockDefinition(
   bool IsLandingPad = false;
   bool IsInlineAsmBrIndirectTarget = false;
   bool IsEHFuncletEntry = false;
+  bool IsEHScopeEntry = false;
   std::optional<MBBSectionID> SectionID;
   uint64_t Alignment = 0;
   std::optional<UniqueBBID> BBID;
@@ -748,6 +749,10 @@ bool MIParser::parseBasicBlockDefinition(
         IsEHFuncletEntry = true;
         lex();
         break;
+      case MIToken::kw_ehscope_entry:
+        IsEHScopeEntry = true;
+        lex();
+        break;
       case MIToken::kw_align:
         if (parseAlignment(Alignment))
           return true;
@@ -804,6 +809,7 @@ bool MIParser::parseBasicBlockDefinition(
   MBB->setIsEHPad(IsLandingPad);
   MBB->setIsInlineAsmBrIndirectTarget(IsInlineAsmBrIndirectTarget);
   MBB->setIsEHFuncletEntry(IsEHFuncletEntry);
+  MBB->setIsEHScopeEntry(IsEHScopeEntry);
   if (SectionID) {
     MBB->setSectionID(*SectionID);
     MF.setBBSectionsType(BasicBlockSection::List);
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index ba0f9c3f64ada..f5634567d8988 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -551,6 +551,11 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
       os << "ehfunclet-entry";
       hasAttributes = true;
     }
+    if (isEHScopeEntry()) {
+      os << (hasAttributes ? ", " : " (");
+      os << "ehscope-entry";
+      hasAttributes = true;
+    }
     if (getAlignment() != Align(1)) {
       os << (hasAttributes ? ", " : " (");
       os << "align " << getAlignment().value();
diff --git a/llvm/test/CodeGen/AArch64/seh-unreachable-loop.mir b/llvm/test/CodeGen/AArch64/seh-unreachable-loop.mir
new file mode 100644
index 0000000000000..f55039b6bf52a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/seh-unreachable-loop.mir
@@ -0,0 +1,154 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -o - %s -mtriple=aarch64-pc-windows-msvc19.33.0 -run-pass=branch-folder | FileCheck %s
+
+# Check that the dead blocks in bb.2 and bb.3 are correctly handled by BranchFolders EHScopeMembership.
+
+--- |
+  declare i32 @__CxxFrameHandler3(...)
+
+  declare ptr @"??2 at YAPEAX_K@Z"(i64)
+
+  define ptr @test(ptr writeonly captures(none) %0, ptr captures(none) %1) personality ptr @__CxxFrameHandler3 {
+    unreachable
+  }
+...
+---
+name:            test
+tracksRegLiveness: true
+hasEHContTarget: false
+hasEHScopes:     true
+hasEHFunclets:   true
+body:             |
+  ; CHECK-LABEL: name: test
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x7ffff800), %bb.2(0x00000800)
+  ; CHECK-NEXT:   liveins: $x0, $x1, $x20, $x19, $lr
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -6 :: (store (s64)), (store (s64))
+  ; CHECK-NEXT:   frame-setup SEH_SaveRegP_X 19, 20, -48
+  ; CHECK-NEXT:   frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64)), (store (s64))
+  ; CHECK-NEXT:   frame-setup SEH_SaveFPLR 16
+  ; CHECK-NEXT:   $fp = frame-setup ADDXri $sp, 16, 0
+  ; CHECK-NEXT:   frame-setup SEH_AddFP 16
+  ; CHECK-NEXT:   frame-setup SEH_PrologEnd
+  ; CHECK-NEXT:   $x2 = MOVi64imm -2
+  ; CHECK-NEXT:   STURXi killed $x2, $fp, 16
+  ; CHECK-NEXT:   renamable $x20 = COPY $x1
+  ; CHECK-NEXT:   renamable $x19 = COPY $x0
+  ; CHECK-NEXT:   EH_LABEL <mcsymbol .Ltmp0>
+  ; CHECK-NEXT:   $x0 = COPY $xzr
+  ; CHECK-NEXT:   BL @"??2 at YAPEAX_K@Z", csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp, implicit-def $x0
+  ; CHECK-NEXT:   EH_LABEL <mcsymbol .Ltmp0>
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   liveins: $x0, $x19, $x20
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   STRXui $xzr, renamable $x20, 1 :: (store (s64), align 1)
+  ; CHECK-NEXT:   STRXui $xzr, renamable $x20, 0 :: (store (s64), align 1)
+  ; CHECK-NEXT:   STRXui $xzr, killed renamable $x20, 2 :: (store (s64), align 1)
+  ; CHECK-NEXT:   STRXui killed renamable $x0, renamable $x19, 0 :: (store (s64))
+  ; CHECK-NEXT:   $x0 = COPY $xzr
+  ; CHECK-NEXT:   frame-destroy SEH_EpilogStart
+  ; CHECK-NEXT:   $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64)), (load (s64))
+  ; CHECK-NEXT:   frame-destroy SEH_SaveFPLR 16
+  ; CHECK-NEXT:   early-clobber $sp, $x19, $x20 = frame-destroy LDPXpost $sp, 6 :: (load (s64)), (load (s64))
+  ; CHECK-NEXT:   frame-destroy SEH_SaveRegP_X 19, 20, -48
+  ; CHECK-NEXT:   frame-destroy SEH_EpilogEnd
+  ; CHECK-NEXT:   RET_ReallyLR implicit $x0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2 (landing-pad, ehfunclet-entry, ehscope-entry):
+  ; CHECK-NEXT:   liveins: $x20, $x19, $lr
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -4 :: (store (s64)), (store (s64))
+  ; CHECK-NEXT:   frame-setup SEH_SaveRegP_X 19, 20, -32
+  ; CHECK-NEXT:   frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64)), (store (s64))
+  ; CHECK-NEXT:   frame-setup SEH_SaveFPLR 16
+  ; CHECK-NEXT:   frame-setup SEH_PrologEnd
+  ; CHECK-NEXT:   renamable $x8 = COPY $xzr
+  ; CHECK-NEXT:   STRWui $wzr, killed renamable $x8, 0 :: (volatile store (s32) into `ptr null`, align 4294967296)
+  ; CHECK-NEXT:   frame-destroy SEH_EpilogStart
+  ; CHECK-NEXT:   $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64)), (load (s64))
+  ; CHECK-NEXT:   frame-destroy SEH_SaveFPLR 16
+  ; CHECK-NEXT:   early-clobber $sp, $x19, $x20 = frame-destroy LDPXpost $sp, 4 :: (load (s64)), (load (s64))
+  ; CHECK-NEXT:   frame-destroy SEH_SaveRegP_X 19, 20, -32
+  ; CHECK-NEXT:   frame-destroy SEH_EpilogEnd
+  ; CHECK-NEXT:   CLEANUPRET
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $x8
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   early-clobber renamable $x8 = STRXpost $xzr, killed renamable $x8, -8 :: (store (s64))
+  ; CHECK-NEXT:   B %bb.3
+  bb.0:
+    successors: %bb.1(0x7ffff800), %bb.5(0x00000800)
+    liveins: $x0, $x1, $x20, $x19, $lr
+
+    early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -6 :: (store (s64)), (store (s64))
+    frame-setup SEH_SaveRegP_X 19, 20, -48
+    frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64)), (store (s64))
+    frame-setup SEH_SaveFPLR 16
+    $fp = frame-setup ADDXri $sp, 16, 0
+    frame-setup SEH_AddFP 16
+    frame-setup SEH_PrologEnd
+    $x2 = MOVi64imm -2
+    STURXi killed $x2, $fp, 16
+    renamable $x20 = COPY $x1
+    renamable $x19 = COPY $x0
+    EH_LABEL <mcsymbol .Ltmp0>
+    $x0 = COPY $xzr
+    BL @"??2 at YAPEAX_K@Z", csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $x0, implicit-def $sp, implicit-def $x0
+    EH_LABEL <mcsymbol .Ltmp0>
+    B %bb.1
+
+  bb.1:
+    successors: %bb.4(0x30000000)
+    liveins: $x0, $x19, $x20
+
+    STRXui $xzr, renamable $x20, 1 :: (store (s64), align 1)
+    STRXui $xzr, renamable $x20, 0 :: (store (s64), align 1)
+    STRXui $xzr, killed renamable $x20, 2 :: (store (s64), align 1)
+    STRXui killed renamable $x0, renamable $x19, 0 :: (store (s64))
+    B %bb.4
+
+  bb.2:
+    successors: %bb.3(0x80000000)
+    liveins: $x19
+
+    renamable $x8 = SUBXri killed renamable $x19, 8, 0
+
+  bb.3:
+    successors: %bb.3(0x80000000)
+    liveins: $x8
+
+    early-clobber renamable $x8 = STRXpost $xzr, killed renamable $x8, -8 :: (store (s64))
+    B %bb.3
+
+  bb.4:
+    $x0 = COPY $xzr
+    frame-destroy SEH_EpilogStart
+    $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64)), (load (s64))
+    frame-destroy SEH_SaveFPLR 16
+    early-clobber $sp, $x19, $x20 = frame-destroy LDPXpost $sp, 6 :: (load (s64)), (load (s64))
+    frame-destroy SEH_SaveRegP_X 19, 20, -48
+    frame-destroy SEH_EpilogEnd
+    RET_ReallyLR implicit $x0
+
+  bb.5 (landing-pad, ehfunclet-entry, ehscope-entry):
+    liveins: $x20, $x19, $lr
+
+    early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -4 :: (store (s64)), (store (s64))
+    frame-setup SEH_SaveRegP_X 19, 20, -32
+    frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64)), (store (s64))
+    frame-setup SEH_SaveFPLR 16
+    frame-setup SEH_PrologEnd
+    renamable $x8 = COPY $xzr
+    STRWui $wzr, killed renamable $x8, 0 :: (volatile store (s32) into `ptr null`, align 4294967296)
+    frame-destroy SEH_EpilogStart
+    $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64)), (load (s64))
+    frame-destroy SEH_SaveFPLR 16
+    early-clobber $sp, $x19, $x20 = frame-destroy LDPXpost $sp, 4 :: (load (s64)), (load (s64))
+    frame-destroy SEH_SaveRegP_X 19, 20, -32
+    frame-destroy SEH_EpilogEnd
+    CLEANUPRET
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/175550


More information about the llvm-commits mailing list