[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