mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 15:39:06 +00:00
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
This commit is contained in:
parent
ac34a00fe0
commit
8db866808c
@ -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);
|
||||
|
@ -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.
|
||||
|
33
test/CodeGen/X86/2008-09-11-CoalescerBug2.ll
Normal file
33
test/CodeGen/X86/2008-09-11-CoalescerBug2.ll
Normal file
@ -0,0 +1,33 @@
|
||||
; RUN: llvm-as < %s | llc -march=x86
|
||||
; PR2748
|
||||
|
||||
@g_73 = external global i32 ; <i32*> [#uses=1]
|
||||
@g_5 = external global i32 ; <i32*> [#uses=1]
|
||||
|
||||
define i32 @func_44(i16 signext %p_46) nounwind {
|
||||
entry:
|
||||
%0 = load i32* @g_5, align 4 ; <i32> [#uses=1]
|
||||
%1 = ashr i32 %0, 1 ; <i32> [#uses=1]
|
||||
%2 = icmp sgt i32 %1, 1 ; <i1> [#uses=1]
|
||||
%3 = zext i1 %2 to i32 ; <i32> [#uses=1]
|
||||
%4 = load i32* @g_73, align 4 ; <i32> [#uses=1]
|
||||
%5 = zext i16 %p_46 to i64 ; <i64> [#uses=1]
|
||||
%6 = sub i64 0, %5 ; <i64> [#uses=1]
|
||||
%7 = trunc i64 %6 to i8 ; <i8> [#uses=2]
|
||||
%8 = trunc i32 %4 to i8 ; <i8> [#uses=2]
|
||||
%9 = icmp eq i8 %8, 0 ; <i1> [#uses=1]
|
||||
br i1 %9, label %bb11, label %bb12
|
||||
|
||||
bb11: ; preds = %entry
|
||||
%10 = urem i8 %7, %8 ; <i8> [#uses=1]
|
||||
br label %bb12
|
||||
|
||||
bb12: ; preds = %bb11, %entry
|
||||
%.014.in = phi i8 [ %10, %bb11 ], [ %7, %entry ] ; <i8> [#uses=1]
|
||||
%11 = icmp ne i8 %.014.in, 0 ; <i1> [#uses=1]
|
||||
%12 = zext i1 %11 to i32 ; <i32> [#uses=1]
|
||||
%13 = tail call i32 (...)* @func_48( i32 %12, i32 %3, i32 0 ) nounwind ; <i32> [#uses=0]
|
||||
ret i32 undef
|
||||
}
|
||||
|
||||
declare i32 @func_48(...)
|
Loading…
Reference in New Issue
Block a user