Index: lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- lib/CodeGen/MachineCopyPropagation.cpp +++ lib/CodeGen/MachineCopyPropagation.cpp @@ -285,18 +285,24 @@ // defined registers. if (RegMask) { // Erase any MaybeDeadCopies whose destination register is clobbered. - for (MachineInstr *MaybeDead : MaybeDeadCopies) { + for (SmallSetVector::iterator DI = + MaybeDeadCopies.begin(); + DI != MaybeDeadCopies.end();) { + MachineInstr *MaybeDead = *DI; unsigned Reg = MaybeDead->getOperand(0).getReg(); assert(!MRI->isReserved(Reg)); - if (!RegMask->clobbersPhysReg(Reg)) + + if (!RegMask->clobbersPhysReg(Reg)) { + ++DI; continue; + } DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: "; MaybeDead->dump()); + MaybeDeadCopies.remove(MaybeDead); MaybeDead->eraseFromParent(); Changed = true; ++NumDeletes; } - MaybeDeadCopies.clear(); removeClobberedRegsFromMap(AvailCopyMap, *RegMask); removeClobberedRegsFromMap(CopyMap, *RegMask); Index: test/CodeGen/MIR/AArch64/machine-dead-copy.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/machine-dead-copy.mir @@ -0,0 +1,67 @@ + +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass machine-cp -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck %s + +--- | + define i32 @copyprop1(i32 %a, i32 %b) { ret i32 %a } + define i32 @copyprop2(i32 %a, i32 %b) { ret i32 %a } + define i32 @copyprop3(i32 %a, i32 %b) { ret i32 %a } + define i32 @copyprop4(i32 %a, i32 %b) { ret i32 %a } + declare i32 @foo(i32) +... +--- +# The first copy is dead copy which is not used. +# CHECK-LABEL: name: copyprop1 +# CHECK: bb.0: +# CHECK-NOT: %w20 = COPY +name: copyprop1 +body: | + bb.0: + liveins: %w0, %w1 + %w20 = COPY %w1 + BL @foo, csr_aarch64_aapcs, implicit %w0, implicit-def %w0 + RET_ReallyLR implicit %w0 +... +--- +# The first copy is not a dead copy which is used in the second copy after the +# call. +# CHECK-LABEL: name: copyprop2 +# CHECK: bb.0: +# CHECK: %w20 = COPY +name: copyprop2 +body: | + bb.0: + liveins: %w0, %w1 + %w20 = COPY %w1 + BL @foo, csr_aarch64_aapcs, implicit %w0, implicit-def %w0 + %w0 = COPY %w20 + RET_ReallyLR implicit %w0 +... +--- +# Both the first and second copy are dead copies which are not used. +# CHECK-LABEL: name: copyprop3 +# CHECK: bb.0: +# CHECK-NOT: COPY +name: copyprop3 +body: | + bb.0: + liveins: %w0, %w1 + %w20 = COPY %w1 + BL @foo, csr_aarch64_aapcs, implicit %w0, implicit-def %w0 + %w20 = COPY %w0 + RET_ReallyLR implicit %w0 +... +# The second copy is removed as a NOP copy, after then the first copy become +# dead which should be removed as well. +# CHECK-LABEL: name: copyprop3 +# CHECK: bb.0: +# CHECK-NOT: COPY +name: copyprop4 +body: | + bb.0: + liveins: %w0, %w1 + %w20 = COPY %w0 + %w0 = COPY %w20 + BL @foo, csr_aarch64_aapcs, implicit %w0, implicit-def %w0 + RET_ReallyLR implicit %w0 +... +