diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -1517,6 +1517,10 @@ /// instruction to this instruction. void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI); + /// Union implicit register operands from specified + /// instruction to this instruction. + void unionImplicitOps(MachineFunction &MF, const MachineInstr &MI); + /// Debugging support /// @{ /// Determine the generic type to be printed (if needed) on uses and defs. diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -305,6 +305,13 @@ return *this; } + /// Union all the implicit operands from OtherMI onto this one. + const MachineInstrBuilder & + unionImplicitOps(const MachineInstr &OtherMI) const { + MI->unionImplicitOps(*MF, OtherMI); + return *this; + } + bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const { diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -1426,6 +1427,31 @@ } } +/// unionImplicitOps - Union implicit register operands from specified +/// instruction to this instruction. The instruction shouldn't have RegMask +/// operand. +void MachineInstr::unionImplicitOps(MachineFunction &MF, + const MachineInstr &MI) { + SmallSet ImpRegSet; + for (unsigned i = getDesc().getNumOperands(), e = getNumOperands(); + i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (MO.isReg() && MO.isImplicit()) + ImpRegSet.insert(MO.getReg()); + + assert(!MO.isRegMask() && "Don't support union for RegMask operand"); + } + + for (unsigned i = MI.getDesc().getNumOperands(), e = MI.getNumOperands(); + i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (MO.isReg() && MO.isImplicit() && !ImpRegSet.count(MO.getReg())) + addOperand(MF, MO); + + assert(!MO.isRegMask() && "Don't support union for RegMask operand"); + } +} + bool MachineInstr::hasComplexRegisterTies() const { const MCInstrDesc &MCID = getDesc(); for (unsigned I = 0, E = getNumOperands(); I < E; ++I) { diff --git a/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp b/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp --- a/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp +++ b/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp @@ -78,7 +78,7 @@ // This is an unconditional branch to the return. Replace the // branch with a blr. BuildMI(**PI, J, J->getDebugLoc(), TII->get(I->getOpcode())) - .copyImplicitOps(*I); + .unionImplicitOps(*I); MachineBasicBlock::iterator K = J--; K->eraseFromParent(); BlockChanged = true; @@ -92,7 +92,7 @@ BuildMI(**PI, J, J->getDebugLoc(), TII->get(PPC::BCCLR)) .addImm(J->getOperand(0).getImm()) .addReg(J->getOperand(1).getReg()) - .copyImplicitOps(*I); + .unionImplicitOps(*I); MachineBasicBlock::iterator K = J--; K->eraseFromParent(); BlockChanged = true; @@ -107,7 +107,7 @@ **PI, J, J->getDebugLoc(), TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn)) .addReg(J->getOperand(0).getReg()) - .copyImplicitOps(*I); + .unionImplicitOps(*I); MachineBasicBlock::iterator K = J--; K->eraseFromParent(); BlockChanged = true; diff --git a/llvm/test/CodeGen/PowerPC/early-ret-verify.mir b/llvm/test/CodeGen/PowerPC/early-ret-verify.mir --- a/llvm/test/CodeGen/PowerPC/early-ret-verify.mir +++ b/llvm/test/CodeGen/PowerPC/early-ret-verify.mir @@ -40,7 +40,7 @@ ; CHECK-LABEL: testEarlyRet ; CHECK: bb.0.entry: - ; CHECK: BCLR $cr5lt, implicit $lr, implicit $rm, implicit $lr, implicit $rm + ; CHECK: BCLR $cr5lt, implicit $lr, implicit $rm ; CHECK: bb.1: ; CHECK: renamable $r3 = IMPLICIT_DEF ; CHECK: renamable $r4 = IMPLICIT_DEF diff --git a/llvm/test/CodeGen/PowerPC/early-ret.mir b/llvm/test/CodeGen/PowerPC/early-ret.mir --- a/llvm/test/CodeGen/PowerPC/early-ret.mir +++ b/llvm/test/CodeGen/PowerPC/early-ret.mir @@ -27,7 +27,7 @@ ; CHECK: bb.0.entry: ; CHECK: renamable $cr0 = CMPWI renamable $r3, 0 ; CHECK: BC killed renamable $cr0gt, %bb.1 - ; CHECK: BLR implicit $lr, implicit $rm, implicit $lr, implicit $rm, implicit killed $r3 + ; CHECK: BLR implicit $lr, implicit $rm, implicit killed $r3 ; CHECK: bb.1.entry: ; CHECK: renamable $r3 = ADDI killed renamable $r4, 0 ; CHECK: BLR implicit $lr, implicit $rm, implicit killed $r3 @@ -106,7 +106,7 @@ ; CHECK-LABEL: name: testBCLR ; CHECK: bb.0.entry: ; CHECK: renamable $cr0 = FCMPUS killed renamable $f3, killed renamable $f4 - ; CHECK: BCLR $cr0eq, implicit $lr, implicit $rm, implicit $lr, implicit $rm, implicit killed $v2 + ; CHECK: BCLR $cr0eq, implicit $lr, implicit $rm, implicit killed $v2 ; CHECK: bb.1.entry: ; CHECK: renamable $cr0 = FCMPUS killed renamable $f1, killed renamable $f2 ; CHECK: BCLRn killed renamable $cr0eq, implicit $lr, implicit $rm, implicit killed $v2 @@ -139,8 +139,8 @@ ; CHECK: bb.0.entry: ; CHECK: renamable $r4 = LI 0 ; CHECK: renamable $cr0 = CMPLWI killed renamable $r4, 0 - ; CHECK: BCCLR 68, $cr0, implicit $lr, implicit $rm, implicit $lr, implicit $rm + ; CHECK: BCCLR 68, $cr0, implicit $lr, implicit $rm ; CHECK: bb.1: - ; CHECK: BCCLR 68, $cr0, implicit $lr, implicit $rm, implicit $lr, implicit $rm + ; CHECK: BCCLR 68, $cr0, implicit $lr, implicit $rm ; CHECK: BLR implicit $lr, implicit $rm ...