Index: lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- lib/CodeGen/MachineCopyPropagation.cpp +++ lib/CodeGen/MachineCopyPropagation.cpp @@ -52,6 +52,7 @@ void SourceNoLongerAvailable(unsigned Reg); void CopyPropagateBlock(MachineBasicBlock &MBB); + bool eraseRedundantCopy(MachineInstr *MI, unsigned Src, unsigned Def); /// Candidates for deletion. SmallSetVector MaybeDeadCopies; @@ -137,6 +138,31 @@ return false; } +bool MachineCopyPropagation::eraseRedundantCopy(MachineInstr *MI, + unsigned Src, unsigned Def) { + Reg2MIMap::iterator CI = AvailCopyMap.find(Src); + if (CI != AvailCopyMap.end()) { + MachineInstr *CopyMI = CI->second; + if (!MRI->isReserved(Def) && isNopCopy(CopyMI, Def, Src, TRI) && + (!MRI->isReserved(Src) || + NoInterveningSideEffect(CopyMI, MI, Src))) { + DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; MI->dump()); + + // Clear any kills of Def between CopyMI and MI. This extends the + // live range. + for (MachineInstr &MMI + : make_range(CopyMI->getIterator(), MI->getIterator())) + MMI.clearRegisterKills(Def, TRI); + + MI->eraseFromParent(); + Changed = true; + ++NumDeletes; + return true; + } + } + return false; +} + void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) { DEBUG(dbgs() << "MCP: CopyPropagateBlock " << MBB.getName() << "\n"); @@ -152,40 +178,36 @@ !TargetRegisterInfo::isVirtualRegister(Src) && "MachineCopyPropagation should be run after register allocation!"); - DenseMap::iterator CI = AvailCopyMap.find(Src); - if (CI != AvailCopyMap.end()) { - MachineInstr *CopyMI = CI->second; - if (!MRI->isReserved(Def) && isNopCopy(CopyMI, Def, Src, TRI) && - (!MRI->isReserved(Src) || - NoInterveningSideEffect(CopyMI, MI, Src))) { - // The two copies cancel out and the source of the first copy - // hasn't been overridden, eliminate the second one. e.g. - // %ECX = COPY %EAX - // ... nothing clobbered EAX. - // %EAX = COPY %ECX - // => - // %ECX = COPY %EAX - // - // Also avoid eliminating a copy from reserved registers unless the - // definition is proven not clobbered. e.g. - // %RSP = COPY %RAX - // CALL - // %RAX = COPY %RSP - - DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; MI->dump()); - - // Clear any kills of Def between CopyMI and MI. This extends the - // live range. - for (MachineInstr &MMI - : make_range(CopyMI->getIterator(), MI->getIterator())) - MMI.clearRegisterKills(Def, TRI); - - MI->eraseFromParent(); - Changed = true; - ++NumDeletes; - continue; - } - } + // The two copies cancel out and the source of the first copy + // hasn't been overridden, eliminate the second one. e.g. + // %ECX = COPY %EAX + // ... nothing clobbered EAX. + // %EAX = COPY %ECX + // => + // %ECX = COPY %EAX + // + // Also avoid eliminating a copy from reserved registers unless the + // definition is proven not clobbered. e.g. + // %RSP = COPY %RAX + // CALL + // %RAX = COPY %RSP + if (eraseRedundantCopy(MI, Src, Def)) + continue; + // The two copies cancel out and the source of the first copy + // hasn't been overridden, eliminate the second one. e.g. + // %ECX = COPY %EAX + // ... nothing clobbered EAX. + // %EAX = COPY %ECX + // => + // %ECX = COPY %EAX + // + // Also avoid eliminating a copy from reserved registers unless the + // definition is proven not clobbered. e.g. + // %RSP = COPY %RAX + // CALL + // %RAX = COPY %RSP + if (eraseRedundantCopy(MI, Def, Src)) + continue; // If Src is defined by a previous copy, the previous copy cannot be // eliminated. Index: test/CodeGen/X86/machine-copy-prop.mir =================================================================== --- test/CodeGen/X86/machine-copy-prop.mir +++ test/CodeGen/X86/machine-copy-prop.mir @@ -2,7 +2,22 @@ --- | declare preserve_mostcc void @foo() + define void @copyprop0() { ret void } define void @copyprop1() { ret void } + define void @copyprop2() { ret void } +... +--- +# CHECK-LABEL: name: copyprop0 +# CHECK: bb.0: +# CHECK-NEXT: %rax = COPY %rdi +# CHECK-NOT: %rax = COPY %rdi +# CHECK-NEXT: NOOP implicit %rax, implicit %rdi +name: copyprop0 +body: | + bb.0: + %rax = COPY %rdi + %rax = COPY %rdi + NOOP implicit %rax, implicit %rdi ... --- # CHECK-LABEL: name: copyprop1 @@ -19,3 +34,18 @@ %rdi = COPY %rax NOOP implicit %rax, implicit %rdi ... +--- +# CHECK-LABEL: name: copyprop2 +# CHECK: bb.0: +# CHECK-NEXT: %rax = COPY %rdi +# CHECK-NEXT: CALL64pcrel32 @foo, csr_64_rt_mostregs, implicit %rsp, implicit-def %rsp +# CHECK-NOT: %rax = COPY %rdi +# CHECK-NEXT: NOOP implicit %rax, implicit %rdi +name: copyprop2 +body: | + bb.0: + %rax = COPY %rdi + CALL64pcrel32 @foo, csr_64_rt_mostregs, implicit %rsp, implicit-def %rsp + %rax = COPY %rdi + NOOP implicit %rax, implicit %rdi +...