public:
static char ID; // Pass identification, replacement for typeid
- LowerSubregsInstructionPass() : MachineFunctionPass(&ID) {}
+ LowerSubregsInstructionPass() : MachineFunctionPass(ID) {}
const char *getPassName() const {
return "Subregister lowering instruction pass";
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;
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!");
}
}
if (MII->addRegisterKilled(SrcReg, TRI, AddIfNotFound))
break;
assert(MII != MI->getParent()->begin() &&
- "copyRegToReg output doesn't reference source register!");
+ "copyPhysReg output doesn't reference source register!");
}
}
-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(TargetInstrInfo::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);
- (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);
- });
+/// 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::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));
}
-
- DEBUG(dbgs() << '\n');
- MBB->erase(MI);
- return true;
}
bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) {
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");
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<def> = ...
- // %RAX<def> = SUBREG_TO_REG 0, %EAX:3<kill>, 3
- // The first def is defining RAX, not EAX so the top bits were not
- // zero extended.
+ // %RAX<def> = SUBREG_TO_REG 0, %EAX<kill>, 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);
- (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);
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");
-
- DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
+bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) {
+ MachineOperand &DstMO = MI->getOperand(0);
+ MachineOperand &SrcMO = MI->getOperand(1);
- if (DstSubReg == InsReg) {
- // No need to insert an identity copy instruction. If the SrcReg was
- // <undef>, 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(TargetInstrInfo::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(TargetInstrInfo::KILL), DstSubReg);
- else {
- bool Emitted = TII->copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1);
- (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;
}
mi != me;) {
MachineBasicBlock::iterator nmi = llvm::next(mi);
MachineInstr *MI = mi;
- if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) {
- MadeChange |= LowerExtract(MI);
- } else if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) {
- MadeChange |= LowerInsert(MI);
- } else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) {
+ 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;
}