cl::init(false), cl::Hidden);
static cl::opt<bool>
-CrossClassJoin("join-cross-class-copies",
- cl::desc("Coalesce cross register class copies"),
+DisableCrossClassJoin("disable-cross-class-join",
+ cl::desc("Avoid coalescing cross register class copies"),
cl::init(false), cl::Hidden);
static cl::opt<bool>
/// computation, replace the copy by rematerialize the definition.
bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
unsigned DstReg,
+ unsigned DstSubIdx,
MachineInstr *CopyMI) {
unsigned CopyIdx = li_->getUseIndex(li_->getInstructionIndex(CopyMI));
LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx);
return false;
if (TID.getNumDefs() != 1)
return false;
- // Make sure the copy destination register class fits the instruction
- // definition register class. The mismatch can happen as a result of earlier
- // extract_subreg, insert_subreg, subreg_to_reg coalescing.
- const TargetRegisterClass *RC = getInstrOperandRegClass(tri_, TID, 0);
- if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
- if (mri_->getRegClass(DstReg) != RC)
+ if (DefMI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) {
+ // Make sure the copy destination register class fits the instruction
+ // definition register class. The mismatch can happen as a result of earlier
+ // extract_subreg, insert_subreg, subreg_to_reg coalescing.
+ const TargetRegisterClass *RC = getInstrOperandRegClass(tri_, TID, 0);
+ if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
+ if (mri_->getRegClass(DstReg) != RC)
+ return false;
+ } else if (!RC->contains(DstReg))
return false;
- } else if (!RC->contains(DstReg))
- return false;
+ }
unsigned DefIdx = li_->getDefIndex(CopyIdx);
const LiveRange *DLR= li_->getInterval(DstReg).getLiveRangeContaining(DefIdx);
}
MachineBasicBlock::iterator MII = next(MachineBasicBlock::iterator(CopyMI));
- tii_->reMaterialize(*MBB, MII, DstReg, DefMI);
+ tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI);
MachineInstr *NewMI = prior(MII);
if (checkForDeadDef) {
CopySrcReg == SrcReg && CopyDstReg != UseDstReg) {
// If the use is a copy and it won't be coalesced away, and its source
// is defined by a trivial computation, try to rematerialize it instead.
- if (ReMaterializeTrivialDef(li_->getInterval(SrcReg), CopyDstReg,UseMI))
+ if (ReMaterializeTrivialDef(li_->getInterval(SrcReg), CopyDstReg,
+ CopyDstSubIdx, UseMI))
continue;
}
}
}
-/// RemoveDeadImpDef - Remove implicit_def instructions which are "re-defining"
-/// registers due to insert_subreg coalescing. e.g.
-/// r1024 = op
-/// r1025 = implicit_def
-/// r1025 = insert_subreg r1025, r1024
-/// = op r1025
-/// =>
-/// r1025 = op
-/// r1025 = implicit_def
-/// r1025 = insert_subreg r1025, r1025
-/// = op r1025
-void
-SimpleRegisterCoalescing::RemoveDeadImpDef(unsigned Reg, LiveInterval &LI) {
- for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(Reg),
- E = mri_->reg_end(); I != E; ) {
- MachineOperand &O = I.getOperand();
- MachineInstr *DefMI = &*I;
- ++I;
- if (!O.isDef())
- continue;
- if (DefMI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF)
- continue;
- if (!LI.liveBeforeAndAt(li_->getInstructionIndex(DefMI)))
- continue;
- li_->RemoveMachineInstrFromMaps(DefMI);
- DefMI->eraseFromParent();
- }
-}
-
/// RemoveUnnecessaryKills - Remove kill markers that are no longer accurate
/// due to live range lengthening as the result of coalescing.
void SimpleRegisterCoalescing::RemoveUnnecessaryKills(unsigned Reg,
if (LR->valno->def == RemoveStart) {
// If the def MI defines the val# and this copy is the only kill of the
// val#, then propagate the dead marker.
- if (li.isOnlyLROfValNo(LR)) {
- PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_);
- ++numDeadValNo;
- }
+ PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_);
+ ++numDeadValNo;
+
if (li.isKill(LR->valno, RemoveEnd))
li.removeKill(LR->valno, RemoveEnd);
}
LiveInterval &ImpLi) const{
if (!CopyMI->killsRegister(ImpLi.reg))
return false;
- unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI));
- LiveInterval::iterator LR = li.FindLiveRangeContaining(CopyIdx);
- if (LR == li.end())
- return false;
- if (LR->valno->hasPHIKill())
- return false;
- if (LR->valno->def != CopyIdx)
- return false;
- // Make sure all of val# uses are copies.
- for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(li.reg),
+ // Make sure this is the only use.
+ for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(ImpLi.reg),
UE = mri_->use_end(); UI != UE;) {
MachineInstr *UseMI = &*UI;
++UI;
- if (JoinedCopies.count(UseMI))
- continue;
- unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(UseMI));
- LiveInterval::iterator ULR = li.FindLiveRangeContaining(UseIdx);
- if (ULR == li.end() || ULR->valno != LR->valno)
+ if (CopyMI == UseMI || JoinedCopies.count(UseMI))
continue;
- // If the use is not a use, then it's not safe to coalesce the move.
- unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
- if (!tii_->isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) {
- if (UseMI->getOpcode() == TargetInstrInfo::INSERT_SUBREG &&
- UseMI->getOperand(1).getReg() == li.reg)
- continue;
- return false;
- }
+ return false;
}
return true;
}
-/// TurnCopiesFromValNoToImpDefs - The specified value# is defined by an
-/// implicit_def and it is being removed. Turn all copies from this value#
-/// into implicit_defs.
-void SimpleRegisterCoalescing::TurnCopiesFromValNoToImpDefs(LiveInterval &li,
- VNInfo *VNI) {
- SmallVector<MachineInstr*, 4> ImpDefs;
- MachineOperand *LastUse = NULL;
- unsigned LastUseIdx = li_->getUseIndex(VNI->def);
- for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(li.reg),
- RE = mri_->reg_end(); RI != RE;) {
- MachineOperand *MO = &RI.getOperand();
- MachineInstr *MI = &*RI;
- ++RI;
- if (MO->isDef()) {
- if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
- ImpDefs.push_back(MI);
- continue;
- }
- if (JoinedCopies.count(MI))
- continue;
- unsigned UseIdx = li_->getUseIndex(li_->getInstructionIndex(MI));
- LiveInterval::iterator ULR = li.FindLiveRangeContaining(UseIdx);
- if (ULR == li.end() || ULR->valno != VNI)
- continue;
- // If the use is a copy, turn it into an identity copy.
- unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
- if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
- SrcReg == li.reg) {
- // Change it to an implicit_def.
- MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
- for (int i = MI->getNumOperands() - 1, e = 0; i > e; --i)
- MI->RemoveOperand(i);
- // It's no longer a copy, update the valno it defines.
- unsigned DefIdx = li_->getDefIndex(UseIdx);
- LiveInterval &DstInt = li_->getInterval(DstReg);
- LiveInterval::iterator DLR = DstInt.FindLiveRangeContaining(DefIdx);
- assert(DLR != DstInt.end() && "Live range not found!");
- assert(DLR->valno->copy == MI);
- DLR->valno->copy = NULL;
- ReMatCopies.insert(MI);
- } else if (UseIdx > LastUseIdx) {
- LastUseIdx = UseIdx;
- LastUse = MO;
- }
- }
- if (LastUse) {
- LastUse->setIsKill();
- li.addKill(VNI, LastUseIdx+1, false);
- } else {
- // Remove dead implicit_def's.
- while (!ImpDefs.empty()) {
- MachineInstr *ImpDef = ImpDefs.back();
- ImpDefs.pop_back();
- li_->RemoveMachineInstrFromMaps(ImpDef);
- ImpDef->eraseFromParent();
- }
- }
-}
-
/// isWinToJoinVRWithSrcPhysReg - Return true if it's worth while to join a
/// a virtual destination register with physical source register.
bool
SrcReg = CopyMI->getOperand(1).getReg();
SrcSubIdx = CopyMI->getOperand(2).getImm();
} else if (isInsSubReg || isSubRegToReg) {
- if (CopyMI->getOperand(2).getSubReg()) {
+ DstReg = CopyMI->getOperand(0).getReg();
+ DstSubIdx = CopyMI->getOperand(3).getImm();
+ SrcReg = CopyMI->getOperand(2).getReg();
+ SrcSubIdx = CopyMI->getOperand(2).getSubReg();
+ if (SrcSubIdx && SrcSubIdx != DstSubIdx) {
+ // r1025 = INSERT_SUBREG r1025, r1024<2>, 2 Then r1024 has already been
+ // coalesced to a larger register so the subreg indices cancel out.
DOUT << "\tSource of insert_subreg is already coalesced "
<< "to another register.\n";
return false; // Not coalescable.
}
- DstReg = CopyMI->getOperand(0).getReg();
- DstSubIdx = CopyMI->getOperand(3).getImm();
- SrcReg = CopyMI->getOperand(2).getReg();
} else if (!tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)){
llvm_unreachable("Unrecognized copy instruction!");
}
// Should be non-null only when coalescing to a sub-register class.
bool CrossRC = false;
+ const TargetRegisterClass *SrcRC= SrcIsPhys ? 0 : mri_->getRegClass(SrcReg);
+ const TargetRegisterClass *DstRC= DstIsPhys ? 0 : mri_->getRegClass(DstReg);
const TargetRegisterClass *NewRC = NULL;
MachineBasicBlock *CopyMBB = CopyMI->getParent();
unsigned RealDstReg = 0;
}
}
if (SubIdx) {
+ if (!DstIsPhys && !SrcIsPhys) {
+ if (isInsSubReg || isSubRegToReg) {
+ NewRC = tri_->getMatchingSuperRegClass(DstRC, SrcRC, SubIdx);
+ } else // extract_subreg {
+ NewRC = tri_->getMatchingSuperRegClass(SrcRC, DstRC, SubIdx);
+ }
+ if (!NewRC) {
+ DOUT << "\t Conflicting sub-register indices.\n";
+ return false; // Not coalescable
+ }
+
unsigned LargeReg = isExtSubReg ? SrcReg : DstReg;
unsigned SmallReg = isExtSubReg ? DstReg : SrcReg;
unsigned Limit= allocatableRCRegs_[mri_->getRegClass(SmallReg)].count();
}
}
} else if (differingRegisterClasses(SrcReg, DstReg)) {
- if (!CrossClassJoin)
+ if (DisableCrossClassJoin)
return false;
CrossRC = true;
}
}
- const TargetRegisterClass *SrcRC= SrcIsPhys ? 0 : mri_->getRegClass(SrcReg);
- const TargetRegisterClass *DstRC= DstIsPhys ? 0 : mri_->getRegClass(DstReg);
unsigned LargeReg = SrcReg;
unsigned SmallReg = DstReg;
- unsigned Limit = 0;
// Now determine the register class of the joined register.
if (isExtSubReg) {
Again = true;
return false;
}
- Limit = allocatableRCRegs_[DstRC].count();
+ if (!DstIsPhys && !SrcIsPhys)
+ NewRC = SrcRC;
} else if (!SrcIsPhys && !DstIsPhys) {
NewRC = getCommonSubClass(SrcRC, DstRC);
if (!NewRC) {
// If definition of source is defined by trivial computation, try
// rematerializing it.
if (!isExtSubReg && !isInsSubReg && !isSubRegToReg &&
- ReMaterializeTrivialDef(SrcInt, DstInt.reg, CopyMI))
+ ReMaterializeTrivialDef(SrcInt, DstReg, DstSubIdx, CopyMI))
return true;
// If we can eliminate the copy without merging the live ranges, do so now.
// Coalescing to a virtual register that is of a sub-register class of the
// other. Make sure the resulting register is set to the right register class.
- if (CrossRC) {
- ++numCrossRCs;
- if (NewRC)
- mri_->setRegClass(DstReg, NewRC);
- }
+ if (CrossRC)
+ ++numCrossRCs;
+
+ // This may happen even if it's cross-rc coalescing. e.g.
+ // %reg1026<def> = SUBREG_TO_REG 0, %reg1037<kill>, 4
+ // reg1026 -> GR64, reg1037 -> GR32_ABCD. The resulting register will have to
+ // be allocate a register from GR64_ABCD.
+ if (NewRC)
+ mri_->setRegClass(DstReg, NewRC);
if (NewHeuristic) {
// Add all copies that define val# in the source interval into the queue.
if (TargetRegisterInfo::isVirtualRegister(DstReg))
RemoveUnnecessaryKills(DstReg, *ResDstInt);
- if (isInsSubReg)
- // Avoid:
- // r1024 = op
- // r1024 = implicit_def
- // ...
- // = r1024
- RemoveDeadImpDef(DstReg, *ResDstInt);
UpdateRegDefsUses(SrcReg, DstReg, SubIdx);
// SrcReg is guarateed to be the register whose live interval that is
delete SavedLI;
}
- if (isEmpty) {
- // Now the copy is being coalesced away, the val# previously defined
- // by the copy is being defined by an IMPLICIT_DEF which defines a zero
- // length interval. Remove the val#.
- unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI));
- const LiveRange *LR = ResDstInt->getLiveRangeContaining(CopyIdx);
- VNInfo *ImpVal = LR->valno;
- assert(ImpVal->def == CopyIdx);
- unsigned NextDef = LR->end;
- TurnCopiesFromValNoToImpDefs(*ResDstInt, ImpVal);
- ResDstInt->removeValNo(ImpVal);
- LR = ResDstInt->FindLiveRangeContaining(NextDef);
- if (LR != ResDstInt->end() && LR->valno->def == NextDef) {
- // Special case: vr1024 = implicit_def
- // vr1024 = insert_subreg vr1024, vr1025, c
- // The insert_subreg becomes a "copy" that defines a val# which can itself
- // be coalesced away.
- MachineInstr *DefMI = li_->getInstructionFromIndex(NextDef);
- if (DefMI->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
- LR->valno->copy = DefMI;
- }
- }
-
// If resulting interval has a preference that no longer fits because of subreg
// coalescing, just clear the preference.
unsigned Preference = getRegAllocPreference(ResDstInt->reg, *mf_, mri_, tri_);
LHSValNo->setHasPHIKill(true);
LHS.addKills(LHSValNo, VNI->kills);
LHS.MergeRangesInAsValue(RHS, LHSValNo);
- LHS.weight += RHS.weight;
+
+ LHS.ComputeJoinedWeight(RHS);
// Update regalloc hint if both are virtual registers.
if (TargetRegisterInfo::isVirtualRegister(LHS.reg) &&
return true;
}
-/// TurnCopyIntoImpDef - If source of the specified copy is an implicit def,
-/// turn the copy into an implicit def.
-bool
-SimpleRegisterCoalescing::TurnCopyIntoImpDef(MachineBasicBlock::iterator &I,
- MachineBasicBlock *MBB,
- unsigned DstReg, unsigned SrcReg) {
- MachineInstr *CopyMI = &*I;
- unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI));
- if (!li_->hasInterval(SrcReg))
- return false;
- LiveInterval &SrcInt = li_->getInterval(SrcReg);
- if (!SrcInt.empty())
- return false;
- if (!li_->hasInterval(DstReg))
- return false;
- LiveInterval &DstInt = li_->getInterval(DstReg);
- const LiveRange *DstLR = DstInt.getLiveRangeContaining(CopyIdx);
- // If the valno extends beyond this basic block, then it's not safe to delete
- // the val# or else livein information won't be correct.
- MachineBasicBlock *EndMBB = li_->getMBBFromIndex(DstLR->end);
- if (EndMBB != MBB)
- return false;
- DstInt.removeValNo(DstLR->valno);
- CopyMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
- for (int i = CopyMI->getNumOperands() - 1, e = 0; i > e; --i)
- CopyMI->RemoveOperand(i);
- CopyMI->getOperand(0).setIsUndef();
- bool NoUse = mri_->use_empty(SrcReg);
- if (NoUse) {
- for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(SrcReg),
- RE = mri_->reg_end(); RI != RE; ) {
- assert(RI.getOperand().isDef());
- MachineInstr *DefMI = &*RI;
- ++RI;
- // The implicit_def source has no other uses, delete it.
- assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF);
- li_->RemoveMachineInstrFromMaps(DefMI);
- DefMI->eraseFromParent();
- }
- }
-
- // Mark uses of implicit_def isUndef.
- for (MachineRegisterInfo::use_iterator RI = mri_->use_begin(DstReg),
- RE = mri_->use_end(); RI != RE; ++RI) {
- assert((*RI).getParent() == MBB);
- RI.getOperand().setIsUndef();
- }
-
- ++I;
- return true;
-}
-
bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
mf_ = &fn;
li_->RemoveMachineInstrFromMaps(MI);
mii = mbbi->erase(mii);
++numPeep;
- } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) {
+ } else {
SmallSet<unsigned, 4> UniqueUses;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &mop = MI->getOperand(i);