X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FLowerSubregs.cpp;h=7871ba9c17e493d3db4dae0ebd35633408cfb1fc;hb=86e4eeb6c79baf1c4bc4569a1e6ffc0c8f4b52b9;hp=b0348a5b753c185aeb21e888d99a4d60c93b0c25;hpb=34dcc6fadca0a1117cdbd0e9b35c991a55b6e556;p=oota-llvm.git diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp index b0348a5b753..7871ba9c17e 100644 --- a/lib/CodeGen/LowerSubregs.cpp +++ b/lib/CodeGen/LowerSubregs.cpp @@ -36,8 +36,8 @@ namespace { public: static char ID; // Pass identification, replacement for typeid - LowerSubregsInstructionPass() : MachineFunctionPass(&ID) {} - + LowerSubregsInstructionPass() : MachineFunctionPass(ID) {} + const char *getPassName() const { return "Subregister lowering instruction pass"; } @@ -53,22 +53,19 @@ namespace { bool runOnMachineFunction(MachineFunction&); private: - bool LowerExtract(MachineInstr *MI); - bool LowerInsert(MachineInstr *MI); bool LowerSubregToReg(MachineInstr *MI); + bool LowerCopy(MachineInstr *MI); void TransferDeadFlag(MachineInstr *MI, unsigned DstReg, const TargetRegisterInfo *TRI); - void TransferKillFlag(MachineInstr *MI, unsigned SrcReg, - const TargetRegisterInfo *TRI, - bool AddIfNotFound = false); + void TransferImplicitDefs(MachineInstr *MI); }; char LowerSubregsInstructionPass::ID = 0; } -FunctionPass *llvm::createLowerSubregsPass() { - return new LowerSubregsInstructionPass(); +FunctionPass *llvm::createLowerSubregsPass() { + return new LowerSubregsInstructionPass(); } /// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead, @@ -83,93 +80,36 @@ LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI, if (MII->addRegisterDead(DstReg, TRI)) break; assert(MII != MI->getParent()->begin() && - "copyRegToReg output doesn't reference destination register!"); + "copyPhysReg output doesn't reference destination register!"); } } -/// TransferKillFlag - MI is a pseudo-instruction with SrcReg killed, -/// and the lowered replacement instructions immediately precede it. -/// Mark the replacement instructions with the kill flag. +/// TransferImplicitDefs - MI is a pseudo-instruction, and the lowered +/// replacement instructions immediately precede it. Copy any implicit-def +/// operands from MI to the replacement instruction. void -LowerSubregsInstructionPass::TransferKillFlag(MachineInstr *MI, - unsigned SrcReg, - const TargetRegisterInfo *TRI, - bool AddIfNotFound) { - for (MachineBasicBlock::iterator MII = - prior(MachineBasicBlock::iterator(MI)); ; --MII) { - if (MII->addRegisterKilled(SrcReg, TRI, AddIfNotFound)) - break; - assert(MII != MI->getParent()->begin() && - "copyRegToReg output doesn't reference source register!"); +LowerSubregsInstructionPass::TransferImplicitDefs(MachineInstr *MI) { + MachineBasicBlock::iterator CopyMI = MI; + --CopyMI; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isImplicit() || MO.isUse()) + continue; + CopyMI->addOperand(MachineOperand::CreateReg(MO.getReg(), true, true)); } } -bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) { - MachineBasicBlock *MBB = MI->getParent(); - - assert(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && - MI->getOperand(1).isReg() && MI->getOperand(1).isUse() && - MI->getOperand(2).isImm() && "Malformed extract_subreg"); - - unsigned DstReg = MI->getOperand(0).getReg(); - unsigned SuperReg = MI->getOperand(1).getReg(); - unsigned SubIdx = MI->getOperand(2).getImm(); - unsigned SrcReg = TRI->getSubReg(SuperReg, SubIdx); - - assert(TargetRegisterInfo::isPhysicalRegister(SuperReg) && - "Extract supperg source must be a physical register"); - assert(TargetRegisterInfo::isPhysicalRegister(DstReg) && - "Extract destination must be in a physical register"); - assert(SrcReg && "invalid subregister index for register"); - - DEBUG(dbgs() << "subreg: CONVERTING: " << *MI); - - if (SrcReg == DstReg) { - // No need to insert an identity copy instruction. - if (MI->getOperand(1).isKill()) { - // We must make sure the super-register gets killed. Replace the - // instruction with KILL. - MI->setDesc(TII->get(TargetOpcode::KILL)); - MI->RemoveOperand(2); // SubIdx - DEBUG(dbgs() << "subreg: replace by: " << *MI); - return true; - } - - DEBUG(dbgs() << "subreg: eliminated!"); - } else { - // Insert copy - const TargetRegisterClass *TRCS = TRI->getPhysicalRegisterRegClass(DstReg); - const TargetRegisterClass *TRCD = TRI->getPhysicalRegisterRegClass(SrcReg); - bool Emitted = TII->copyRegToReg(*MBB, MI, DstReg, SrcReg, TRCD, TRCS, - MI->getDebugLoc()); - (void)Emitted; - assert(Emitted && "Subreg and Dst must be of compatible register class"); - // Transfer the kill/dead flags, if needed. - if (MI->getOperand(0).isDead()) - TransferDeadFlag(MI, DstReg, TRI); - if (MI->getOperand(1).isKill()) - TransferKillFlag(MI, SuperReg, TRI, true); - DEBUG({ - MachineBasicBlock::iterator dMI = MI; - dbgs() << "subreg: " << *(--dMI); - }); - } - - DEBUG(dbgs() << '\n'); - MBB->erase(MI); - return true; -} - bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { MachineBasicBlock *MBB = MI->getParent(); assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && MI->getOperand(1).isImm() && (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) && MI->getOperand(3).isImm() && "Invalid subreg_to_reg"); - + unsigned DstReg = MI->getOperand(0).getReg(); unsigned InsReg = MI->getOperand(2).getReg(); - unsigned InsSIdx = MI->getOperand(2).getSubReg(); + assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?"); unsigned SubIdx = MI->getOperand(3).getImm(); assert(SubIdx != 0 && "Invalid index for insert_subreg"); @@ -182,27 +122,25 @@ bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { DEBUG(dbgs() << "subreg: CONVERTING: " << *MI); - if (DstSubReg == InsReg && InsSIdx == 0) { + if (DstSubReg == InsReg) { // No need to insert an identify copy instruction. // Watch out for case like this: - // %RAX = ... - // %RAX = SUBREG_TO_REG 0, %EAX:3, 3 - // The first def is defining RAX, not EAX so the top bits were not - // zero extended. + // %RAX = SUBREG_TO_REG 0, %EAX, 3 + // We must leave %RAX live. + if (DstReg != InsReg) { + MI->setDesc(TII->get(TargetOpcode::KILL)); + MI->RemoveOperand(3); // SubIdx + MI->RemoveOperand(1); // Imm + DEBUG(dbgs() << "subreg: replace by: " << *MI); + return true; + } DEBUG(dbgs() << "subreg: eliminated!"); } else { - // Insert sub-register copy - const TargetRegisterClass *TRC0= TRI->getPhysicalRegisterRegClass(DstSubReg); - const TargetRegisterClass *TRC1= TRI->getPhysicalRegisterRegClass(InsReg); - bool Emitted = TII->copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1, - MI->getDebugLoc()); - (void)Emitted; - assert(Emitted && "Subreg and Dst must be of compatible register class"); + TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg, + MI->getOperand(2).isKill()); // Transfer the kill/dead flags, if needed. if (MI->getOperand(0).isDead()) TransferDeadFlag(MI, DstSubReg, TRI); - if (MI->getOperand(2).isKill()) - TransferKillFlag(MI, InsReg, TRI); DEBUG({ MachineBasicBlock::iterator dMI = MI; dbgs() << "subreg: " << *(--dMI); @@ -214,87 +152,39 @@ bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { return true; } -bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { - MachineBasicBlock *MBB = MI->getParent(); - assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && - (MI->getOperand(1).isReg() && MI->getOperand(1).isUse()) && - (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) && - MI->getOperand(3).isImm() && "Invalid insert_subreg"); - - unsigned DstReg = MI->getOperand(0).getReg(); -#ifndef NDEBUG - unsigned SrcReg = MI->getOperand(1).getReg(); -#endif - unsigned InsReg = MI->getOperand(2).getReg(); - unsigned SubIdx = MI->getOperand(3).getImm(); - - assert(DstReg == SrcReg && "insert_subreg not a two-address instruction?"); - assert(SubIdx != 0 && "Invalid index for insert_subreg"); - unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx); - assert(DstSubReg && "invalid subregister index for register"); - assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) && - "Insert superreg source must be in a physical register"); - assert(TargetRegisterInfo::isPhysicalRegister(InsReg) && - "Inserted value must be in a physical register"); +bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) { + MachineOperand &DstMO = MI->getOperand(0); + MachineOperand &SrcMO = MI->getOperand(1); - DEBUG(dbgs() << "subreg: CONVERTING: " << *MI); - - if (DstSubReg == InsReg) { - // No need to insert an identity copy instruction. If the SrcReg was - // , we need to make sure it is alive by inserting a KILL - if (MI->getOperand(1).isUndef() && !MI->getOperand(0).isDead()) { - MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), - TII->get(TargetOpcode::KILL), DstReg); - if (MI->getOperand(2).isUndef()) - MIB.addReg(InsReg, RegState::Undef); - else - MIB.addReg(InsReg, RegState::Kill); - } else { - DEBUG(dbgs() << "subreg: eliminated!\n"); - MBB->erase(MI); + if (SrcMO.getReg() == DstMO.getReg()) { + DEBUG(dbgs() << "identity copy: " << *MI); + // No need to insert an identity copy instruction, but replace with a KILL + // if liveness is changed. + if (DstMO.isDead() || SrcMO.isUndef() || MI->getNumOperands() > 2) { + // We must make sure the super-register gets killed. Replace the + // instruction with KILL. + MI->setDesc(TII->get(TargetOpcode::KILL)); + DEBUG(dbgs() << "replaced by: " << *MI); return true; } - } else { - // Insert sub-register copy - const TargetRegisterClass *TRC0= TRI->getPhysicalRegisterRegClass(DstSubReg); - const TargetRegisterClass *TRC1= TRI->getPhysicalRegisterRegClass(InsReg); - if (MI->getOperand(2).isUndef()) - // If the source register being inserted is undef, then this becomes a - // KILL. - BuildMI(*MBB, MI, MI->getDebugLoc(), - TII->get(TargetOpcode::KILL), DstSubReg); - else { - bool Emitted = TII->copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1, - MI->getDebugLoc()); - (void)Emitted; - assert(Emitted && "Subreg and Dst must be of compatible register class"); - } - MachineBasicBlock::iterator CopyMI = MI; - --CopyMI; - - // INSERT_SUBREG is a two-address instruction so it implicitly kills SrcReg. - if (!MI->getOperand(1).isUndef()) - CopyMI->addOperand(MachineOperand::CreateReg(DstReg, false, true, true)); - - // Transfer the kill/dead flags, if needed. - if (MI->getOperand(0).isDead()) { - TransferDeadFlag(MI, DstSubReg, TRI); - } else { - // Make sure the full DstReg is live after this replacement. - CopyMI->addOperand(MachineOperand::CreateReg(DstReg, true, true)); - } - - // Make sure the inserted register gets killed - if (MI->getOperand(2).isKill() && !MI->getOperand(2).isUndef()) - TransferKillFlag(MI, InsReg, TRI); + // Vanilla identity copy. + MI->eraseFromParent(); + return true; } - DEBUG({ - MachineBasicBlock::iterator dMI = MI; - dbgs() << "subreg: " << *(--dMI) << "\n"; - }); + DEBUG(dbgs() << "real copy: " << *MI); + TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(), + DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill()); - MBB->erase(MI); + if (DstMO.isDead()) + TransferDeadFlag(MI, DstMO.getReg(), TRI); + if (MI->getNumOperands() > 2) + TransferImplicitDefs(MI); + DEBUG({ + MachineBasicBlock::iterator dMI = MI; + dbgs() << "replaced by: " << *(--dMI); + }); + MI->eraseFromParent(); return true; } @@ -302,9 +192,9 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { /// copies. /// bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { - DEBUG(dbgs() << "Machine Function\n" + DEBUG(dbgs() << "Machine Function\n" << "********** LOWERING SUBREG INSTRS **********\n" - << "********** Function: " + << "********** Function: " << MF.getFunction()->getName() << '\n'); TRI = MF.getTarget().getRegisterInfo(); TII = MF.getTarget().getInstrInfo(); @@ -317,12 +207,13 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { mi != me;) { MachineBasicBlock::iterator nmi = llvm::next(mi); MachineInstr *MI = mi; - if (MI->isExtractSubreg()) { - MadeChange |= LowerExtract(MI); - } else if (MI->isInsertSubreg()) { - MadeChange |= LowerInsert(MI); - } else if (MI->isSubregToReg()) { + assert(!MI->isInsertSubreg() && "INSERT_SUBREG should no longer appear"); + assert(MI->getOpcode() != TargetOpcode::EXTRACT_SUBREG && + "EXTRACT_SUBREG should no longer appear"); + if (MI->isSubregToReg()) { MadeChange |= LowerSubregToReg(MI); + } else if (MI->isCopy()) { + MadeChange |= LowerCopy(MI); } mi = nmi; }