[MachineLICM] Recognize registers clobbered at EH landing pad entry (#122446)

EH landing pad entry implicitly clobbers target-specific exception
pointer and exception selector registers. The post-RA MachineLICM pass
needs to take these into account when deciding whether to hoist an
instruction out of the loop that initializes one of these registers.

Fixes: https://github.com/llvm/llvm-project/issues/122315
diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp
index d13d41c..9ea0e5a 100644
--- a/llvm/lib/CodeGen/MachineLICM.cpp
+++ b/llvm/lib/CodeGen/MachineLICM.cpp
@@ -633,6 +633,19 @@
     if (const uint32_t *Mask = BB->getBeginClobberMask(TRI))
       applyBitsNotInRegMaskToRegUnitsMask(*TRI, RUClobbers, Mask);
 
+    // EH landing pads clobber exception pointer/selector registers.
+    if (BB->isEHPad()) {
+      const MachineFunction &MF = *BB->getParent();
+      const Constant *PersonalityFn = MF.getFunction().getPersonalityFn();
+      const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
+      if (MCRegister Reg = TLI.getExceptionPointerRegister(PersonalityFn))
+        for (MCRegUnit Unit : TRI->regunits(Reg))
+          RUClobbers.set(Unit);
+      if (MCRegister Reg = TLI.getExceptionSelectorRegister(PersonalityFn))
+        for (MCRegUnit Unit : TRI->regunits(Reg))
+          RUClobbers.set(Unit);
+    }
+
     SpeculationState = SpeculateUnknown;
     for (MachineInstr &MI : *BB)
       ProcessMI(&MI, RUDefs, RUClobbers, StoredFIs, Candidates, CurLoop);
diff --git a/llvm/test/CodeGen/SystemZ/pr122315.ll b/llvm/test/CodeGen/SystemZ/pr122315.ll
new file mode 100644
index 0000000..b094d11
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/pr122315.ll
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Verify that MachineLICM recognizes that EH landing pad entry clobbers %r6/%r7
+;
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
+
+declare i64 @personality(i64, i64, i64, ptr, ptr)
+declare void @callee(i64, i64, i64, i64, i64)
+declare void @panic()
+
+define void @test() uwtable personality ptr @personality {
+; CHECK-LABEL: test:
+; CHECK:       .Lfunc_begin0:
+; CHECK-NEXT:    .cfi_startproc
+; CHECK-NEXT:    .cfi_personality 0, personality
+; CHECK-NEXT:    .cfi_lsda 0, .Lexception0
+; CHECK-NEXT:  # %bb.0: # %start
+; CHECK-NEXT:    stmg %r6, %r15, 48(%r15)
+; CHECK-NEXT:    .cfi_offset %r6, -112
+; CHECK-NEXT:    .cfi_offset %r7, -104
+; CHECK-NEXT:    .cfi_offset %r14, -48
+; CHECK-NEXT:    .cfi_offset %r15, -40
+; CHECK-NEXT:    aghi %r15, -160
+; CHECK-NEXT:    .cfi_def_cfa_offset 320
+; CHECK-NEXT:  .LBB0_1: # %bb1
+; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    lghi %r2, 0
+; CHECK-NEXT:    lghi %r3, 0
+; CHECK-NEXT:    lghi %r4, 0
+; CHECK-NEXT:    lghi %r5, 0
+; CHECK-NEXT:    lghi %r6, 0
+; CHECK-NEXT:    brasl %r14, callee@PLT
+; CHECK-NEXT:  .Ltmp0:
+; CHECK-NEXT:    brasl %r14, panic@PLT
+; CHECK-NEXT:  .Ltmp1:
+; CHECK-NEXT:    j .LBB0_3
+; CHECK-NEXT:  .LBB0_2: # %bb3
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:  .Ltmp2:
+; CHECK-NEXT:    j .LBB0_1
+; CHECK-NEXT:  .LBB0_3: # %bb2
+; CHECK-NEXT:    lmg %r6, %r15, 208(%r15)
+; CHECK-NEXT:    br %r14
+start:
+  br label %bb1
+
+bb1:
+  call void @callee(i64 0, i64 0, i64 0, i64 0, i64 0)
+  invoke void @panic()
+          to label %bb2 unwind label %bb3
+
+bb2:
+  ret void
+
+bb3:
+  %lp = landingpad { ptr, i32 }
+          catch ptr null
+  br label %bb1
+}
+