[llvm] [Hexagon] Fix load/store widening to preserve subreg operands (PR #188181)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 23 23:19:38 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-hexagon

Author: None (pkarveti)

<details>
<summary>Changes</summary>

HexagonLoadStoreWidening pass was incorrectly using DoubleRegs registers where IntRegs was required when widening load/store pairs. When the S2_addasl_rrri instruction used a subreg (e.g., %2.isub_lo), the widening pass extracted only the base register without preserving the subreg, causing machine verifier errors.

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


2 Files Affected:

- (modified) llvm/lib/Target/Hexagon/HexagonLoadStoreWidening.cpp (+15-2) 
- (added) llvm/test/CodeGen/Hexagon/store-widen-subreg.mir (+34) 


``````````diff
diff --git a/llvm/lib/Target/Hexagon/HexagonLoadStoreWidening.cpp b/llvm/lib/Target/Hexagon/HexagonLoadStoreWidening.cpp
index 261b6c90ef265..27c77c8f2ba60 100644
--- a/llvm/lib/Target/Hexagon/HexagonLoadStoreWidening.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonLoadStoreWidening.cpp
@@ -581,6 +581,19 @@ MachineInstr *HexagonLoadStoreWidening::widenLoadStoreAddAsl(
   MachineInstr *WidenedInstr = nullptr;
   auto Reg1 = AddaslDef->getOperand(1).getReg();
   auto Reg2 = AddaslDef->getOperand(2).getReg();
+  unsigned Reg2SubReg = AddaslDef->getOperand(2).getSubReg();
+
+  // S4_storerd_rr and L4_loadrd_rr require IntRegs for Reg2.
+  const TargetRegisterClass *Reg2RC = MRI->getRegClass(Reg2);
+  if (Hexagon::DoubleRegsRegClass.hasSubClassEq(Reg2RC)) {
+    if (Reg2SubReg == 0)
+      // No subreg specified, cannot safely widen
+      return nullptr;
+
+  } else if (!Hexagon::IntRegsRegClass.hasSubClassEq(Reg2RC))
+    // Reg2 is neither IntRegs nor DoubleRegs, cannot widen
+    return nullptr;
+
   auto Reg3 = AddaslDef->getOperand(3).getImm();
   MachineInstrBuilder MIB;
 
@@ -590,12 +603,12 @@ MachineInstr *HexagonLoadStoreWidening::widenLoadStoreAddAsl(
               .addDef(NewPairReg, getKillRegState(LdOp.isKill()),
                       LdOp.getSubReg())
               .addReg(Reg1)
-              .addReg(Reg2)
+              .addReg(Reg2, {}, Reg2SubReg)
               .addImm(Reg3);
   } else {
     MIB = BuildMI(*MF, DL, TII->get(Hexagon::S4_storerd_rr))
               .addReg(Reg1)
-              .addReg(Reg2)
+              .addReg(Reg2, {}, Reg2SubReg)
               .addImm(Reg3)
               .addReg(NewPairReg);
   }
diff --git a/llvm/test/CodeGen/Hexagon/store-widen-subreg.mir b/llvm/test/CodeGen/Hexagon/store-widen-subreg.mir
new file mode 100644
index 0000000000000..47e79c4f5b33e
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/store-widen-subreg.mir
@@ -0,0 +1,34 @@
+# RUN: llc -mtriple=hexagon -run-pass=hexagon-widen-stores -verify-machineinstrs %s -o - | FileCheck %s
+
+# Test that store widening correctly handles DoubleRegs operands with subreg
+# in S2_addasl_rrri instruction. The widening pass should preserve the subreg
+# when creating the widened S4_storerd_rr instruction.
+
+--- |
+  define void @test_store_widen_subreg(ptr %base, i64 %idx, i32 %val) {
+  entry:
+    ret void
+  }
+...
+---
+name:            test_store_widen_subreg
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: test_store_widen_subreg
+  ; CHECK: S2_addasl_rrri %{{[0-9]+}}, %{{[0-9]+}}.isub_lo, 2
+  ; CHECK: S4_storerd_rr %{{[0-9]+}}, %{{[0-9]+}}.isub_lo, 2, %{{[0-9]+}} :: (store (s64), align 64)
+  bb.0:
+    liveins: $r0, $d1, $r4
+
+    %0:intregs = COPY $r4
+    %1:doubleregs = COPY $d1
+    %2:intregs = COPY $r0
+    %3:intregs = A2_addi %2, 384
+    %4:intregs = S2_addasl_rrri %3, %1.isub_lo, 2
+
+  bb.1:
+    successors: %bb.1(0x80000000)
+
+    S2_storeri_io %4, 0, %0 :: (store (s32), align 64)
+    S2_storeri_io %4, 4, %0 :: (store (s32))
+    J2_jump %bb.1, implicit-def dead $pc

``````````

</details>


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


More information about the llvm-commits mailing list