[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 03:17:41 PDT 2026


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

>From 8a611e74800bd462dcf049579b277728148bd540 Mon Sep 17 00:00:00 2001
From: Pratik J Ashar <pratik.j.ashar at intel.com>
Date: Fri, 8 May 2026 14:45:22 +0530
Subject: [PATCH] [CodeGen] IMPLICIT_DEF must not contribute to Weight in LICM
 register cost computation

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.
---
 llvm/lib/CodeGen/MachineLICM.cpp              |   5 +
 .../X86/machine-licm-implicit-def-kill.mir    | 110 ++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/machine-licm-implicit-def-kill.mir

diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp
index 53fbd3bec76cd..10daa557bb875 100644
--- a/llvm/lib/CodeGen/MachineLICM.cpp
+++ b/llvm/lib/CodeGen/MachineLICM.cpp
@@ -969,6 +969,11 @@ MachineLICMImpl::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen,
     if (MO.isDef())
       RCCost = W.RegWeight;
     else {
+      // IMPLICIT_DEF contributes zero register pressure, so a vreg whose
+      // unique def is IMPLICIT_DEF must not reduce tracked pressure.
+      if (MachineInstr *DefMI = MRI->getUniqueVRegDef(Reg);
+          DefMI && DefMI->isImplicitDef())
+        continue;
       bool isKill = isOperandKill(MO, MRI);
       if (isNew && !isKill && ConsiderUnseenAsDef)
         // Haven't seen this, it must be a livein.
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
+...



More information about the llvm-commits mailing list