TwoAddressInstructionPass.cpp [plain text]
#define DEBUG_TYPE "twoaddrinstr"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions");
STATISTIC(NumCommuted , "Number of instructions commuted to coalesce");
STATISTIC(NumAggrCommuted , "Number of instructions aggressively commuted");
STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address");
STATISTIC(Num3AddrSunk, "Number of 3-address instructions sunk");
STATISTIC(NumReMats, "Number of instructions re-materialized");
STATISTIC(NumDeletes, "Number of dead instructions deleted");
namespace {
class VISIBILITY_HIDDEN TwoAddressInstructionPass
: public MachineFunctionPass {
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
MachineRegisterInfo *MRI;
LiveVariables *LV;
DenseMap<MachineInstr*, unsigned> DistanceMap;
DenseMap<unsigned, unsigned> SrcRegMap;
DenseMap<unsigned, unsigned> DstRegMap;
bool Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI,
unsigned Reg,
MachineBasicBlock::iterator OldPos);
bool isProfitableToReMat(unsigned Reg, const TargetRegisterClass *RC,
MachineInstr *MI, MachineInstr *DefMI,
MachineBasicBlock *MBB, unsigned Loc);
bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist,
unsigned &LastDef);
MachineInstr *FindLastUseInMBB(unsigned Reg, MachineBasicBlock *MBB,
unsigned Dist);
bool isProfitableToCommute(unsigned regB, unsigned regC,
MachineInstr *MI, MachineBasicBlock *MBB,
unsigned Dist);
bool CommuteInstruction(MachineBasicBlock::iterator &mi,
MachineFunction::iterator &mbbi,
unsigned RegB, unsigned RegC, unsigned Dist);
bool isProfitableToConv3Addr(unsigned RegA);
bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi,
MachineBasicBlock::iterator &nmi,
MachineFunction::iterator &mbbi,
unsigned RegB, unsigned Dist);
void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB,
SmallPtrSet<MachineInstr*, 8> &Processed);
public:
static char ID; TwoAddressInstructionPass() : MachineFunctionPass(&ID) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addPreserved<LiveVariables>();
AU.addPreservedID(MachineLoopInfoID);
AU.addPreservedID(MachineDominatorsID);
if (StrongPHIElim)
AU.addPreservedID(StrongPHIEliminationID);
else
AU.addPreservedID(PHIEliminationID);
MachineFunctionPass::getAnalysisUsage(AU);
}
bool runOnMachineFunction(MachineFunction&);
};
}
char TwoAddressInstructionPass::ID = 0;
static RegisterPass<TwoAddressInstructionPass>
X("twoaddressinstruction", "Two-Address instruction pass");
const PassInfo *const llvm::TwoAddressInstructionPassID = &X;
bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB,
MachineInstr *MI, unsigned SavedReg,
MachineBasicBlock::iterator OldPos) {
bool SeenStore = true; if (!MI->isSafeToMove(TII, SeenStore))
return false;
unsigned DefReg = 0;
SmallSet<unsigned, 4> UseRegs;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg())
continue;
unsigned MOReg = MO.getReg();
if (!MOReg)
continue;
if (MO.isUse() && MOReg != SavedReg)
UseRegs.insert(MO.getReg());
if (!MO.isDef())
continue;
if (MO.isImplicit())
return false;
if (DefReg)
return false;
DefReg = MO.getReg();
}
MachineInstr *KillMI = NULL;
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SavedReg),
UE = MRI->use_end(); UI != UE; ++UI) {
MachineOperand &UseMO = UI.getOperand();
if (!UseMO.isKill())
continue;
KillMI = UseMO.getParent();
break;
}
if (!KillMI || KillMI->getParent() != MBB || KillMI == MI)
return false;
MachineOperand *KillMO = NULL;
MachineBasicBlock::iterator KillPos = KillMI;
++KillPos;
unsigned NumVisited = 0;
for (MachineBasicBlock::iterator I = next(OldPos); I != KillPos; ++I) {
MachineInstr *OtherMI = I;
if (NumVisited > 30) return false;
++NumVisited;
for (unsigned i = 0, e = OtherMI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = OtherMI->getOperand(i);
if (!MO.isReg())
continue;
unsigned MOReg = MO.getReg();
if (!MOReg)
continue;
if (DefReg == MOReg)
return false;
if (MO.isKill()) {
if (OtherMI == KillMI && MOReg == SavedReg)
KillMO = &MO;
else if (UseRegs.count(MOReg))
return false;
}
}
}
KillMO->setIsKill(false);
KillMO = MI->findRegisterUseOperand(SavedReg, false, TRI);
KillMO->setIsKill(true);
if (LV)
LV->replaceKillInstruction(SavedReg, KillMI, MI);
MBB->remove(MI);
MBB->insert(KillPos, MI);
++Num3AddrSunk;
return true;
}
static bool isTwoAddrUse(MachineInstr *UseMI, unsigned Reg) {
const TargetInstrDesc &TID = UseMI->getDesc();
for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) {
MachineOperand &MO = UseMI->getOperand(i);
if (MO.isReg() && MO.getReg() == Reg &&
(MO.isDef() || UseMI->isRegTiedToDefOperand(i)))
return true;
}
return false;
}
bool
TwoAddressInstructionPass::isProfitableToReMat(unsigned Reg,
const TargetRegisterClass *RC,
MachineInstr *MI, MachineInstr *DefMI,
MachineBasicBlock *MBB, unsigned Loc) {
bool OtherUse = false;
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg),
UE = MRI->use_end(); UI != UE; ++UI) {
MachineOperand &UseMO = UI.getOperand();
MachineInstr *UseMI = UseMO.getParent();
MachineBasicBlock *UseMBB = UseMI->getParent();
if (UseMBB == MBB) {
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(UseMI);
if (DI != DistanceMap.end() && DI->second == Loc)
continue; OtherUse = true;
if (isTwoAddrUse(UseMI, Reg))
return true;
}
}
if (OtherUse)
return false;
return MBB == DefMI->getParent();
}
bool TwoAddressInstructionPass::NoUseAfterLastDef(unsigned Reg,
MachineBasicBlock *MBB, unsigned Dist,
unsigned &LastDef) {
LastDef = 0;
unsigned LastUse = Dist;
for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg),
E = MRI->reg_end(); I != E; ++I) {
MachineOperand &MO = I.getOperand();
MachineInstr *MI = MO.getParent();
if (MI->getParent() != MBB)
continue;
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI);
if (DI == DistanceMap.end())
continue;
if (MO.isUse() && DI->second < LastUse)
LastUse = DI->second;
if (MO.isDef() && DI->second > LastDef)
LastDef = DI->second;
}
return !(LastUse > LastDef && LastUse < Dist);
}
MachineInstr *TwoAddressInstructionPass::FindLastUseInMBB(unsigned Reg,
MachineBasicBlock *MBB,
unsigned Dist) {
unsigned LastUseDist = Dist;
MachineInstr *LastUse = 0;
for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg),
E = MRI->reg_end(); I != E; ++I) {
MachineOperand &MO = I.getOperand();
MachineInstr *MI = MO.getParent();
if (MI->getParent() != MBB)
continue;
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI);
if (DI == DistanceMap.end())
continue;
if (MO.isUse() && DI->second < LastUseDist) {
LastUse = DI->first;
LastUseDist = DI->second;
}
}
return LastUse;
}
static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII,
unsigned &SrcReg, unsigned &DstReg,
bool &IsSrcPhys, bool &IsDstPhys) {
SrcReg = 0;
DstReg = 0;
unsigned SrcSubIdx, DstSubIdx;
if (!TII->isMoveInstr(MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) {
if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) {
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
} else if (MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG) {
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(2).getReg();
} else if (MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) {
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(2).getReg();
}
}
if (DstReg) {
IsSrcPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg);
IsDstPhys = TargetRegisterInfo::isPhysicalRegister(DstReg);
return true;
}
return false;
}
static bool isKilled(MachineInstr &MI, unsigned Reg,
const MachineRegisterInfo *MRI,
const TargetInstrInfo *TII) {
MachineInstr *DefMI = &MI;
for (;;) {
if (!DefMI->killsRegister(Reg))
return false;
if (TargetRegisterInfo::isPhysicalRegister(Reg))
return true;
MachineRegisterInfo::def_iterator Begin = MRI->def_begin(Reg);
if (next(Begin) != MRI->def_end())
return true;
DefMI = &*Begin;
bool IsSrcPhys, IsDstPhys;
unsigned SrcReg, DstReg;
if (!isCopyToReg(*DefMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys))
return true;
Reg = SrcReg;
}
}
static bool isTwoAddrUse(MachineInstr &MI, unsigned Reg, unsigned &DstReg) {
const TargetInstrDesc &TID = MI.getDesc();
unsigned NumOps = (MI.getOpcode() == TargetInstrInfo::INLINEASM)
? MI.getNumOperands() : TID.getNumOperands();
for (unsigned i = 0; i != NumOps; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.isUse() || MO.getReg() != Reg)
continue;
unsigned ti;
if (MI.isRegTiedToDefOperand(i, &ti)) {
DstReg = MI.getOperand(ti).getReg();
return true;
}
}
return false;
}
static
MachineInstr *findOnlyInterestingUse(unsigned Reg, MachineBasicBlock *MBB,
MachineRegisterInfo *MRI,
const TargetInstrInfo *TII,
bool &IsCopy,
unsigned &DstReg, bool &IsDstPhys) {
MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg);
if (UI == MRI->use_end())
return 0;
MachineInstr &UseMI = *UI;
if (++UI != MRI->use_end())
return 0;
if (UseMI.getParent() != MBB)
return 0;
unsigned SrcReg;
bool IsSrcPhys;
if (isCopyToReg(UseMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) {
IsCopy = true;
return &UseMI;
}
IsDstPhys = false;
if (isTwoAddrUse(UseMI, Reg, DstReg)) {
IsDstPhys = TargetRegisterInfo::isPhysicalRegister(DstReg);
return &UseMI;
}
return 0;
}
static unsigned
getMappedReg(unsigned Reg, DenseMap<unsigned, unsigned> &RegMap) {
while (TargetRegisterInfo::isVirtualRegister(Reg)) {
DenseMap<unsigned, unsigned>::iterator SI = RegMap.find(Reg);
if (SI == RegMap.end())
return 0;
Reg = SI->second;
}
if (TargetRegisterInfo::isPhysicalRegister(Reg))
return Reg;
return 0;
}
static bool
regsAreCompatible(unsigned RegA, unsigned RegB, const TargetRegisterInfo *TRI) {
if (RegA == RegB)
return true;
if (!RegA || !RegB)
return false;
return TRI->regsOverlap(RegA, RegB);
}
bool
TwoAddressInstructionPass::isProfitableToCommute(unsigned regB, unsigned regC,
MachineInstr *MI, MachineBasicBlock *MBB,
unsigned Dist) {
if (!MI->killsRegister(regC))
return false;
unsigned FromRegB = getMappedReg(regB, SrcRegMap);
unsigned FromRegC = getMappedReg(regC, SrcRegMap);
unsigned ToRegB = getMappedReg(regB, DstRegMap);
unsigned ToRegC = getMappedReg(regC, DstRegMap);
if (!regsAreCompatible(FromRegB, ToRegB, TRI) &&
(regsAreCompatible(FromRegB, ToRegC, TRI) ||
regsAreCompatible(FromRegC, ToRegB, TRI)))
return true;
unsigned LastDefC = 0;
if (!NoUseAfterLastDef(regC, MBB, Dist, LastDefC))
return false;
unsigned LastDefB = 0;
if (!NoUseAfterLastDef(regB, MBB, Dist, LastDefB))
return true;
return LastDefB && LastDefC && LastDefC > LastDefB;
}
bool
TwoAddressInstructionPass::CommuteInstruction(MachineBasicBlock::iterator &mi,
MachineFunction::iterator &mbbi,
unsigned RegB, unsigned RegC, unsigned Dist) {
MachineInstr *MI = mi;
DOUT << "2addr: COMMUTING : " << *MI;
MachineInstr *NewMI = TII->commuteInstruction(MI);
if (NewMI == 0) {
DOUT << "2addr: COMMUTING FAILED!\n";
return false;
}
DOUT << "2addr: COMMUTED TO: " << *NewMI;
if (NewMI != MI) {
if (LV)
LV->replaceKillInstruction(RegC, MI, NewMI);
mbbi->insert(mi, NewMI); mbbi->erase(mi); mi = NewMI;
DistanceMap.insert(std::make_pair(NewMI, Dist));
}
unsigned FromRegC = getMappedReg(RegC, SrcRegMap);
if (FromRegC) {
unsigned RegA = MI->getOperand(0).getReg();
SrcRegMap[RegA] = FromRegC;
}
return true;
}
bool
TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA) {
unsigned FromRegA = getMappedReg(RegA, SrcRegMap);
unsigned ToRegA = getMappedReg(RegA, DstRegMap);
return (FromRegA && ToRegA && !regsAreCompatible(FromRegA, ToRegA, TRI));
}
bool
TwoAddressInstructionPass::ConvertInstTo3Addr(MachineBasicBlock::iterator &mi,
MachineBasicBlock::iterator &nmi,
MachineFunction::iterator &mbbi,
unsigned RegB, unsigned Dist) {
MachineInstr *NewMI = TII->convertToThreeAddress(mbbi, mi, LV);
if (NewMI) {
DOUT << "2addr: CONVERTING 2-ADDR: " << *mi;
DOUT << "2addr: TO 3-ADDR: " << *NewMI;
bool Sunk = false;
if (NewMI->findRegisterUseOperand(RegB, false, TRI))
Sunk = Sink3AddrInstruction(mbbi, NewMI, RegB, mi);
mbbi->erase(mi);
if (!Sunk) {
DistanceMap.insert(std::make_pair(NewMI, Dist));
mi = NewMI;
nmi = next(mi);
}
return true;
}
return false;
}
void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI,
MachineBasicBlock *MBB,
SmallPtrSet<MachineInstr*, 8> &Processed) {
if (Processed.count(MI))
return;
bool IsSrcPhys, IsDstPhys;
unsigned SrcReg, DstReg;
if (!isCopyToReg(*MI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys))
return;
if (IsDstPhys && !IsSrcPhys)
DstRegMap.insert(std::make_pair(SrcReg, DstReg));
else if (!IsDstPhys && IsSrcPhys) {
bool isNew = SrcRegMap.insert(std::make_pair(DstReg, SrcReg)).second;
if (!isNew)
assert(SrcRegMap[DstReg] == SrcReg &&
"Can't map to two src physical registers!");
SmallVector<unsigned, 4> VirtRegPairs;
bool IsCopy = false;
unsigned NewReg = 0;
while (MachineInstr *UseMI = findOnlyInterestingUse(DstReg, MBB, MRI,TII,
IsCopy, NewReg, IsDstPhys)) {
if (IsCopy) {
if (!Processed.insert(UseMI))
break;
}
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(UseMI);
if (DI != DistanceMap.end())
break;
if (IsDstPhys) {
VirtRegPairs.push_back(NewReg);
break;
}
bool isNew = SrcRegMap.insert(std::make_pair(NewReg, DstReg)).second;
if (!isNew)
assert(SrcRegMap[NewReg] == DstReg &&
"Can't map to two src physical registers!");
VirtRegPairs.push_back(NewReg);
DstReg = NewReg;
}
if (!VirtRegPairs.empty()) {
unsigned ToReg = VirtRegPairs.back();
VirtRegPairs.pop_back();
while (!VirtRegPairs.empty()) {
unsigned FromReg = VirtRegPairs.back();
VirtRegPairs.pop_back();
bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second;
if (!isNew)
assert(DstRegMap[FromReg] == ToReg &&
"Can't map to two dst physical registers!");
ToReg = FromReg;
}
}
}
Processed.insert(MI);
}
static bool isSafeToDelete(MachineInstr *MI, unsigned Reg,
const TargetInstrInfo *TII,
SmallVector<unsigned, 4> &Kills) {
const TargetInstrDesc &TID = MI->getDesc();
if (TID.mayStore() || TID.isCall())
return false;
if (TID.isTerminator() || TID.hasUnmodeledSideEffects())
return false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg())
continue;
if (MO.isDef() && !MO.isDead())
return false;
if (MO.isUse() && MO.getReg() != Reg && MO.isKill())
Kills.push_back(MO.getReg());
}
return true;
}
bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
DOUT << "Machine Function\n";
const TargetMachine &TM = MF.getTarget();
MRI = &MF.getRegInfo();
TII = TM.getInstrInfo();
TRI = TM.getRegisterInfo();
LV = getAnalysisIfAvailable<LiveVariables>();
bool MadeChange = false;
DOUT << "********** REWRITING TWO-ADDR INSTRS **********\n";
DOUT << "********** Function: " << MF.getFunction()->getName() << '\n';
BitVector ReMatRegs;
ReMatRegs.resize(MRI->getLastVirtReg()+1);
SmallPtrSet<MachineInstr*, 8> Processed;
for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
mbbi != mbbe; ++mbbi) {
unsigned Dist = 0;
DistanceMap.clear();
SrcRegMap.clear();
DstRegMap.clear();
Processed.clear();
for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end();
mi != me; ) {
MachineBasicBlock::iterator nmi = next(mi);
const TargetInstrDesc &TID = mi->getDesc();
bool FirstTied = true;
DistanceMap.insert(std::make_pair(mi, ++Dist));
ProcessCopy(&*mi, &*mbbi, Processed);
unsigned NumOps = (mi->getOpcode() == TargetInstrInfo::INLINEASM)
? mi->getNumOperands() : TID.getNumOperands();
for (unsigned si = 0; si < NumOps; ++si) {
unsigned ti = 0;
if (!mi->isRegTiedToDefOperand(si, &ti))
continue;
if (FirstTied) {
++NumTwoAddressInstrs;
DOUT << '\t'; DEBUG(mi->print(*cerr.stream(), &TM));
}
FirstTied = false;
assert(mi->getOperand(si).isReg() && mi->getOperand(si).getReg() &&
mi->getOperand(si).isUse() && "two address instruction invalid");
if (mi->getOperand(ti).getReg() != mi->getOperand(si).getReg()) {
unsigned regA = mi->getOperand(ti).getReg();
unsigned regB = mi->getOperand(si).getReg();
assert(TargetRegisterInfo::isVirtualRegister(regB) &&
"cannot update physical register live information");
#ifndef NDEBUG
for (unsigned i = 0; i != mi->getNumOperands(); ++i)
assert(i == ti ||
!mi->getOperand(i).isReg() ||
mi->getOperand(i).getReg() != regA);
#endif
if (!isKilled(*mi, regB, MRI, TII)) {
SmallVector<unsigned, 4> Kills;
if (mi->getOperand(ti).isDead() &&
isSafeToDelete(mi, regB, TII, Kills)) {
SmallVector<std::pair<std::pair<unsigned, bool>
,MachineInstr*>, 4> NewKills;
bool ReallySafe = true;
while (!Kills.empty()) {
unsigned Kill = Kills.back();
Kills.pop_back();
if (TargetRegisterInfo::isPhysicalRegister(Kill)) {
ReallySafe = false;
break;
}
MachineInstr *LastKill = FindLastUseInMBB(Kill, &*mbbi, Dist);
if (LastKill) {
bool isModRef = LastKill->modifiesRegister(Kill);
NewKills.push_back(std::make_pair(std::make_pair(Kill,isModRef),
LastKill));
} else {
ReallySafe = false;
break;
}
}
if (ReallySafe) {
if (LV) {
while (!NewKills.empty()) {
MachineInstr *NewKill = NewKills.back().second;
unsigned Kill = NewKills.back().first.first;
bool isDead = NewKills.back().first.second;
NewKills.pop_back();
if (LV->removeVirtualRegisterKilled(Kill, mi)) {
if (isDead)
LV->addVirtualRegisterDead(Kill, NewKill);
else
LV->addVirtualRegisterKilled(Kill, NewKill);
}
}
}
mbbi->erase(mi); mi = nmi;
++NumDeletes;
break; }
}
if (TID.isCommutable() && mi->getNumOperands() >= 3) {
assert(mi->getOperand(3-si).isReg() &&
"Not a proper commutative instruction!");
unsigned regC = mi->getOperand(3-si).getReg();
if (isKilled(*mi, regC, MRI, TII)) {
if (CommuteInstruction(mi, mbbi, regB, regC, Dist)) {
++NumCommuted;
regB = regC;
goto InstructionRearranged;
}
}
}
if (TID.isConvertibleTo3Addr()) {
#ifndef NDEBUG
for (unsigned i = si + 1, e = TID.getNumOperands(); i < e; ++i)
assert(TID.getOperandConstraint(i, TOI::TIED_TO) == -1);
#endif
if (ConvertInstTo3Addr(mi, nmi, mbbi, regB, Dist)) {
++NumConvertedTo3Addr;
break; }
}
}
if (TID.isCommutable() && mi->getNumOperands() >= 3) {
unsigned regC = mi->getOperand(3-si).getReg();
if (isProfitableToCommute(regB, regC, mi, mbbi, Dist))
if (CommuteInstruction(mi, mbbi, regB, regC, Dist)) {
++NumAggrCommuted;
++NumCommuted;
regB = regC;
goto InstructionRearranged;
}
}
if (TID.isConvertibleTo3Addr() && isProfitableToConv3Addr(regA)) {
if (ConvertInstTo3Addr(mi, nmi, mbbi, regB, Dist)) {
++NumConvertedTo3Addr;
break; }
}
InstructionRearranged:
const TargetRegisterClass* rc = MRI->getRegClass(regB);
MachineInstr *DefMI = MRI->getVRegDef(regB);
if (DefMI &&
DefMI->getDesc().isAsCheapAsAMove() &&
DefMI->isSafeToReMat(TII, regB) &&
isProfitableToReMat(regB, rc, mi, DefMI, mbbi, Dist)){
DEBUG(cerr << "2addr: REMATTING : " << *DefMI << "\n");
TII->reMaterialize(*mbbi, mi, regA, DefMI);
ReMatRegs.set(regB);
++NumReMats;
} else {
bool Emitted = TII->copyRegToReg(*mbbi, mi, regA, regB, rc, rc);
assert(Emitted && "Unable to issue a copy instruction!\n");
}
MachineBasicBlock::iterator prevMI = prior(mi);
DistanceMap.insert(std::make_pair(prevMI, Dist));
DistanceMap[mi] = ++Dist;
if (LV) {
LiveVariables::VarInfo& varInfoB = LV->getVarInfo(regB);
varInfoB.UsedBlocks[mbbi->getNumber()] = true;
if (LV->removeVirtualRegisterKilled(regB, mi))
LV->addVirtualRegisterKilled(regB, prevMI);
if (LV->removeVirtualRegisterDead(regB, mi))
LV->addVirtualRegisterDead(regB, prevMI);
}
DOUT << "\t\tprepend:\t"; DEBUG(prevMI->print(*cerr.stream(), &TM));
for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) {
if (mi->getOperand(i).isReg() &&
mi->getOperand(i).getReg() == regB)
mi->getOperand(i).setReg(regA);
}
}
assert(mi->getOperand(ti).isDef() && mi->getOperand(si).isUse());
mi->getOperand(ti).setReg(mi->getOperand(si).getReg());
MadeChange = true;
DOUT << "\t\trewrite to:\t"; DEBUG(mi->print(*cerr.stream(), &TM));
}
mi = nmi;
}
}
int VReg = ReMatRegs.find_first();
while (VReg != -1) {
if (MRI->use_empty(VReg)) {
MachineInstr *DefMI = MRI->getVRegDef(VReg);
DefMI->eraseFromParent();
}
VReg = ReMatRegs.find_next(VReg);
}
return MadeChange;
}