diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp --- a/llvm/lib/CodeGen/MachineSink.cpp +++ b/llvm/lib/CodeGen/MachineSink.cpp @@ -1287,6 +1287,19 @@ SinkBlock->splice(SinkBlock->SkipPHIsAndLabels(SinkBlock->begin()), Preheader, I); + // Clear any kill flags on uses defined outside cycle + for (MachineOperand &MO : I.operands()) { + if (!MO.isReg() || !MO.isUse() || !MO.isKill()) + continue; + + for (const MachineInstr &MI : MRI->def_instructions(MO.getReg())) { + if (!Cycle->contains(MI.getParent())) { + MO.setIsKill(false); + break; + } + } + } + // The instruction is moved from its basic block, so do not retain the // debug information. assert(!I.isDebugInstr() && "Should not sink debug inst"); diff --git a/llvm/test/CodeGen/SystemZ/machinelicm-sunk-kill-flags.ll b/llvm/test/CodeGen/SystemZ/machinelicm-sunk-kill-flags.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/machinelicm-sunk-kill-flags.ll @@ -0,0 +1,23 @@ +; RUN: llc -mtriple=s390x-linux-gnu -O3 -consthoist-gep -sink-insts-to-avoid-spills -verify-machineinstrs -o /dev/null %s +; REQUIRES: asserts + +; Test that verification passes after MachineLICM. + +%0 = type <{ i32, [3 x i8] }> +@b = external dso_local global [1 x %0], align 2 + +define dso_local void @c() local_unnamed_addr #0 { +bb: + br label %bb1 + +bb1: ; preds = %bb1, %bb + call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 undef, ptr align 1 getelementptr inbounds ([1 x %0], ptr @b, i64 7, i64 0), i64 7, i1 true) + call void @llvm.memcpy.p0.p0.i64(ptr nonnull align 1 undef, ptr align 1 getelementptr inbounds ([1 x %0], ptr @b, i64 7, i64 0), i64 7, i1 true) + br label %bb1 +} + +; Function Attrs: argmemonly nofree nounwind willreturn +declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #1 + +attributes #0 = { "target-features"="+transactional-execution,+vector,+vector-enhancements-1,+vector-enhancements-2" } +attributes #1 = { argmemonly nofree nounwind willreturn }