diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp --- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -288,6 +288,8 @@ 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 +463,17 @@ return false; } +bool MachineCopyPropagation::hasOverlappingMultipleDef( + const MachineInstr &MI, const MachineOperand &MODef, Register Def) { + for (const MachineOperand &MIDef : MI.defs()) { + if ((&MIDef != &MODef) && MIDef.isReg() && + 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 +799,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); diff --git a/llvm/test/CodeGen/ARM/mcp-dest-regs-no-dup.mir b/llvm/test/CodeGen/ARM/mcp-dest-regs-no-dup.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/mcp-dest-regs-no-dup.mir @@ -0,0 +1,131 @@ +# RUN: llc -mtriple=arm-eabi -O1 -run-pass=machine-cp %s -o - 2>&1 | FileCheck %s +--- | + @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 = %1, %0 + store i32 2, i32* @f, align 4 + %12 = load i32*, i32** @g, align 4 + br label %13 + + 13: ; preds = %13, %11 + %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 + } + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #1 + + attributes #0 = { "target-features"="+armv8-a,-fpregs" } + attributes #1 = { nounwind } + +... +--- +name: h +alignment: 4 +tracksRegLiveness: true +frameInfo: + maxAlignment: 1 + maxCallFrameSize: 0 +machineFunctionInfo: {} +body: | + bb.0 (%ir-block.0): + INLINEASM &"", 1 /* sideeffect attdialect */ + renamable $r10 = MOVi32imm @f + renamable $r8 = MOVi32imm @d + renamable $r11 = MOVi 11, 14 /* CC::al */, $noreg, $noreg + renamable $r2 = MOVi32imm @e + renamable $r4 = MOVi 0, 14 /* CC::al */, $noreg, $noreg + renamable $r5 = MOVi32imm @b + renamable $r6 = MOVi 1, 14 /* CC::al */, $noreg, $noreg + renamable $r7 = MOVi32imm @c + renamable $r3 = MOVi32imm @m + B %bb.2 + + bb.1 (%ir-block.1): + successors: %bb.4(0x04000000), %bb.2(0x7c000000) + liveins: $r1, $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r10, $r11 + + INLINEASM &"", 1 /* sideeffect attdialect */ + renamable $r12 = LDRi12 renamable $r10, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @f) + renamable $lr = LDRi12 renamable $r5, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @b) + CMPrr killed renamable $lr, killed renamable $r12, 14 /* CC::al */, $noreg, implicit-def $cpsr + renamable $r12 = MOVi 0, 14 /* CC::al */, $noreg, $noreg + renamable $r12 = MOVCCi16 killed renamable $r12, 1, 3 /* CC::lo */, killed $cpsr + renamable $r0 = MOVi32imm @a + renamable $lr = LDRi12 killed renamable $r0, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @a) + renamable $r0 = MOVi32imm 1813430637 + dead renamable $r9, renamable $r0 = UMULL renamable $lr, killed renamable $r0, 14 /* CC::al */, $noreg, $noreg + renamable $r9 = COPY killed renamable $r0 + renamable $r0 = SUBrr killed renamable $lr, renamable $r9, 14 /* CC::al */, $noreg, $noreg + renamable $r0 = ADDrsi killed renamable $r9, killed renamable $r0, 11, 14 /* CC::al */, $noreg, $noreg + CMPrsi killed renamable $r12, killed renamable $r0, 43, 14 /* CC::al */, $noreg, implicit-def $cpsr + renamable $r0 = MOVi 0, 14 /* CC::al */, $noreg, $noreg + renamable $r0 = MOVCCi16 killed renamable $r0, 1, 2 /* CC::hs */, killed $cpsr + CMPrr killed renamable $r1, killed renamable $r0, 14 /* CC::al */, $noreg, implicit-def $cpsr + Bcc %bb.4, 3 /* CC::lo */, killed $cpsr + B %bb.2 + + bb.2 (%ir-block.11): + liveins: $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r10, $r11 + + renamable $r0 = MOVi 2, 14 /* CC::al */, $noreg, $noreg + STRi12 killed renamable $r0, renamable $r10, 0, 14 /* CC::al */, $noreg :: (store 4 into @f) + renamable $r0 = MOVi32imm @g + renamable $r12 = LDRi12 killed renamable $r0, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @g) + + bb.3 (%ir-block.13): + successors: %bb.1(0x04000000), %bb.3(0x7c000000) + liveins: $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r10, $r11, $r12 + + STRi12 renamable $r11, renamable $r8, 0, 14 /* CC::al */, $noreg :: (store 4 into @d) + STRi12 renamable $r4, renamable $r2, 0, 14 /* CC::al */, $noreg :: (store 4 into @e) + STRi12 renamable $r6, renamable $r5, 0, 14 /* CC::al */, $noreg :: (store 4 into @b) + renamable $r1 = LDRi12 renamable $r7, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @c) + renamable $r0 = LDRi12 renamable $r3, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @m) + STRi12 killed renamable $r0, renamable $r12, 0, 14 /* CC::al */, $noreg :: (store 4 into %ir.12) + renamable $r0 = LDRi12 renamable $r10, 0, 14 /* CC::al */, $noreg :: (dereferenceable load 4 from @f) + CMPri killed renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr + Bcc %bb.1, 0 /* CC::eq */, killed $cpsr + B %bb.3 + + bb.4 (%ir-block.18): + BX_RET 14 /* CC::al */, $noreg + + ; CHECK: dead renamable $[[REGISTER:lr|r[0-9]+]], renamable $ + ; CHECK-NOT: [[REGISTER]] + ; CHECK: = UMULL +...