Index: llvm/lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -288,6 +288,9 @@ const MachineInstr &UseI, unsigned UseIdx); bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use); + bool hasOverlappingMultipleDef(const MachineInstr &MI, + const MachineOperand &MODef, + Register Def); /// Candidates for deletion. SmallSetVector MaybeDeadCopies; @@ -461,6 +464,19 @@ return false; } +bool MachineCopyPropagation::hasOverlappingMultipleDef( + const MachineInstr &MI, const MachineOperand &MODef, Register Def) { + if (MI.getDesc().getNumDefs() > 1) { + for (const MachineOperand &MIDef : MI.defs()) { + if ((&MIDef != &MODef) && MIDef.isReg() && MIDef.isDef() && + TRI->regsOverlap(Def, MIDef.getReg())) + return true; + } + } + + return false; +} + /// Look for available copies whose destination register is used by \p MI and /// replace the use in \p MI with the copy's source register. void MachineCopyPropagation::forwardUses(MachineInstr &MI) { @@ -786,6 +802,9 @@ if (hasImplicitOverlap(MI, MODef)) continue; + if (hasOverlappingMultipleDef(MI, MODef, Def)) + continue; + LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI) << "\n with " << printReg(Def, TRI) << "\n in " << MI << " from " << *Copy); Index: llvm/test/CodeGen/ARM/mcp-dest-regs-no-dup.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/mcp-dest-regs-no-dup.ll @@ -0,0 +1,51 @@ +; RUN: llc -mtriple=arm-eabi -O1 %s -verify-machineinstrs -o %t +; RUN: llvm-mc < %t -triple thumbv7 -filetype=obj -o /dev/null + +@a = hidden local_unnamed_addr global i32 0, align 4 +@b = hidden local_unnamed_addr global i32 0, align 4 +@f = hidden local_unnamed_addr global i32 0, align 4 +@c = hidden local_unnamed_addr global i32 0, align 4 +@d = hidden local_unnamed_addr global i32 0, align 4 +@e = hidden local_unnamed_addr global i32 0, align 4 +@m = hidden local_unnamed_addr global i32 0, align 4 +@g = hidden local_unnamed_addr global i32* null, align 4 + +define hidden void @h() local_unnamed_addr #0 { + call void asm sideeffect "", ""() #1 + br label %11 + +1: ; preds = %13 + call void asm sideeffect "", ""() #1 + %2 = load i32, i32* @a, align 4 + %3 = udiv i32 %2, 45 + %4 = load i32, i32* @b, align 4 + %5 = load i32, i32* @f, align 4 + %6 = icmp ult i32 %4, %5 + %7 = zext i1 %6 to i32 + %8 = icmp ule i32 %3, %7 + %9 = zext i1 %8 to i32 + %10 = icmp ult i32 %14, %9 + br i1 %10, label %18, label %11 + +11: ; preds = %0, %1 + store i32 2, i32* @f, align 4 + %12 = load i32*, i32** @g, align 4 + br label %13 + +13: ; preds = %11, %13 + %14 = load i32, i32* @c, align 4 + store i32 11, i32* @d, align 4 + store i32 0, i32* @e, align 4 + store i32 1, i32* @b, align 4 + %15 = load i32, i32* @m, align 4 + store i32 %15, i32* %12, align 4 + %16 = load i32, i32* @f, align 4 + %17 = icmp eq i32 %16, 0 + br i1 %17, label %1, label %13 + +18: ; preds = %1 + ret void +} + +attributes #0 = { "target-features"="+armv8-a,-fpregs" } +attributes #1 = { nounwind }