[llvm] [MachineLICM] Only mark live-ins as non-invariant if defined in loop (PR #191755)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 12 20:37:15 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-backend-risc-v
Author: yuyzhang512
<details>
<summary>Changes</summary>
Previously, `HoistRegionPostRA` conservatively treated all live-in registers
as external defs, preventing hoisting of any instruction using them. This was
overly conservative for registers defined solely outside the loop, which are
truly loop-invariant.
This patch uses a two-pass approach:
1. First collect all register units defined within the loop
2. Then only mark live-in registers that overlap with loop defs as non-invariant
This allows hoisting instructions that use registers defined only outside the
loop (e.g. spill reloads).
- Added new lit test `machinelicm-livein-not-def-in-loop.mir` with positive and negative cases
- Updated 30 existing tests across AMDGPU, X86, AArch64, SystemZ, and RISCV to reflect improved
hoisting
---
Patch is 59.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191755.diff
32 Files Affected:
- (modified) llvm/lib/CodeGen/MachineLICM.cpp (+28-6)
- (modified) llvm/test/CodeGen/AArch64/avoid-free-ext-promotion.ll (+1-1)
- (modified) llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir (+3-3)
- (modified) llvm/test/CodeGen/AArch64/peephole-and-tst.ll (+2-2)
- (modified) llvm/test/CodeGen/AMDGPU/coalescer_distribute.ll (+2-1)
- (modified) llvm/test/CodeGen/AMDGPU/indirect-addressing-si.ll (+8-8)
- (modified) llvm/test/CodeGen/AMDGPU/infer-addrspace-flat-atomic.ll (+2-1)
- (modified) llvm/test/CodeGen/AMDGPU/insert-delay-alu-bug.ll (+2-2)
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.kill.ll (+6-5)
- (added) llvm/test/CodeGen/AMDGPU/machinelicm-livein-not-def-in-loop.mir (+114)
- (modified) llvm/test/CodeGen/AMDGPU/no-dup-inst-prefetch.ll (+16-18)
- (modified) llvm/test/CodeGen/AMDGPU/noclobber-barrier.ll (+2-1)
- (modified) llvm/test/CodeGen/AMDGPU/select-undef.ll (+39-22)
- (modified) llvm/test/CodeGen/AMDGPU/undefined-subreg-liverange.ll (+2-1)
- (modified) llvm/test/CodeGen/RISCV/rvv/pr95865.ll (+1-1)
- (modified) llvm/test/CodeGen/SystemZ/DAGCombiner_illegal_BUILD_VECTOR.ll (+1-1)
- (modified) llvm/test/CodeGen/SystemZ/vec-trunc-to-i1.ll (+2-1)
- (modified) llvm/test/CodeGen/X86/2007-01-13-StackPtrIndex.ll (+2-2)
- (modified) llvm/test/CodeGen/X86/2009-04-25-CoalescerBug.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/apx/nf-regressions.ll (+13-11)
- (modified) llvm/test/CodeGen/X86/assertzext-demanded.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/combine-i64-trunc-srl-add.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/combine-pmuldq.ll (+2-2)
- (modified) llvm/test/CodeGen/X86/constant-pool-sharing.ll (+4-4)
- (modified) llvm/test/CodeGen/X86/postalloc-coalescing.ll (-1)
- (modified) llvm/test/CodeGen/X86/pr22338.ll (+2-2)
- (modified) llvm/test/CodeGen/X86/pr63108.ll (+4-4)
- (modified) llvm/test/CodeGen/X86/promote-sra-by-itself.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/ragreedy-hoist-spill.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/split-extend-vector-inreg.ll (+2-2)
- (modified) llvm/test/CodeGen/X86/trunc-store.ll (+1-1)
- (modified) llvm/test/CodeGen/X86/undef-label.ll (+6-5)
``````````diff
diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp
index 53fbd3bec76cd..650d03f3b22f7 100644
--- a/llvm/lib/CodeGen/MachineLICM.cpp
+++ b/llvm/lib/CodeGen/MachineLICM.cpp
@@ -596,20 +596,42 @@ void MachineLICMImpl::HoistRegionPostRA(MachineLoop *CurLoop) {
SmallVector<CandidateInfo, 32> Candidates;
SmallDenseSet<int> StoredFIs;
- // Walk the entire region, count number of defs for each register, and
- // collect potential LICM candidates.
+ // First pass: collect all register units defined within the loop.
+ BitVector LoopRUDefs(NumRegUnits);
+ for (MachineBasicBlock *BB : CurLoop->getBlocks()) {
+ for (MachineInstr &MI : *BB) {
+ for (const MachineOperand &MO : MI.operands()) {
+ if (MO.isRegMask()) {
+ applyBitsNotInRegMaskToRegUnitsMask(*TRI, LoopRUDefs,
+ MO.getRegMask());
+ continue;
+ }
+ if (!MO.isReg() || !MO.isDef())
+ continue;
+ Register Reg = MO.getReg();
+ if (!Reg)
+ continue;
+ for (MCRegUnit Unit : TRI->regunits(Reg))
+ LoopRUDefs.set(static_cast<unsigned>(Unit));
+ }
+ }
+ }
+
+ // Second pass: walk the entire region, count number of defs for each
+ // register, and collect potential LICM candidates.
for (MachineBasicBlock *BB : CurLoop->getBlocks()) {
// If the header of the loop containing this basic block is a landing pad,
// then don't try to hoist instructions out of this loop.
const MachineLoop *ML = MLI->getLoopFor(BB);
if (ML && ML->getHeader()->isEHPad()) continue;
- // Conservatively treat live-in's as an external def.
- // FIXME: That means a reload that're reused in successor block(s) will not
- // be LICM'ed.
+ // Only treat live-in registers that are also defined within the loop as
+ // non-invariant. Live-ins that are solely defined outside the loop are
+ // loop-invariant and should not block hoisting.
for (const auto &LI : BB->liveins()) {
for (MCRegUnit Unit : TRI->regunits(LI.PhysReg))
- RUDefs.set(static_cast<unsigned>(Unit));
+ if (LoopRUDefs.test(static_cast<unsigned>(Unit)))
+ RUDefs.set(static_cast<unsigned>(Unit));
}
// Funclet entry blocks will clobber all registers
diff --git a/llvm/test/CodeGen/AArch64/avoid-free-ext-promotion.ll b/llvm/test/CodeGen/AArch64/avoid-free-ext-promotion.ll
index 634d1b90ff903..49090aa80b625 100644
--- a/llvm/test/CodeGen/AArch64/avoid-free-ext-promotion.ll
+++ b/llvm/test/CodeGen/AArch64/avoid-free-ext-promotion.ll
@@ -14,9 +14,9 @@ define void @avoid_promotion_1_and(ptr nocapture noundef %arg, ptr %p) {
; CHECK: ; %bb.0: ; %bb
; CHECK-NEXT: ldr w8, [x0, #52]
; CHECK-NEXT: mov w9, #10 ; =0xa
+; CHECK-NEXT: cmp w8, #3
; CHECK-NEXT: LBB0_1: ; %bb8
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: cmp w8, #3
; CHECK-NEXT: b.lo LBB0_1
; CHECK-NEXT: ; %bb.2: ; %bb9
; CHECK-NEXT: ; in Loop: Header=BB0_1 Depth=1
diff --git a/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir b/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir
index 2c5a70288cfad..658755489ff44 100644
--- a/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir
+++ b/llvm/test/CodeGen/AArch64/mlicm-implicit-defs.mir
@@ -62,15 +62,15 @@ body: |
; CHECK-NEXT: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: $x12 = COPY killed $x0
+ ; CHECK-NEXT: $x1 = COPY killed $x12
; CHECK-NEXT: $x2 = MOVi64imm 1024, implicit-def dead $x16
; CHECK-NEXT: B %bb.1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
- ; CHECK-NEXT: liveins: $x12, $x2
+ ; CHECK-NEXT: liveins: $x12, $x1, $x2
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: $x1 = COPY killed $x12
- ; CHECK-NEXT: $x16 = LDRXroX killed $x1, $x2, 0, 0
+ ; CHECK-NEXT: $x16 = LDRXroX $x1, $x2, 0, 0
; CHECK-NEXT: $xzr = SUBSXri $x16, 0, 0, implicit-def $nzcv
; CHECK-NEXT: Bcc 1, %bb.1, implicit $nzcv
; CHECK-NEXT: B %bb.2
diff --git a/llvm/test/CodeGen/AArch64/peephole-and-tst.ll b/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
index 74b0e69d1b05b..29db9febcb1b8 100644
--- a/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
+++ b/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
@@ -10,6 +10,7 @@ define i32 @test_func_i32_two_uses(i32 %in, i32 %bit, i32 %mask) {
; CHECK-SD-LABEL: test_func_i32_two_uses:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: adrp x8, :got:ptr_wrapper
+; CHECK-SD-NEXT: and w11, w2, w0
; CHECK-SD-NEXT: ldr x8, [x8, :got_lo12:ptr_wrapper]
; CHECK-SD-NEXT: ldr x9, [x8]
; CHECK-SD-NEXT: mov w8, wzr
@@ -22,7 +23,6 @@ define i32 @test_func_i32_two_uses(i32 %in, i32 %bit, i32 %mask) {
; CHECK-SD-NEXT: .LBB0_3: // %do.body
; CHECK-SD-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-SD-NEXT: ands w10, w1, w0
-; CHECK-SD-NEXT: and w11, w2, w0
; CHECK-SD-NEXT: cinc w8, w8, ne
; CHECK-SD-NEXT: cmp w10, w11
; CHECK-SD-NEXT: b.eq .LBB0_1
@@ -40,6 +40,7 @@ define i32 @test_func_i32_two_uses(i32 %in, i32 %bit, i32 %mask) {
; CHECK-GI-LABEL: test_func_i32_two_uses:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: adrp x8, :got:ptr_wrapper
+; CHECK-GI-NEXT: and w11, w2, w0
; CHECK-GI-NEXT: ldr x8, [x8, :got_lo12:ptr_wrapper]
; CHECK-GI-NEXT: ldr x9, [x8]
; CHECK-GI-NEXT: mov w8, wzr
@@ -53,7 +54,6 @@ define i32 @test_func_i32_two_uses(i32 %in, i32 %bit, i32 %mask) {
; CHECK-GI-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-GI-NEXT: and w10, w1, w0
; CHECK-GI-NEXT: tst w1, w0
-; CHECK-GI-NEXT: and w11, w2, w0
; CHECK-GI-NEXT: cinc w8, w8, ne
; CHECK-GI-NEXT: cmp w10, w11
; CHECK-GI-NEXT: b.eq .LBB0_1
diff --git a/llvm/test/CodeGen/AMDGPU/coalescer_distribute.ll b/llvm/test/CodeGen/AMDGPU/coalescer_distribute.ll
index d07cc84865bea..20990488f3704 100644
--- a/llvm/test/CodeGen/AMDGPU/coalescer_distribute.ll
+++ b/llvm/test/CodeGen/AMDGPU/coalescer_distribute.ll
@@ -20,9 +20,10 @@ define amdgpu_kernel void @hoge(i1 %c0, i1 %c1, i1 %c2, i1 %c3, i1 %c4) {
; CHECK-NEXT: s_xor_b64 s[0:1], s[0:1], -1
; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1]
; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v0
+; CHECK-NEXT: s_and_b64 vcc, exec, s[0:1]
; CHECK-NEXT: .LBB0_1: ; %bb25
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: s_and_b64 vcc, exec, s[0:1]
+; CHECK-NEXT: s_mov_b64 vcc, vcc
; CHECK-NEXT: s_cbranch_vccnz .LBB0_1
; CHECK-NEXT: ; %bb.2: ; %bb30
; CHECK-NEXT: s_endpgm
diff --git a/llvm/test/CodeGen/AMDGPU/indirect-addressing-si.ll b/llvm/test/CodeGen/AMDGPU/indirect-addressing-si.ll
index a9e67ff3fdcbb..91409c3daeb96 100644
--- a/llvm/test/CodeGen/AMDGPU/indirect-addressing-si.ll
+++ b/llvm/test/CodeGen/AMDGPU/indirect-addressing-si.ll
@@ -9595,6 +9595,8 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; SI-MOVREL-NEXT: v_mov_b32_e32 v0, 8
; SI-MOVREL-NEXT: s_mov_b32 s3, 0xf000
; SI-MOVREL-NEXT: s_mov_b32 s2, -1
+; SI-MOVREL-NEXT: s_waitcnt lgkmcnt(0)
+; SI-MOVREL-NEXT: v_mov_b32_e32 v17, s1
; SI-MOVREL-NEXT: s_branch .LBB26_2
; SI-MOVREL-NEXT: .LBB26_1:
; SI-MOVREL-NEXT: ; implicit-def: $vgpr0
@@ -9602,14 +9604,12 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; SI-MOVREL-NEXT: .LBB26_2: ; %bb2
; SI-MOVREL-NEXT: ; =>This Loop Header: Depth=1
; SI-MOVREL-NEXT: ; Child Loop BB26_4 Depth 2
-; SI-MOVREL-NEXT: s_waitcnt lgkmcnt(0)
; SI-MOVREL-NEXT: v_cmp_le_i32_e32 vcc, s0, v0
; SI-MOVREL-NEXT: s_cbranch_vccnz .LBB26_1
; SI-MOVREL-NEXT: ; %bb.3: ; %bb4
; SI-MOVREL-NEXT: ; in Loop: Header=BB26_2 Depth=1
; SI-MOVREL-NEXT: buffer_load_dword v16, off, s[0:3], 0 glc
; SI-MOVREL-NEXT: s_waitcnt vmcnt(0)
-; SI-MOVREL-NEXT: v_mov_b32_e32 v17, s1
; SI-MOVREL-NEXT: s_mov_b64 s[4:5], exec
; SI-MOVREL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
; SI-MOVREL-NEXT: .LBB26_4: ; Parent Loop BB26_2 Depth=1
@@ -9631,6 +9631,8 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; VI-MOVREL: ; %bb.0: ; %bb
; VI-MOVREL-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; VI-MOVREL-NEXT: v_mov_b32_e32 v0, 8
+; VI-MOVREL-NEXT: s_waitcnt lgkmcnt(0)
+; VI-MOVREL-NEXT: v_mov_b32_e32 v17, s1
; VI-MOVREL-NEXT: s_branch .LBB26_2
; VI-MOVREL-NEXT: .LBB26_1:
; VI-MOVREL-NEXT: ; implicit-def: $vgpr0
@@ -9638,14 +9640,12 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; VI-MOVREL-NEXT: .LBB26_2: ; %bb2
; VI-MOVREL-NEXT: ; =>This Loop Header: Depth=1
; VI-MOVREL-NEXT: ; Child Loop BB26_4 Depth 2
-; VI-MOVREL-NEXT: s_waitcnt lgkmcnt(0)
; VI-MOVREL-NEXT: v_cmp_le_i32_e32 vcc, s0, v0
; VI-MOVREL-NEXT: s_cbranch_vccnz .LBB26_1
; VI-MOVREL-NEXT: ; %bb.3: ; %bb4
; VI-MOVREL-NEXT: ; in Loop: Header=BB26_2 Depth=1
; VI-MOVREL-NEXT: flat_load_dword v16, v[0:1] glc
; VI-MOVREL-NEXT: s_waitcnt vmcnt(0)
-; VI-MOVREL-NEXT: v_mov_b32_e32 v17, s1
; VI-MOVREL-NEXT: s_mov_b64 s[2:3], exec
; VI-MOVREL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
; VI-MOVREL-NEXT: .LBB26_4: ; Parent Loop BB26_2 Depth=1
@@ -9667,6 +9667,8 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; VI-IDXMODE: ; %bb.0: ; %bb
; VI-IDXMODE-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; VI-IDXMODE-NEXT: v_mov_b32_e32 v0, 8
+; VI-IDXMODE-NEXT: s_waitcnt lgkmcnt(0)
+; VI-IDXMODE-NEXT: v_mov_b32_e32 v17, s1
; VI-IDXMODE-NEXT: s_branch .LBB26_2
; VI-IDXMODE-NEXT: .LBB26_1:
; VI-IDXMODE-NEXT: ; implicit-def: $vgpr0
@@ -9674,14 +9676,12 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; VI-IDXMODE-NEXT: .LBB26_2: ; %bb2
; VI-IDXMODE-NEXT: ; =>This Loop Header: Depth=1
; VI-IDXMODE-NEXT: ; Child Loop BB26_4 Depth 2
-; VI-IDXMODE-NEXT: s_waitcnt lgkmcnt(0)
; VI-IDXMODE-NEXT: v_cmp_le_i32_e32 vcc, s0, v0
; VI-IDXMODE-NEXT: s_cbranch_vccnz .LBB26_1
; VI-IDXMODE-NEXT: ; %bb.3: ; %bb4
; VI-IDXMODE-NEXT: ; in Loop: Header=BB26_2 Depth=1
; VI-IDXMODE-NEXT: flat_load_dword v16, v[0:1] glc
; VI-IDXMODE-NEXT: s_waitcnt vmcnt(0)
-; VI-IDXMODE-NEXT: v_mov_b32_e32 v17, s1
; VI-IDXMODE-NEXT: s_mov_b64 s[2:3], exec
; VI-IDXMODE-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
; VI-IDXMODE-NEXT: .LBB26_4: ; Parent Loop BB26_2 Depth=1
@@ -9704,6 +9704,8 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; GFX9-IDXMODE: ; %bb.0: ; %bb
; GFX9-IDXMODE-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x24
; GFX9-IDXMODE-NEXT: v_mov_b32_e32 v0, 8
+; GFX9-IDXMODE-NEXT: s_waitcnt lgkmcnt(0)
+; GFX9-IDXMODE-NEXT: v_mov_b32_e32 v17, s1
; GFX9-IDXMODE-NEXT: s_branch .LBB26_2
; GFX9-IDXMODE-NEXT: .LBB26_1:
; GFX9-IDXMODE-NEXT: ; implicit-def: $vgpr0
@@ -9711,14 +9713,12 @@ define amdgpu_kernel void @broken_phi_bb(i32 %arg, i32 %arg1) {
; GFX9-IDXMODE-NEXT: .LBB26_2: ; %bb2
; GFX9-IDXMODE-NEXT: ; =>This Loop Header: Depth=1
; GFX9-IDXMODE-NEXT: ; Child Loop BB26_4 Depth 2
-; GFX9-IDXMODE-NEXT: s_waitcnt lgkmcnt(0)
; GFX9-IDXMODE-NEXT: v_cmp_le_i32_e32 vcc, s0, v0
; GFX9-IDXMODE-NEXT: s_cbranch_vccnz .LBB26_1
; GFX9-IDXMODE-NEXT: ; %bb.3: ; %bb4
; GFX9-IDXMODE-NEXT: ; in Loop: Header=BB26_2 Depth=1
; GFX9-IDXMODE-NEXT: global_load_dword v16, v[0:1], off glc
; GFX9-IDXMODE-NEXT: s_waitcnt vmcnt(0)
-; GFX9-IDXMODE-NEXT: v_mov_b32_e32 v17, s1
; GFX9-IDXMODE-NEXT: s_mov_b64 s[2:3], exec
; GFX9-IDXMODE-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15
; GFX9-IDXMODE-NEXT: .LBB26_4: ; Parent Loop BB26_2 Depth=1
diff --git a/llvm/test/CodeGen/AMDGPU/infer-addrspace-flat-atomic.ll b/llvm/test/CodeGen/AMDGPU/infer-addrspace-flat-atomic.ll
index 36df710529599..338bea9668722 100644
--- a/llvm/test/CodeGen/AMDGPU/infer-addrspace-flat-atomic.ll
+++ b/llvm/test/CodeGen/AMDGPU/infer-addrspace-flat-atomic.ll
@@ -119,9 +119,10 @@ define protected amdgpu_kernel void @InferPHI(i32 %a, ptr addrspace(1) %b, doubl
; CHECK-NEXT: s_cselect_b64 s[0:1], -1, 0
; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1]
; CHECK-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v0
+; CHECK-NEXT: s_and_b64 vcc, exec, s[0:1]
; CHECK-NEXT: .LBB3_1: ; %bb0
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
-; CHECK-NEXT: s_and_b64 vcc, exec, s[0:1]
+; CHECK-NEXT: s_mov_b64 vcc, vcc
; CHECK-NEXT: s_cbranch_vccnz .LBB3_1
; CHECK-NEXT: ; %bb.2: ; %bb1
; CHECK-NEXT: s_mov_b64 s[0:1], src_shared_base
diff --git a/llvm/test/CodeGen/AMDGPU/insert-delay-alu-bug.ll b/llvm/test/CodeGen/AMDGPU/insert-delay-alu-bug.ll
index 7d8a0b70d5f55..39f1fee7ca8e8 100644
--- a/llvm/test/CodeGen/AMDGPU/insert-delay-alu-bug.ll
+++ b/llvm/test/CodeGen/AMDGPU/insert-delay-alu-bug.ll
@@ -172,10 +172,10 @@ define amdgpu_kernel void @f2(i32 %arg, i32 %arg1, i32 %arg2, i1 %arg3, i32 %arg
; GFX11-NEXT: s_cbranch_vccz .LBB2_12
; GFX11-NEXT: ; %bb.9:
; GFX11-NEXT: s_xor_b32 s0, s3, -1
-; GFX11-NEXT: .LBB2_10: ; %bb17
-; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1
; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1)
; GFX11-NEXT: s_and_b32 vcc_lo, exec_lo, s0
+; GFX11-NEXT: .LBB2_10: ; %bb17
+; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1
; GFX11-NEXT: s_cbranch_vccz .LBB2_10
; GFX11-NEXT: ; %bb.11: ; %Flow6
; GFX11-NEXT: s_mov_b32 s21, -1
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.kill.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.kill.ll
index af81d95973452..f646c40f9300e 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.kill.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.kill.ll
@@ -1529,13 +1529,14 @@ define amdgpu_ps void @kill_with_loop_exit(float inreg %inp0, float inreg %inp1,
; SI-NEXT: ; %bb.1: ; %.preheader1.preheader
; SI-NEXT: v_cmp_ngt_f32_e64 s[0:1], s6, 0
; SI-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[0:1]
+; SI-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v1
; SI-NEXT: s_mov_b64 s[2:3], exec
; SI-NEXT: v_mov_b32_e32 v0, 0x3fc00000
-; SI-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v1
+; SI-NEXT: s_and_b64 vcc, exec, s[0:1]
; SI-NEXT: .LBB26_2: ; %bb
; SI-NEXT: ; =>This Inner Loop Header: Depth=1
-; SI-NEXT: s_and_b64 vcc, exec, s[0:1]
; SI-NEXT: v_add_f32_e32 v0, 0x3e800000, v0
+; SI-NEXT: s_mov_b64 vcc, vcc
; SI-NEXT: s_cbranch_vccnz .LBB26_2
; SI-NEXT: ; %bb.3: ; %bb33
; SI-NEXT: s_andn2_b64 s[2:3], s[2:3], exec
@@ -1564,10 +1565,10 @@ define amdgpu_ps void @kill_with_loop_exit(float inreg %inp0, float inreg %inp1,
; GFX10-NEXT: s_mov_b64 s[2:3], exec
; GFX10-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[0:1]
; GFX10-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v1
+; GFX10-NEXT: s_and_b64 vcc, exec, s[0:1]
; GFX10-NEXT: .LBB26_2: ; %bb
; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1
; GFX10-NEXT: v_add_f32_e32 v0, 0x3e800000, v0
-; GFX10-NEXT: s_and_b64 vcc, exec, s[0:1]
; GFX10-NEXT: s_cbranch_vccnz .LBB26_2
; GFX10-NEXT: ; %bb.3: ; %bb33
; GFX10-NEXT: s_andn2_b64 s[2:3], s[2:3], exec
@@ -1597,10 +1598,10 @@ define amdgpu_ps void @kill_with_loop_exit(float inreg %inp0, float inreg %inp1,
; GFX11-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[0:1]
; GFX11-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v1
; GFX11-NEXT: s_waitcnt_depctr depctr_va_sdst(0)
+; GFX11-NEXT: s_and_b64 vcc, exec, s[0:1]
; GFX11-NEXT: .LBB26_2: ; %bb
; GFX11-NEXT: ; =>This Inner Loop Header: Depth=1
; GFX11-NEXT: v_add_f32_e32 v0, 0x3e800000, v0
-; GFX11-NEXT: s_and_b64 vcc, exec, s[0:1]
; GFX11-NEXT: s_cbranch_vccnz .LBB26_2
; GFX11-NEXT: ; %bb.3: ; %bb33
; GFX11-NEXT: s_and_not1_b64 s[2:3], s[2:3], exec
@@ -1632,10 +1633,10 @@ define amdgpu_ps void @kill_with_loop_exit(float inreg %inp0, float inreg %inp1,
; GFX12-NEXT: s_cselect_b64 s[0:1], -1, 0
; GFX12-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1]
; GFX12-NEXT: v_cmp_ne_u32_e64 s[0:1], 1, v0
+; GFX12-NEXT: s_and_b64 vcc, exec, s[0:1]
; GFX12-NEXT: .LBB26_2: ; %bb
; GFX12-NEXT: ; =>This Inner Loop Header: Depth=1
; GFX12-NEXT: s_add_f32 s4, s4, 0x3e800000
-; GFX12-NEXT: s_and_b64 vcc, exec, s[0:1]
; GFX12-NEXT: s_cbranch_vccnz .LBB26_2
; GFX12-NEXT: ; %bb.3: ; %bb33
; GFX12-NEXT: s_and_not1_b64 s[2:3], s[2:3], exec
diff --git a/llvm/test/CodeGen/AMDGPU/machinelicm-livein-not-def-in-loop.mir b/llvm/test/CodeGen/AMDGPU/machinelicm-livein-not-def-in-loop.mir
new file mode 100644
index 0000000000000..255689463c2dc
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/machinelicm-livein-not-def-in-loop.mir
@@ -0,0 +1,114 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=amdgcn -mcpu=gfx900 -run-pass=machinelicm -verify-machineinstrs -o - %s | FileCheck %s
+# RUN: llc -mtriple=amdgcn -mcpu=gfx900 -passes=machinelicm -o - %s | FileCheck %s
+
+# Test that post-RA MachineLICM can hoist an instruction using a live-in
+# register that is not defined within the loop. Previously, all live-in
+# registers were conservatively treated as non-invariant, which blocked
+# hoisting.
+
+---
+# $sgpr0 is defined in the preheader and is live-in to the loop body but
+# never redefined inside the loop. The S_MOV_B32 reading $sgpr0 should
+# be hoisted to the preheader.
+name: hoist_livein_not_def_in_loop
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: hoist_livein_not_def_in_loop
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: liveins: $sgpr0, $sgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $sgpr0 = S_MOV_B32 0
+ ; CHECK-NEXT: $sgpr2 = S_MOV_B32 $sgpr0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: liveins: $sgpr0, $sgpr1, $sgpr2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: S_NOP 0, implicit $sgpr2
+ ; CHECK-NEXT: $sgpr1 = S_ADD_I32 $sgpr1, 1, implicit-def $scc
+ ; CHECK-NEXT: S_CBRANCH_SCC1 %bb.1, implicit $scc
+ ; CHECK-NEXT: S_BRANCH %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: liveins: $sgpr2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: S_NOP 0, implicit $sgpr2
+ ; CHECK-NEXT: S_ENDPGM 0
+ bb.0:
+ successors: %bb.1
+ liveins: $sgpr0, $sgpr1
+
+ $sgpr0 = S_MOV_B32 0
+
+ bb.1:
+ successors: %bb.1, %bb.2
+ liveins: $sgpr0, $sgpr1
+
+ $sgpr2 = S_MOV_B32 $sgpr0
+ S_NOP 0, implicit $sgpr2
+ $sgpr1 = S_ADD_I32 $sgpr1, 1, implicit-def $scc
+ S_CBRANCH_SCC1 %bb.1, implicit $scc
+ S_BRANCH %bb.2
+
+ bb.2:
+ liveins: $sgpr2
+
+ S_NOP 0, implicit $sgpr2
+ S_ENDPGM 0
+...
+
+---
+# $sgpr0 is live-in to the loop and also defined inside the loop. The
+# S_MOV_B32 reading $sgpr0 should NOT be hoisted since $sgpr0 is not
+# loop-invariant.
+name: no_hoist_livein_def_in_loop
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: no_hoist_livein_def_in_loop
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: liveins: $sgpr0, $sgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $sgpr0 = S_MOV_B32 0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: liveins: $sgpr0, $sgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $sgpr2 = S_MOV_B32 $sgpr0
+ ; CHECK-NEXT: $sgpr0 = S_ADD_I32 $sgpr0, 1, implicit-def $scc
+ ; CHECK-NEXT: S_NOP 0, implicit $sgpr2
+ ; CHECK-NEXT: $sgpr1 = S_ADD_I32 $sgpr1, -1, implicit-def $scc
+ ; CHECK-NEXT: S_CBRANCH_SCC1 %bb.1, implicit $scc
+ ; CHECK-NEXT: S_BRANCH %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: liveins: $sgpr2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: S_NOP 0, implicit $sgpr2
+ ; CHECK-NEXT: S_ENDPGM 0
+ bb.0:
+ successors: %bb.1
+ liveins: $sgpr0, $sgpr1
+
+ $sgpr0 = S_MOV_B32 0
+
+ bb.1:
+ successors: %bb.1, %bb.2
+ liveins: $sgpr0, $sgpr1
+
+ $sgpr2 = S_MOV_B32 $sgpr0
+ $sgpr0 = S_ADD_I32 $sgpr0, 1, implicit-def $scc
+ S_NOP 0, implicit $sgpr2
+ $sgpr1 = S_ADD_I32 $sgpr1, -1, impl...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/191755
More information about the llvm-commits
mailing list