[llvm] [MachineLICM] Only mark live-ins as non-invariant if defined in loop (PR #191755)

Yuyang Zhang via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 23 00:09:40 PDT 2026


================
@@ -36,11 +36,11 @@ define i32 @test(ptr %arg, ptr %arg1, ptr %arg2) #0 !dbg !6 {
 ; CHECK-NEXT:    movne r6, #0
 ; CHECK-NEXT:  Ltmp0:
 ; CHECK-NEXT:    @DEBUG_VALUE: test:this <- [DW_OP_LLVM_arg 0, DW_OP_plus_uconst 135168, DW_OP_LLVM_arg 1, DW_OP_constu 4, DW_OP_mul, DW_OP_plus, DW_OP_plus_uconst 4, DW_OP_stack_value] $r0, $r5
-; CHECK-NEXT:    .loc 1 28 24 prologue_end @ test.cpp:28:24
+; CHECK-NEXT:    .loc 1 28 24 prologue_end @ test.cpp:28:24 @[ test.cpp:204:23 ]
 ; CHECK-NEXT:    strne.w r6, [r8]
 ; CHECK-NEXT:    moveq r6, #1
 ; CHECK-NEXT:    ldr r4, [r4, #4]
-; CHECK-NEXT:    orrs r4, r6
+; CHECK-NEXT:    orr.w r4, r4, r6
----------------
yuyzhang512 wrote:

Yes, it did. The hoisted instruction is:
```
t2CMPri lr, 0, implicit-def $cpsr
```
Since `lr` is loop-invariant, the compare becomes hoistable with this change. Hoisting it into the preheader keeps `$cpsr` live throughout the loop, preventing `Thumb2SizeReduce` from using the 16-bit `adds`/`orrs` forms in the loop body because they would clobber the live `$cpsr`. As a result, those instructions remain in their 32-bit forms, leading to the code size increase.

The hoist is correct but unprofitable. This reflects a pre-existing limitation of post-RA `MachineLICM`, which currently has no cost model for hoisting. I also prototyped a guard to avoid hoisting instructions that define registers used by a loop terminator, but it also suppressed existing hoists, so I didn't include it in this patch.

Do you think it's worth pursuing a separate improvement here?

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


More information about the llvm-commits mailing list