diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -572,6 +572,19 @@ /// analysis post-RA, \p StartMI and \p EndMI are hard to keep right. void fixupIsDeadOrKill(MachineInstr &StartMI, MachineInstr &EndMI, unsigned RegNo) const; + + /// Set the killed/dead flag when folding \p DefMI and \p MI for SSA. + /// \p ForwardingMO is the forwarding operand used in MI, \p ForwardedMO is + /// the forwarded operand used in \p DefMI, its Reg is used by MI after the + /// folding. Before the folding, \p ForwardingMOHasOneUse is show that whether + /// the forwarding operand has only one use, \p ForwardingKilledOperandReg is + /// show that whether the forwarding operand has the killed flag. + void setKillAfterFolding(MachineInstr &MI, MachineInstr &DefMI, + MachineOperand &ForwardingMO, + MachineOperand &ForwardedMO, + bool ForwardingMOHasOneUse, + unsigned ForwardingKilledOperandReg = ~0U) const; + void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const; void replaceInstrOperandWithImm(MachineInstr &MI, unsigned OpNo, int64_t Imm) const; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -2726,6 +2726,70 @@ "RegNo should be killed or dead"); } +void PPCInstrInfo::setKillAfterFolding( + MachineInstr &MI, MachineInstr &DefMI, + MachineOperand &ForwardingMO, MachineOperand &ForwardedMO, + bool ForwardingMOHasOneUse, + unsigned ForwardingKilledOperandReg) const { + MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); + assert(MRI.isSSA() && "Only used for SSA form."); + + if (!ForwardingMOHasOneUse && !ForwardingMO.isKill()) { + // FIXME: Set the kill/dead flag if ForwardingMO has more than one use and + // not the last use before the folding. Below is an example: + // + // bb1: + // %2:g8rc = RLDICL killed %1, 0, 32 + // %3:g8rc = RLDICR %2, 2, 61 + // bb2: + // %4:g8rc = RLDICR %2, 2, 61 + ForwardedMO.setIsKill(false); + } else if (DefMI.getParent() == MI.getParent()) { + // Check if reg is killed between MI and DefMI. + auto IsKilledFor = [&](unsigned Reg) { + MachineBasicBlock::const_reverse_iterator It = MI; + MachineBasicBlock::const_reverse_iterator E = DefMI; + It++; + for (; It != E; ++It) { + if (It->killsRegister(Reg)) + return true; + } + return false; + }; + + // Update kill flag + if (ForwardedMO.isKill() || IsKilledFor(ForwardedMO.getReg())) { + // For below example, we call fixupIsDeadOrKill() to move the killed %1 + // from STORE to RLDIC after folding. + // + // %2:g8rc = RLDICL %1, 0, 32 | %2:g8rc = RLDICL %1, 0, 32 + // STORE killed %1 ==> | STORE %1 + // %3:g8rc = RLDICR %2, 2, 61 | %3:g8rc = RLDIC killed %1, 2, 30 + fixupIsDeadOrKill(DefMI, MI, ForwardedMO.getReg()); + } if (ForwardingKilledOperandReg != ~0U) { + // For below example, we call fixupIsDeadOrKill() to move the killed %2 + // from RLDICR to STORE and killed %1 from RLDICL to RLDIC after folding. + // + // %2:g8rc = RLDICL killed %1, 0, 32 | %2:g8rc = RLDICL %1, 0, 32 + // STORE %2 ==> | STORE killed %2 + // %3:g8rc = RLDICR killed %2, 2, 61 | %3:g8rc = RLDIC killed %1, 2, 30 + fixupIsDeadOrKill(DefMI, MI, ForwardingKilledOperandReg); + } + } else if (DefMI.getOperand(1).isKill()) { + // FIXME: If MI and DefMI are not in same basic block. we should based on + // the CFG to set kill/dead flag. For below example, %3 is in a loop, but + // %2 is out of the loop. + // + // bb1: + // %2:g8rc = RLDICL killed %1, 0, 32 + // bb2: + // %3:g8rc = RLDICR %2, 2, 61 + // ... + // BCC 4, $cr0, %bb.2 + DefMI.getOperand(1).setIsKill(false); + } +} + // This opt tries to convert the following imm form to an index form to save an // add for stack variables. // Return false if no such pattern found. @@ -3921,30 +3985,15 @@ LLVM_DEBUG(dbgs() << "Fed by:\n"); LLVM_DEBUG(DefMI.dump()); + bool HasOneUse = + MRI->hasOneUse(MI.getOperand(III.OpNoForForwarding).getReg()); + + // The default kill flag for MI.getOperand(III.OpNoForForwarding) is false. MI.getOperand(III.OpNoForForwarding).setReg(RegMO->getReg()); - MI.getOperand(III.OpNoForForwarding).setIsKill(RegMO->isKill()); MI.getOperand(III.ImmOpNo).setImm(Imm); - // FIXME: fix kill/dead flag if MI and DefMI are not in same basic block. - if (DefMI.getParent() == MI.getParent()) { - // Check if reg is killed between MI and DefMI. - auto IsKilledFor = [&](unsigned Reg) { - MachineBasicBlock::const_reverse_iterator It = MI; - MachineBasicBlock::const_reverse_iterator E = DefMI; - It++; - for (; It != E; ++It) { - if (It->killsRegister(Reg)) - return true; - } - return false; - }; - - // Update kill flag - if (RegMO->isKill() || IsKilledFor(RegMO->getReg())) - fixupIsDeadOrKill(DefMI, MI, RegMO->getReg()); - if (ForwardKilledOperandReg != ~0U) - fixupIsDeadOrKill(DefMI, MI, ForwardKilledOperandReg); - } + setKillAfterFolding(MI, DefMI, MI.getOperand(III.OpNoForForwarding), *RegMO, + HasOneUse, ForwardKilledOperandReg); LLVM_DEBUG(dbgs() << "With:\n"); LLVM_DEBUG(MI.dump()); diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp --- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -934,13 +934,17 @@ MI.RemoveOperand(3); MI.getOperand(2).setImm(0); MI.setDesc(TII->get(Is64Bit ? PPC::ANDI8_rec : PPC::ANDI_rec)); + + // Get killed info in case fixup needed after transformation. + unsigned ForwardKilledOperandReg = ~0U; + if (MI.getOperand(1).isKill()) + ForwardKilledOperandReg = MI.getOperand(1).getReg(); + bool HasOneUse = MRI->hasOneUse(MI.getOperand(1).getReg()); + MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); - if (SrcMI->getOperand(1).isKill()) { - MI.getOperand(1).setIsKill(true); - SrcMI->getOperand(1).setIsKill(false); - } else - // About to replace MI.getOperand(1), clear its kill flag. - MI.getOperand(1).setIsKill(false); + TII->setKillAfterFolding(MI, *SrcMI, MI.getOperand(1), + SrcMI->getOperand(1), HasOneUse, + ForwardKilledOperandReg); } LLVM_DEBUG(dbgs() << "With: "); @@ -962,13 +966,17 @@ MI.getOperand(3).setImm(NewMB); MI.getOperand(4).setImm(NewME); } + + // Get killed info in case fixup needed after transformation. + unsigned ForwardKilledOperandReg = ~0U; + if (MI.getOperand(1).isKill()) + ForwardKilledOperandReg = MI.getOperand(1).getReg(); + bool HasOneUse = MRI->hasOneUse(MI.getOperand(1).getReg()); + MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); - if (SrcMI->getOperand(1).isKill()) { - MI.getOperand(1).setIsKill(true); - SrcMI->getOperand(1).setIsKill(false); - } else - // About to replace MI.getOperand(1), clear its kill flag. - MI.getOperand(1).setIsKill(false); + TII->setKillAfterFolding(MI, *SrcMI, MI.getOperand(1), + SrcMI->getOperand(1), HasOneUse, + ForwardKilledOperandReg); LLVM_DEBUG(dbgs() << "To: "); LLVM_DEBUG(MI.dump()); @@ -1547,15 +1555,28 @@ if ((63 - NewSH) != MEMI) return false; + // Get killed info in case fixup needed after transformation. + unsigned ForwardKilledOperandReg = ~0U; + if (MI.getOperand(1).isKill()) + ForwardKilledOperandReg = MI.getOperand(1).getReg(); + + LLVM_DEBUG(dbgs() << "Converting pair: "); LLVM_DEBUG(SrcMI->dump()); LLVM_DEBUG(MI.dump()); + bool HasOneUse = MRI->hasOneUse(MI.getOperand(1).getReg()); + MI.setDesc(TII->get(PPC::RLDIC)); + + // The default kill flag for MI.getOperand(1) is false. MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); MI.getOperand(2).setImm(NewSH); MI.getOperand(3).setImm(NewMB); + TII->setKillAfterFolding(MI, *SrcMI, MI.getOperand(1), SrcMI->getOperand(1), + HasOneUse, ForwardKilledOperandReg); + LLVM_DEBUG(dbgs() << "To: "); LLVM_DEBUG(MI.dump()); NumRotatesCollapsed++; diff --git a/llvm/test/CodeGen/PowerPC/jump-tables-collapse-rotate-remove-SrcMI.mir b/llvm/test/CodeGen/PowerPC/jump-tables-collapse-rotate-remove-SrcMI.mir --- a/llvm/test/CodeGen/PowerPC/jump-tables-collapse-rotate-remove-SrcMI.mir +++ b/llvm/test/CodeGen/PowerPC/jump-tables-collapse-rotate-remove-SrcMI.mir @@ -51,4 +51,4 @@ # # CHECK-PASS-NOT: %2:g8rc = RLDICL killed %1, 0, 32 # CHECK-PASS-NOT: %3:g8rc = RLDICR %2, 2, 61 -# CHECK-PASS: %3:g8rc = RLDIC %1, 2, 30 +# CHECK-PASS: %3:g8rc = RLDIC killed %1, 2, 30 diff --git a/llvm/test/CodeGen/PowerPC/mi-peephole-kill.mir b/llvm/test/CodeGen/PowerPC/mi-peephole-kill.mir --- a/llvm/test/CodeGen/PowerPC/mi-peephole-kill.mir +++ b/llvm/test/CodeGen/PowerPC/mi-peephole-kill.mir @@ -154,7 +154,7 @@ ; CHECK: %4:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @global ; CHECK: %5:g8rc = ADDItocL killed %4, @global ; CHECK: %6:g8rc_and_g8rc_nox0 = ADD8 killed %5, killed %3 - ; CHECK: %0:g8rc_and_g8rc_nox0 = ADDI8 killed %6, 40 + ; CHECK: %0:g8rc_and_g8rc_nox0 = ADDI8 %6, 40 ; CHECK: %7:g8rc_and_g8rc_nox0 = RLDICL %0, 61, 3 ; CHECK: %8:g8rc = LI8 1 ; CHECK: %9:g8rc = RLDICR killed %8, 44, 19 @@ -181,8 +181,8 @@ ; CHECK: ADJCALLSTACKUP 32, 0, implicit-def dead $r1, implicit $r1 ; CHECK: bb.3 (%ir-block.19): - ; CHECK: %16:gprc_and_gprc_nor0 = LWZ 40, killed %6 :: (load 4 from %ir.20) + ; CHECK: %16:gprc_and_gprc_nor0 = LWZ 40, %6 :: (load 4 from %ir.20) ; CHECK: %17:gprc = nsw ADDI killed %16, 1 - ; CHECK: STW killed %17, 40, killed %6 :: (store 4 into %ir.20) + ; CHECK: STW killed %17, 40, %6 :: (store 4 into %ir.20) ; CHECK: BLR8 implicit $lr8, implicit $rm ... diff --git a/llvm/test/CodeGen/PowerPC/mi-peephole.mir b/llvm/test/CodeGen/PowerPC/mi-peephole.mir --- a/llvm/test/CodeGen/PowerPC/mi-peephole.mir +++ b/llvm/test/CodeGen/PowerPC/mi-peephole.mir @@ -31,7 +31,7 @@ ; CHECK: bb.0.entry: ; CHECK: %1:g8rc = COPY $x4 ; CHECK: %0:g8rc = COPY $x3 - ; CHECK: %3:g8rc = RLDIC %1, 2, 30 + ; CHECK: %3:g8rc = RLDIC killed %1, 2, 30 ; CHECK: $x3 = COPY %3 ; CHECK: BLR8 implicit $lr8, implicit $rm, implicit $x3 ...