Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -11523,8 +11523,11 @@ // Only look at ends of store sequences. SDValue Chain = SDValue(St, 0); - if (Chain->hasOneUse() && Chain->use_begin()->getOpcode() == ISD::STORE) - return false; + if (Chain->hasOneUse() && Chain->use_begin()->getOpcode() == ISD::STORE) { + StoreSDNode *StUser = cast(*Chain->use_begin()); + if (St->getMemoryVT() == StUser->getMemoryVT()) + return false; + } // Save the LoadSDNodes that we find in the chain. // We need to make sure that these nodes do not interfere with Index: test/CodeGen/AArch64/merge-store.ll =================================================================== --- test/CodeGen/AArch64/merge-store.ll +++ test/CodeGen/AArch64/merge-store.ll @@ -109,6 +109,47 @@ ret void } +; PR27816 - Continue merging consecutive stores when the next store has different type in store sequences + +; CHECK-LABEL: merge_const_store +; CHECK: str x{{[0-9]+}}, {{.*}} +; CHECK: str wzr + +%struct.A = type { i8, i8, i8, i8, i8, i8, i8, i8, i32} + +define void @merge_const_store(i32 %count, %struct.A* nocapture %p, i8 %val8) { + %1 = icmp sgt i32 %count, 0 + br i1 %1, label %.lr.ph, label %._crit_edge +.lr.ph: + %i.02 = phi i32 [ %add, %.lr.ph ], [ 0, %0 ] + %.01 = phi %struct.A* [ %addr, %.lr.ph ], [ %p, %0 ] + %a0 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 0 + store i8 1, i8* %a0, align 1 + %a1 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 1 + store i8 2, i8* %a1, align 1 + %a2 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 2 + store i8 3, i8* %a2, align 1 + %a3 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 3 + store i8 4, i8* %a3, align 1 + %a4 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 4 + store i8 5, i8* %a4, align 1 + %a5 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 5 + store i8 6, i8* %a5, align 1 + %a6 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 6 + store i8 7, i8* %a6, align 1 + %a7 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 7 + store i8 8, i8* %a7, align 1 + %addr_last = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 8 + store i32 0, i32* %addr_last, align 4 + %add = add nsw i32 %i.02, 1 + %addr = getelementptr inbounds %struct.A, %struct.A* %.01, i64 1 + %exitcond = icmp eq i32 %add, %count + br i1 %exitcond, label %._crit_edge, label %.lr.ph +._crit_edge: + ret void +} + + declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) declare i32 @fcntl(i32, i32, ...) declare noalias i8* @foo()