Index: lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp =================================================================== --- lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -863,8 +863,10 @@ if (!Reg) continue; if (MO.isDef()) { - for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) - ModifiedRegs.set(*AI); + // WZR/XZR are not modified even when used as a destination register. + if (Reg != AArch64::WZR && Reg != AArch64::XZR) + for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) + ModifiedRegs.set(*AI); } else { assert(MO.isUse() && "Reg operand not a def and not a use?!?"); for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) Index: test/CodeGen/AArch64/ldst-opt.ll =================================================================== --- test/CodeGen/AArch64/ldst-opt.ll +++ test/CodeGen/AArch64/ldst-opt.ll @@ -1555,3 +1555,16 @@ store <4 x double> zeroinitializer, <4 x double>* %p ret void } + +; Check that write of xzr doesn't inhibit pariing of xzr stores since +; it isn't actually clobbered. +define i1 @no-clobber-zr(i64* %p, i64 %x) nounwind { +; CHECK-LABEL: no-clobber-zr +; CHECK: stp xzr, xzr, [x{{[0-9]+}}] +entry: + store i64 0, i64* %p + %cond = icmp eq i64 %x, 0 + %p1 = getelementptr i64, i64* %p, i64 1 + store i64 0, i64* %p1 + ret i1 %cond +}