[llvm] [CodeGen] IMPLICIT_DEF must not contribute to Weight in LICM register cost computation (PR #196500)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 02:36:33 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: pratikashar

<details>
<summary>Changes</summary>

IMPLICIT_DEF is always hoisted out of loop by LICM as it's trivially
rematerializable.

Any src operand inside the loop whose value is defined by an
IMPLICIT_DEF shouldn't contribute to reduction in register pressure
in the loop.

If we do this, we end up hoisting too many instructions out of the loop
that later causes spill.


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


2 Files Affected:

- (modified) llvm/lib/CodeGen/MachineLICM.cpp (+5) 
- (added) llvm/test/CodeGen/X86/machine-licm-implicit-def-kill.mir (+110) 


``````````diff
diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp
index 53fbd3bec76cd..4e9959a1b600f 100644
--- a/llvm/lib/CodeGen/MachineLICM.cpp
+++ b/llvm/lib/CodeGen/MachineLICM.cpp
@@ -959,6 +959,11 @@ MachineLICMImpl::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen,
     Register Reg = MO.getReg();
     if (!Reg.isVirtual())
       continue;
+    // IMPLICIT_DEF contributes zero register pressure, so killing a vreg
+    // whose unique def is IMPLICIT_DEF must not reduce tracked pressure.
+    if (MachineInstr *DefMI = MRI->getUniqueVRegDef(Reg);
+        DefMI && DefMI->isImplicitDef())
+      continue;
 
     // FIXME: It seems bad to use RegSeen only for some of these calculations.
     bool isNew = ConsiderSeen ? RegSeen.insert(Reg).second : false;
diff --git a/llvm/test/CodeGen/X86/machine-licm-implicit-def-kill.mir b/llvm/test/CodeGen/X86/machine-licm-implicit-def-kill.mir
new file mode 100644
index 0000000000000..88a2f9aa3a26c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/machine-licm-implicit-def-kill.mir
@@ -0,0 +1,110 @@
+# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=early-machinelicm -o - %s | FileCheck %s
+
+# Verify that MachineLICM does not credit pressure relief for a use of a vreg
+# whose unique def is IMPLICIT_DEF.  GR pressure is saturated below, so if it
+# did, INSERT_SUBREG would hoist and cause a spill.
+
+# CHECK-LABEL: name: no_hoist_insert_subreg_of_implicit_def
+# IMPLICIT_DEF may hoist; INSERT_SUBREG must stay in the loop.
+# CHECK:      bb.0:
+# CHECK:        %{{[a-zA-Z0-9_.]+}}:gr64 = IMPLICIT_DEF
+# CHECK-NOT:    INSERT_SUBREG
+# CHECK:      bb.1:
+# CHECK:        %{{[a-zA-Z0-9_.]+}}:gr64 = INSERT_SUBREG %{{[a-zA-Z0-9_.]+}}, %{{[a-zA-Z0-9_.]+}}, %subreg.sub_32bit
+
+---
+name:            no_hoist_insert_subreg_of_implicit_def
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    successors: %bb.1(0x80000000)
+    liveins: $rdi
+
+    %0:gr64 = COPY $rdi
+    %1:gr64 = COPY $rdi
+    %2:gr64 = COPY $rdi
+    %3:gr64 = COPY $rdi
+    %4:gr64 = COPY $rdi
+    %5:gr64 = COPY $rdi
+    %6:gr64 = COPY $rdi
+    %7:gr64 = COPY $rdi
+    %8:gr64 = COPY $rdi
+    %9:gr64 = COPY $rdi
+    %10:gr64 = COPY $rdi
+    %11:gr64 = COPY $rdi
+    %12:gr64 = COPY $rdi
+    %13:gr64 = COPY $rdi
+    %14:gr64 = COPY $rdi
+    %15:gr64 = COPY $rdi
+    %16:gr64 = COPY $rdi
+    %17:gr64 = COPY $rdi
+    %18:gr64 = COPY $rdi
+    %19:gr64 = COPY $rdi
+    %20:gr64 = COPY $rdi
+    %21:gr64 = COPY $rdi
+    %22:gr64 = COPY $rdi
+    %23:gr64 = COPY $rdi
+    %24:gr64 = COPY $rdi
+    %25:gr64 = COPY $rdi
+    %26:gr64 = COPY $rdi
+    %27:gr64 = COPY $rdi
+    %28:gr64 = COPY $rdi
+    %29:gr64 = COPY $rdi
+    %30:gr64 = COPY $rdi
+    %31:gr64 = COPY $rdi
+    %32:gr64 = COPY $rdi
+    ; Multiple uses below so isOperandKill is false for %narrow at INSERT_SUBREG;
+    ; isolates the IMPLICIT_DEF case from a real GR32 -W kill.
+    %narrow:gr32 = COPY $edi
+
+  bb.1:
+    successors: %bb.1(0x7c000000), %bb.2(0x04000000)
+
+    %impdef:gr64 = IMPLICIT_DEF
+    %ins:gr64 = INSERT_SUBREG %impdef, %narrow, %subreg.sub_32bit
+
+    ; Keep preheader vregs and %narrow live to saturate GR16/GR32/GR64
+    ; pressure while LICM decides whether to hoist %ins.
+    $rax = MOV64rr %0
+    $rax = ADD64rr $rax, %1, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %2, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %3, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %4, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %5, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %6, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %7, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %8, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %9, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %10, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %11, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %12, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %13, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %14, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %15, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %16, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %17, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %18, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %19, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %20, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %21, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %22, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %23, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %24, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %25, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %26, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %27, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %28, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %29, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %30, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %31, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %32, implicit-def dead $eflags
+    $rax = ADD64rr $rax, %ins, implicit-def dead $eflags
+    $eax = ADD32rr $eax, %narrow, implicit-def dead $eflags
+    $eax = ADD32rr $eax, %narrow, implicit-def dead $eflags
+    MOV64mr %0, 1, $noreg, 0, $noreg, $rax :: (store (s64) into `ptr undef`)
+    JCC_1 %bb.1, 5, implicit undef $eflags
+    JMP_1 %bb.2
+
+  bb.2:
+    RET 0
+...

``````````

</details>


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


More information about the llvm-commits mailing list