[llvm] BPF: Fix misfolding subregisters (PR #208244)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 8 08:42:56 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/208244

This would end up introducing a copy between registers
with mismatched sizes previously. Defends against verifier
failures in a future change.

The actual transform here should be deleted. Optimizations should
not be trying to introduce SUBREG_TO_REG.

>From 2fc4cd3ef7d7d42ae95b9d26fd699babfe5a7366 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 8 Jul 2026 09:46:53 +0200
Subject: [PATCH] BPF: Fix misfolding subregisters

This would end up introducing a copy between registers
with mismatched sizes previously. Defends against verifier
failures in a future change.

The actual transform here should be deleted. Optimizations should
not be trying to introduce SUBREG_TO_REG.
---
 llvm/lib/Target/BPF/BPFMIPeephole.cpp         | 11 +++--
 .../CodeGen/BPF/mov32-64-subreg-source.mir    | 43 +++++++++++++++++++
 2 files changed, 50 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/BPF/mov32-64-subreg-source.mir

diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
index 637872ee2ebb8..d39259f074993 100644
--- a/llvm/lib/Target/BPF/BPFMIPeephole.cpp
+++ b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
@@ -48,6 +48,7 @@ struct BPFMIPeephole : public MachineFunctionPass {
 
   static char ID;
   const BPFInstrInfo *TII;
+  const BPFRegisterInfo *TRI;
   MachineFunction *MF;
   MachineRegisterInfo *MRI;
 
@@ -89,6 +90,7 @@ void BPFMIPeephole::initialize(MachineFunction &MFParm) {
   MF = &MFParm;
   MRI = &MF->getRegInfo();
   TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
+  TRI = &TII->getRegisterInfo();
   LLVM_DEBUG(dbgs() << "*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
 }
 
@@ -96,9 +98,6 @@ bool BPFMIPeephole::isCopyFrom32Def(MachineInstr *CopyMI)
 {
   MachineOperand &opnd = CopyMI->getOperand(1);
 
-  if (!opnd.isReg())
-    return false;
-
   // Return false if getting value from a 32bit physical register.
   // Most likely, this physical register is aliased to
   // function call return value or current function parameters.
@@ -106,7 +105,11 @@ bool BPFMIPeephole::isCopyFrom32Def(MachineInstr *CopyMI)
   if (!Reg.isVirtual())
     return false;
 
-  if (MRI->getRegClass(Reg) == &BPF::GPRRegClass)
+  const TargetRegisterClass *RC = MRI->getRegClass(Reg);
+  if (unsigned SubReg = opnd.getSubReg())
+    RC = TRI->getSubRegisterClass(RC, SubReg);
+
+  if (!RC->hasSubClassEq(&BPF::GPRRegClass))
     return false;
 
   MachineInstr *DefInsn = MRI->getVRegDef(Reg);
diff --git a/llvm/test/CodeGen/BPF/mov32-64-subreg-source.mir b/llvm/test/CodeGen/BPF/mov32-64-subreg-source.mir
new file mode 100644
index 0000000000000..35ab96b279406
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/mov32-64-subreg-source.mir
@@ -0,0 +1,43 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=bpfel -mattr=+alu32 -run-pass=bpf-mi-zext-elim %s -o - | FileCheck %s
+
+# Make sure that folds of MOV_32_64 respect a subregister index on the
+# source operand.
+
+---
+name:            mov32_64_subreg_source_imm
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $r1
+    ; CHECK-LABEL: name: mov32_64_subreg_source_imm
+    ; CHECK: liveins: $r1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[LD_imm64_:%[0-9]+]]:gpr = LD_imm64 0
+    ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr = SUBREG_TO_REG [[LD_imm64_]], %subreg.sub_32
+    ; CHECK-NEXT: $r0 = COPY [[SUBREG_TO_REG]]
+    ; CHECK-NEXT: RET implicit $r0
+    %0:gpr = LD_imm64 0
+    %1:gpr = MOV_32_64 %0.sub_32
+    $r0 = COPY %1:gpr
+    RET implicit $r0
+...
+
+---
+name:            mov32_64_subreg_source_copy
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $r1
+    ; CHECK-LABEL: name: mov32_64_subreg_source_copy
+    ; CHECK: liveins: $r1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $r1
+    ; CHECK-NEXT: [[MOV_32_64_:%[0-9]+]]:gpr = MOV_32_64 [[COPY]].sub_32
+    ; CHECK-NEXT: $r0 = COPY [[MOV_32_64_]]
+    ; CHECK-NEXT: RET implicit $r0
+    %0:gpr = COPY $r1
+    %1:gpr = MOV_32_64 %0.sub_32
+    $r0 = COPY %1:gpr
+    RET implicit $r0
+...



More information about the llvm-commits mailing list