aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-09-11 20:07:10 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-09-11 20:07:10 +0000
commit8db866808c803f9bdcd45c56a042fedd8cccd5bc (patch)
tree0616d920ec6af7dc1ea68c275f8065140b736e13 /lib/CodeGen
parentac34a00fe0784cd6efc466f03f93ab1017fa9726 (diff)
downloadexternal_llvm-8db866808c803f9bdcd45c56a042fedd8cccd5bc.zip
external_llvm-8db866808c803f9bdcd45c56a042fedd8cccd5bc.tar.gz
external_llvm-8db866808c803f9bdcd45c56a042fedd8cccd5bc.tar.bz2
Fix PR2748. Avoid coalescing physical register with virtual register which would create illegal extract_subreg. e.g.
vr1024 = extract_subreg vr1025, 1 ... vr1024 = mov8rr AH If vr1024 is coalesced with AH, the extract_subreg is now illegal since AH does not have a super-reg whose sub-register 1 is AH. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56118 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp63
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.h7
2 files changed, 70 insertions, 0 deletions
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index 2d4d590..7619dd5 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -875,6 +875,8 @@ void SimpleRegisterCoalescing::RemoveCopiesFromValNo(LiveInterval &li,
}
}
+/// getMatchingSuperReg - Return a super-register of the specified register
+/// Reg so its sub-register of index SubIdx is Reg.
static unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx,
const TargetRegisterClass *RC,
const TargetRegisterInfo* TRI) {
@@ -919,6 +921,61 @@ SimpleRegisterCoalescing::isProfitableToCoalesceToSubRC(unsigned SrcReg,
return (SrcSize + DstSize) <= Threshold;
}
+/// HasIncompatibleSubRegDefUse - If we are trying to coalesce a virtual
+/// register with a physical register, check if any of the virtual register
+/// operand is a sub-register use or def. If so, make sure it won't result
+/// in an illegal extract_subreg or insert_subreg instruction. e.g.
+/// vr1024 = extract_subreg vr1025, 1
+/// ...
+/// vr1024 = mov8rr AH
+/// If vr1024 is coalesced with AH, the extract_subreg is now illegal since
+/// AH does not have a super-reg whose sub-register 1 is AH.
+bool
+SimpleRegisterCoalescing::HasIncompatibleSubRegDefUse(MachineInstr *CopyMI,
+ unsigned VirtReg,
+ unsigned PhysReg) {
+ for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(VirtReg),
+ E = mri_->reg_end(); I != E; ++I) {
+ MachineOperand &O = I.getOperand();
+ MachineInstr *MI = &*I;
+ if (MI == CopyMI || JoinedCopies.count(MI))
+ continue;
+ unsigned SubIdx = O.getSubReg();
+ if (SubIdx && !tri_->getSubReg(PhysReg, SubIdx))
+ return true;
+ if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) {
+ SubIdx = MI->getOperand(2).getImm();
+ if (O.isUse() && !tri_->getSubReg(PhysReg, SubIdx))
+ return true;
+ if (O.isDef()) {
+ unsigned SrcReg = MI->getOperand(1).getReg();
+ const TargetRegisterClass *RC =
+ TargetRegisterInfo::isPhysicalRegister(SrcReg)
+ ? tri_->getPhysicalRegisterRegClass(SrcReg)
+ : mri_->getRegClass(SrcReg);
+ if (!getMatchingSuperReg(PhysReg, SubIdx, RC, tri_))
+ return true;
+ }
+ }
+ if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) {
+ SubIdx = MI->getOperand(3).getImm();
+ if (VirtReg == MI->getOperand(0).getReg()) {
+ if (!tri_->getSubReg(PhysReg, SubIdx))
+ return true;
+ } else {
+ unsigned DstReg = MI->getOperand(0).getReg();
+ const TargetRegisterClass *RC =
+ TargetRegisterInfo::isPhysicalRegister(DstReg)
+ ? tri_->getPhysicalRegisterRegClass(DstReg)
+ : mri_->getRegClass(DstReg);
+ if (!getMatchingSuperReg(PhysReg, SubIdx, RC, tri_))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
/// which are the src/dst of the copy instruction CopyMI. This returns true
@@ -1111,6 +1168,12 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
return false;
}
}
+
+ // Will it create illegal extract_subreg / insert_subreg?
+ if (SrcIsPhys && HasIncompatibleSubRegDefUse(CopyMI, DstReg, SrcReg))
+ return false;
+ if (DstIsPhys && HasIncompatibleSubRegDefUse(CopyMI, SrcReg, DstReg))
+ return false;
LiveInterval &SrcInt = li_->getInterval(SrcReg);
LiveInterval &DstInt = li_->getInterval(DstReg);
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h
index 41d1dfb..39c9071 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.h
+++ b/lib/CodeGen/SimpleRegisterCoalescing.h
@@ -223,6 +223,13 @@ namespace llvm {
bool isProfitableToCoalesceToSubRC(unsigned SrcReg, unsigned DstReg,
MachineBasicBlock *MBB);
+ /// HasIncompatibleSubRegDefUse - If we are trying to coalesce a virtual
+ /// register with a physical register, check if any of the virtual register
+ /// operand is a sub-register use or def. If so, make sure it won't result
+ /// in an illegal extract_subreg or insert_subreg instruction.
+ bool HasIncompatibleSubRegDefUse(MachineInstr *CopyMI,
+ unsigned VirtReg, unsigned PhysReg);
+
/// RangeIsDefinedByCopyFromReg - Return true if the specified live range of
/// the specified live interval is defined by a copy from the specified
/// register.