[llvm-branch-commits] [llvm] 0380caa - [DAGCombine] Fix alignment of store in replaceStoreOfInsertLoad. (#215895)
Douglas Yung via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Aug 15 08:47:13 PDT 2026
Author: Eli Friedman
Date: 2026-08-15T15:46:59Z
New Revision: 0380caa08342afc85226053e686571739ec570ef
URL: https://github.com/llvm/llvm-project/commit/0380caa08342afc85226053e686571739ec570ef
DIFF: https://github.com/llvm/llvm-project/commit/0380caa08342afc85226053e686571739ec570ef.diff
LOG: [DAGCombine] Fix alignment of store in replaceStoreOfInsertLoad. (#215895)
For the variable index case, the alignment of the original store was
used, which is too large.
Fixes #215530
(cherry picked from commit 2dd35f8ff91fbea3d898474851f78dfad2332c18)
Added:
llvm/test/CodeGen/X86/store-of-insert-load-isel.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e772abffbadff..3ae55f69013d6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -24132,22 +24132,27 @@ SDValue DAGCombiner::replaceStoreOfInsertLoad(StoreSDNode *ST) {
return SDValue();
MachinePointerInfo PointerInfo(ST->getAddressSpace());
+ Align NewAlign;
// If the offset is a known constant then try to recover the pointer
// info
SDValue NewPtr;
if (auto *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
- unsigned COffset = CIdx->getSExtValue() * EltVT.getSizeInBits() / 8;
+ unsigned COffset = CIdx->getSExtValue() * EltVT.getFixedSizeInBits() / 8;
NewPtr = DAG.getMemBasePlusOffset(Ptr, TypeSize::getFixed(COffset), DL);
PointerInfo = ST->getPointerInfo().getWithOffset(COffset);
+ NewAlign = ST->getAlign();
} else {
// The original DAG loaded the entire vector from memory, so arithmetic
// within it must be inbounds.
NewPtr = TLI.getInboundsVectorElementPointer(DAG, Ptr, Value.getValueType(),
Idx);
+ // MachinePointerInfo can't represent a variable offset, so use a generic
+ // MachinePointerInfo and recompute the alignment.
+ NewAlign = commonAlignment(ST->getAlign(), EltVT.getFixedSizeInBits() / 8);
}
- return DAG.getStore(Chain, DL, Elt, NewPtr, PointerInfo, ST->getAlign(),
+ return DAG.getStore(Chain, DL, Elt, NewPtr, PointerInfo, NewAlign,
ST->getMemOperand()->getFlags());
}
diff --git a/llvm/test/CodeGen/X86/store-of-insert-load-isel.ll b/llvm/test/CodeGen/X86/store-of-insert-load-isel.ll
new file mode 100644
index 0000000000000..f33c6c29d047c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/store-of-insert-load-isel.ll
@@ -0,0 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-linux-gnu -stop-after=finalize-isel | FileCheck %s
+
+; Make sure the memory operand of the MOV32mr is correct. For a constant
+; offset, use the explicit alignment of the pointer; for a variable offset,
+; reduce the alignment.
+
+define void @constant_offset_insert(ptr %g, i32 %eltval) {
+ ; CHECK-LABEL: name: constant_offset_insert
+ ; CHECK: bb.0 (%ir-block.0):
+ ; CHECK-NEXT: liveins: $rdi, $esi
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $esi
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
+ ; CHECK-NEXT: MOV32mr [[COPY1]], 1, $noreg, 4, $noreg, [[COPY]] :: (store (s32) into %ir.g + 4, basealign 16)
+ ; CHECK-NEXT: RET 0
+ %vec = load <4 x i32>, ptr %g, align 16
+ %insert = insertelement <4 x i32> %vec, i32 %eltval, i32 1
+ store <4 x i32> %insert, ptr %g, align 16
+ ret void
+}
+
+define void @variable_offset_insert(ptr %g, i32 %eltval, i32 %offset) {
+ ; CHECK-LABEL: name: variable_offset_insert
+ ; CHECK: bb.0 (%ir-block.0):
+ ; CHECK-NEXT: liveins: $rdi, $esi, $edx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edx
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esi
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64 = COPY $rdi
+ ; CHECK-NEXT: [[AND32ri:%[0-9]+]]:gr32 = AND32ri [[COPY]], 3, implicit-def dead $eflags
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64_nosp = SUBREG_TO_REG killed [[AND32ri]], %subreg.sub_32bit
+ ; CHECK-NEXT: MOV32mr [[COPY2]], 4, killed [[SUBREG_TO_REG]], 0, $noreg, [[COPY1]] :: (store (s32))
+ ; CHECK-NEXT: RET 0
+ %vec = load <4 x i32>, ptr %g, align 16
+ %insert = insertelement <4 x i32> %vec, i32 %eltval, i32 %offset
+ store <4 x i32> %insert, ptr %g, align 16
+ ret void
+}
+
+define void @variable_offset_insert_unaligned(ptr %g, i32 %eltval, i32 %offset) {
+ ; CHECK-LABEL: name: variable_offset_insert_unaligned
+ ; CHECK: bb.0 (%ir-block.0):
+ ; CHECK-NEXT: liveins: $rdi, $esi, $edx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edx
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esi
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64 = COPY $rdi
+ ; CHECK-NEXT: [[AND32ri:%[0-9]+]]:gr32 = AND32ri [[COPY]], 3, implicit-def dead $eflags
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64_nosp = SUBREG_TO_REG killed [[AND32ri]], %subreg.sub_32bit
+ ; CHECK-NEXT: MOV32mr [[COPY2]], 4, killed [[SUBREG_TO_REG]], 0, $noreg, [[COPY1]] :: (store (s32), align 1)
+ ; CHECK-NEXT: RET 0
+ %vec = load <4 x i32>, ptr %g, align 1
+ %insert = insertelement <4 x i32> %vec, i32 %eltval, i32 %offset
+ store <4 x i32> %insert, ptr %g, align 1
+ ret void
+}
More information about the llvm-branch-commits
mailing list