Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -8110,6 +8110,19 @@ Store->isIndexed()) return SDValue(); Stores.push_back(Store); + + // If this store is used as a chain operand in a store that is not included + // in the set of stores to be merged, then the transform may not be safe. + // We must preserve the order of that other store relative to the indivdual + // stores in this set. + for (SDNode *Use : Store->uses()) { + auto *StoreUse = dyn_cast(Use); + if (StoreUse && StoreUse->getChain().getNode() == Store && + !is_contained(Stores, StoreUse)) + return SDValue(); + } + + // Get the next link in the chain and try to collect another store. Chain = Store->getChain(); } // There is no reason to continue if we do not have at least a pair of stores. Index: llvm/test/CodeGen/SystemZ/merge-stores.ll =================================================================== --- llvm/test/CodeGen/SystemZ/merge-stores.ll +++ llvm/test/CodeGen/SystemZ/merge-stores.ll @@ -9,8 +9,9 @@ @f = dso_local local_unnamed_addr global ptr @e, align 8 @d = dso_local local_unnamed_addr global i32 0, align 4 -; FIXME: This shows a miscompile caused by merging truncated -; stores if the store of 0 (sthrl) to 'e' happens before +; PR58883: +; This shows a miscompile caused by merging truncated +; stores if the store of 0 (sthrl) to 'e' happens before ; a 64-bit store (stg) of r0. define signext i32 @main() { @@ -22,7 +23,7 @@ ; CHECK-NEXT: st %r2, 0(%r1) ; CHECK-NEXT: lhi %r2, 0 ; CHECK-NEXT: sthrl %r2, e -; CHECK-NEXT: stg %r0, 0(%r1) +; CHECK-NEXT: st %r0, 4(%r1) ; CHECK-NEXT: lghi %r2, 0 ; CHECK-NEXT: strl %r0, d ; CHECK-NEXT: br %r14