RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]);
}
-/// attemptTrivialCoalescing - If a simple interval is defined by a copy, try
-/// allocate the definition the same register as the source register if the
-/// register is not defined during live time of the interval. If the interval is
-/// killed by a copy, try to use the destination register. This eliminates a
-/// copy. This is used to coalesce copies which were not coalesced away before
-/// allocation either due to dest and src being in different register classes or
-/// because the coalescer was overly conservative.
+/// attemptTrivialCoalescing - If a simple interval is defined by a copy,
+/// try allocate the definition the same register as the source register
+/// if the register is not defined during live time of the interval. This
+/// eliminate a copy. This is used to coalesce copies which were not
+/// coalesced away before allocation either due to dest and src being in
+/// different register classes or because the coalescer was overly
+/// conservative.
unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
unsigned Preference = vrm_->getRegAllocPref(cur.reg);
if ((Preference && Preference == Reg) || !cur.containsOneValue())
return Reg;
VNInfo *vni = cur.begin()->valno;
- if (vni->isUnused())
+ if ((vni->def == SlotIndex()) ||
+ vni->isUnused() || !vni->isDefAccurate())
return Reg;
- unsigned CandReg;
- bool forward; // extending physreg forward
- {
- MachineInstr *CopyMI;
- unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
- if (vni->def != SlotIndex() && vni->isDefAccurate() &&
- (CopyMI = li_->getInstructionFromIndex(vni->def)) &&
- tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
- // Defined by a copy, try to extend SrcReg forward
- CandReg = SrcReg, forward = true;
- else if (cur.ranges.size()==1 &&
- (CopyMI =
- li_->getInstructionFromIndex(cur.begin()->end.getBaseIndex())) &&
- tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
- cur.reg == SrcReg)
- // Only used by a copy, try to extend DstReg backwards
- CandReg = DstReg, forward = false;
- else
- return Reg;
- }
-
- if (TargetRegisterInfo::isVirtualRegister(CandReg)) {
- if (!vrm_->isAssignedReg(CandReg))
+ MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
+ unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg;
+ if (!CopyMI ||
+ !tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
+ return Reg;
+ PhysReg = SrcReg;
+ if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
+ if (!vrm_->isAssignedReg(SrcReg))
return Reg;
- CandReg = vrm_->getPhys(CandReg);
+ PhysReg = vrm_->getPhys(SrcReg);
}
- if (Reg == CandReg)
+ if (Reg == PhysReg)
return Reg;
const TargetRegisterClass *RC = mri_->getRegClass(cur.reg);
- if (!RC->contains(CandReg))
+ if (!RC->contains(PhysReg))
return Reg;
- if (forward) {
- if (li_->conflictsWithPhysRegDef(cur, *vrm_, CandReg))
- return Reg;
- } else {
- if (li_->conflictsWithPhysRegUse(cur, *vrm_, CandReg))
- return Reg;
- }
-
// Try to coalesce.
- DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg)
- << '\n');
- vrm_->clearVirt(cur.reg);
- vrm_->assignVirt2Phys(cur.reg, CandReg);
+ if (!li_->conflictsWithPhysRegDef(cur, *vrm_, PhysReg)) {
+ DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(PhysReg)
+ << '\n');
+ vrm_->clearVirt(cur.reg);
+ vrm_->assignVirt2Phys(cur.reg, PhysReg);
+
+ // Remove unnecessary kills since a copy does not clobber the register.
+ if (li_->hasInterval(SrcReg)) {
+ LiveInterval &SrcLI = li_->getInterval(SrcReg);
+ for (MachineRegisterInfo::use_iterator I = mri_->use_begin(cur.reg),
+ E = mri_->use_end(); I != E; ++I) {
+ MachineOperand &O = I.getOperand();
+ if (!O.isKill())
+ continue;
+ MachineInstr *MI = &*I;
+ if (SrcLI.liveAt(li_->getInstructionIndex(MI).getDefIndex()))
+ O.setIsKill(false);
+ }
+ }
+
+ ++NumCoalesce;
+ return PhysReg;
+ }
- ++NumCoalesce;
- return CandReg;
+ return Reg;
}
bool RALinScan::runOnMachineFunction(MachineFunction &fn) {