diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 2d4d5907153..7619dd543d7 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 41d1dfb20b0..39c90716b60 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. diff --git a/test/CodeGen/X86/2008-09-11-CoalescerBug2.ll b/test/CodeGen/X86/2008-09-11-CoalescerBug2.ll new file mode 100644 index 00000000000..94033449114 --- /dev/null +++ b/test/CodeGen/X86/2008-09-11-CoalescerBug2.ll @@ -0,0 +1,33 @@ +; RUN: llvm-as < %s | llc -march=x86 +; PR2748 + +@g_73 = external global i32 ; [#uses=1] +@g_5 = external global i32 ; [#uses=1] + +define i32 @func_44(i16 signext %p_46) nounwind { +entry: + %0 = load i32* @g_5, align 4 ; [#uses=1] + %1 = ashr i32 %0, 1 ; [#uses=1] + %2 = icmp sgt i32 %1, 1 ; [#uses=1] + %3 = zext i1 %2 to i32 ; [#uses=1] + %4 = load i32* @g_73, align 4 ; [#uses=1] + %5 = zext i16 %p_46 to i64 ; [#uses=1] + %6 = sub i64 0, %5 ; [#uses=1] + %7 = trunc i64 %6 to i8 ; [#uses=2] + %8 = trunc i32 %4 to i8 ; [#uses=2] + %9 = icmp eq i8 %8, 0 ; [#uses=1] + br i1 %9, label %bb11, label %bb12 + +bb11: ; preds = %entry + %10 = urem i8 %7, %8 ; [#uses=1] + br label %bb12 + +bb12: ; preds = %bb11, %entry + %.014.in = phi i8 [ %10, %bb11 ], [ %7, %entry ] ; [#uses=1] + %11 = icmp ne i8 %.014.in, 0 ; [#uses=1] + %12 = zext i1 %11 to i32 ; [#uses=1] + %13 = tail call i32 (...)* @func_48( i32 %12, i32 %3, i32 0 ) nounwind ; [#uses=0] + ret i32 undef +} + +declare i32 @func_48(...)