[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