From 639f493ebf31632574738735bb367729ca187282 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 17 Apr 2008 07:58:04 +0000 Subject: [PATCH] Be more careful with insert_subreg and extract_subreg where either source or destination operand has already been coalesced with another register that's defined by a insert_subreg or extract_subreg. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49843 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SimpleRegisterCoalescing.cpp | 81 ++++++---- test/CodeGen/X86/2008-04-17-CoalescerBug.ll | 171 ++++++++++++++++++++ 2 files changed, 225 insertions(+), 27 deletions(-) create mode 100644 test/CodeGen/X86/2008-04-17-CoalescerBug.ll diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 3c69b25538f..c9b5fd68811 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -849,20 +849,28 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // r1024 = EXTRACT_SUBREG EAX, 0 then r1024 is really going to be // coalesced with AX. unsigned DstSubIdx = CopyMI->getOperand(0).getSubReg(); - assert(!DstSubIdx || DstSubIdx == SubIdx); - if (DstSubIdx != SubIdx) - // r1024<2> = EXTRACT_SUBREG EAX, 0. Then r1024 has already been - // coalesced to an INSERT_SUBREG so the subreg indices cancel out. + if (DstSubIdx) { + // r1024<2> = EXTRACT_SUBREG EAX, 2. Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + if (DstSubIdx != SubIdx) { + DOUT << "\t Sub-register indices mismatch.\n"; + return false; // Not coalescable. + } + } else SrcReg = tri_->getSubReg(SrcReg, SubIdx); SubIdx = 0; } else if (DstIsPhys && isInsSubReg) { // EAX = INSERT_SUBREG EAX, r1024, 0 unsigned SrcSubIdx = CopyMI->getOperand(2).getSubReg(); - assert(!SrcSubIdx || SrcSubIdx == SubIdx); - if (SrcSubIdx != SubIdx) - // EAX = INSERT_SUBREG EAX, r1024<2>, 0 Then r1024 has already been - // coalesced to an EXTRACT_SUBREG so the subreg indices cancel out. - DstReg = tri_->getSubReg(DstReg, SubIdx); + if (SrcSubIdx) { + // EAX = INSERT_SUBREG EAX, r1024<2>, 2 Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + if (SrcSubIdx != SubIdx) { + DOUT << "\t Sub-register indices mismatch.\n"; + return false; // Not coalescable. + } + } else + DstReg = tri_->getSubReg(DstReg, SubIdx); SubIdx = 0; } else if ((DstIsPhys && isExtSubReg) || (SrcIsPhys && isInsSubReg)) { // If this is a extract_subreg where dst is a physical register, e.g. @@ -870,6 +878,11 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // then create and update the actual physical register allocated to RHS. // Ditto for // reg1024 = INSERT_SUBREG r1024, cl, 1 + if (CopyMI->getOperand(1).getSubReg()) { + DOUT << "\tSrc of extract_ / insert_subreg already coalesced with reg" + << " of a super-class.\n"; + return false; // Not coalescable. + } const TargetRegisterClass *RC = mri_->getRegClass(isExtSubReg ? SrcReg : DstReg); if (isExtSubReg) { @@ -899,24 +912,38 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { } SubIdx = 0; } else { - unsigned LargeReg = isExtSubReg ? SrcReg : DstReg; - unsigned SmallReg = isExtSubReg ? DstReg : SrcReg; - unsigned LargeRegSize = - li_->getInterval(LargeReg).getSize() / InstrSlots::NUM; - unsigned SmallRegSize = - li_->getInterval(SmallReg).getSize() / InstrSlots::NUM; - const TargetRegisterClass *RC = mri_->getRegClass(SmallReg); - unsigned Threshold = allocatableRCRegs_[RC].count(); - // Be conservative. If both sides are virtual registers, do not coalesce - // if this will cause a high use density interval to target a smaller set - // of registers. - if (SmallRegSize > Threshold || LargeRegSize > Threshold) { - LiveVariables::VarInfo &svi = lv_->getVarInfo(LargeReg); - LiveVariables::VarInfo &dvi = lv_->getVarInfo(SmallReg); - if ((float)dvi.NumUses / SmallRegSize < - (float)svi.NumUses / LargeRegSize) { - Again = true; // May be possible to coalesce later. - return false; + unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg() + : CopyMI->getOperand(2).getSubReg(); + if (OldSubIdx) { + if (OldSubIdx == SubIdx) + // r1024<2> = EXTRACT_SUBREG r1025, 2. Then r1024 has already been + // coalesced to a larger register so the subreg indices cancel out. + SubIdx = 0; + else { + DOUT << "\t Sub-register indices mismatch.\n"; + return false; // Not coalescable. + } + } + if (SubIdx) { + unsigned LargeReg = isExtSubReg ? SrcReg : DstReg; + unsigned SmallReg = isExtSubReg ? DstReg : SrcReg; + unsigned LargeRegSize = + li_->getInterval(LargeReg).getSize() / InstrSlots::NUM; + unsigned SmallRegSize = + li_->getInterval(SmallReg).getSize() / InstrSlots::NUM; + const TargetRegisterClass *RC = mri_->getRegClass(SmallReg); + unsigned Threshold = allocatableRCRegs_[RC].count(); + // Be conservative. If both sides are virtual registers, do not coalesce + // if this will cause a high use density interval to target a smaller + // set of registers. + if (SmallRegSize > Threshold || LargeRegSize > Threshold) { + LiveVariables::VarInfo &svi = lv_->getVarInfo(LargeReg); + LiveVariables::VarInfo &dvi = lv_->getVarInfo(SmallReg); + if ((float)dvi.NumUses / SmallRegSize < + (float)svi.NumUses / LargeRegSize) { + Again = true; // May be possible to coalesce later. + return false; + } } } } diff --git a/test/CodeGen/X86/2008-04-17-CoalescerBug.ll b/test/CodeGen/X86/2008-04-17-CoalescerBug.ll new file mode 100644 index 00000000000..cd7c29bae52 --- /dev/null +++ b/test/CodeGen/X86/2008-04-17-CoalescerBug.ll @@ -0,0 +1,171 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin | grep xorl | grep {%e} +; Make sure xorl operands are 32-bit registers. + + %struct.tm = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8* } + %struct.wxDateTime = type { %struct.wxLongLong } + %"struct.wxDateTime::TimeZone" = type { i32 } + %struct.wxLongLong = type { i64 } + %struct.wxString = type { %struct.wxStringBase } + %struct.wxStringBase = type { i32* } +@.str = external constant [27 x i32] ; <[27 x i32]*> [#uses=1] +@.str4 = external constant [14 x i32] ; <[14 x i32]*> [#uses=1] +@_ZZNK10wxDateTime5GetTmERKNS_8TimeZoneEE12__FUNCTION__ = external constant [6 x i8] ; <[6 x i8]*> [#uses=1] +@.str33 = external constant [29 x i32] ; <[29 x i32]*> [#uses=1] +@.str89 = external constant [5 x i32] ; <[5 x i32]*> [#uses=1] + +define void @_ZNK10wxDateTime6FormatEPKwRKNS_8TimeZoneE(%struct.wxString* noalias sret %agg.result, %struct.wxDateTime* %this, i32* %format, %"struct.wxDateTime::TimeZone"* %tz) { +entry: + br i1 false, label %bb116.i, label %bb115.critedge.i +bb115.critedge.i: ; preds = %entry + ret void +bb116.i: ; preds = %entry + br i1 false, label %bb52.i.i, label %bb3118 +bb3118: ; preds = %bb116.i + ret void +bb52.i.i: ; preds = %bb116.i + br i1 false, label %bb142.i, label %bb115.critedge.i.i +bb115.critedge.i.i: ; preds = %bb52.i.i + ret void +bb142.i: ; preds = %bb52.i.i + br i1 false, label %bb161.i, label %bb182.i +bb161.i: ; preds = %bb142.i + br label %bb3261 +bb182.i: ; preds = %bb142.i + ret void +bb3261: ; preds = %bb7834, %bb161.i + %tmp3263 = load i32* null, align 4 ; [#uses=1] + %tmp3264 = icmp eq i32 %tmp3263, 37 ; [#uses=1] + br i1 %tmp3264, label %bb3306, label %bb3267 +bb3267: ; preds = %bb3261 + ret void +bb3306: ; preds = %bb3261 + %tmp3310 = invoke %struct.wxStringBase* @_ZN12wxStringBaseaSEPKw( %struct.wxStringBase* null, i32* getelementptr ([5 x i32]* @.str89, i32 0, i32 0) ) + to label %bb3314 unwind label %lpad ; <%struct.wxStringBase*> [#uses=0] +bb3314: ; preds = %bb3306 + %tmp3316 = load i32* null, align 4 ; [#uses=1] + switch i32 %tmp3316, label %bb7595 [ + i32 0, label %bb7819 + i32 37, label %bb7806 + i32 66, label %bb3477 + i32 72, label %bb5334 + i32 73, label %bb5484 + i32 77, label %bb6118 + i32 83, label %bb6406 + i32 85, label %bb6556 + i32 87, label %bb6708 + i32 89, label %bb7308 + i32 98, label %bb3477 + i32 99, label %bb3626 + i32 100, label %bb5184 + i32 106, label %bb5657 + i32 108, label %bb5809 + i32 109, label %bb5968 + i32 119, label %bb6860 + i32 120, label %bb3626 + i32 121, label %bb7158 + ] +bb3477: ; preds = %bb3314, %bb3314 + ret void +bb3626: ; preds = %bb3314, %bb3314 + ret void +bb5184: ; preds = %bb3314 + ret void +bb5334: ; preds = %bb3314 + ret void +bb5484: ; preds = %bb3314 + ret void +bb5657: ; preds = %bb3314 + %tmp5661 = invoke i16 @_ZNK10wxDateTime12GetDayOfYearERKNS_8TimeZoneE( %struct.wxDateTime* %this, %"struct.wxDateTime::TimeZone"* %tz ) zeroext + to label %invcont5660 unwind label %lpad ; [#uses=0] +invcont5660: ; preds = %bb5657 + ret void +bb5809: ; preds = %bb3314 + %tmp61.i.i8486 = icmp sgt i64 0, -1 ; [#uses=1] + %tmp95.i.i8490 = icmp slt i64 0, 2147483647000 ; [#uses=1] + %bothcond9308 = and i1 %tmp61.i.i8486, %tmp95.i.i8490 ; [#uses=1] + br i1 %bothcond9308, label %bb91.i8504, label %bb115.critedge.i.i8492 +bb115.critedge.i.i8492: ; preds = %bb5809 + ret void +bb91.i8504: ; preds = %bb5809 + br i1 false, label %bb155.i8541, label %bb182.i8560 +bb155.i8541: ; preds = %bb91.i8504 + %tmp156.i85398700 = invoke %struct.tm* @gmtime_r( i32* null, %struct.tm* null ) + to label %bb182.i8560 unwind label %lpad ; <%struct.tm*> [#uses=1] +bb182.i8560: ; preds = %bb155.i8541, %bb91.i8504 + %tm48.0.i8558 = phi %struct.tm* [ null, %bb91.i8504 ], [ %tmp156.i85398700, %bb155.i8541 ] ; <%struct.tm*> [#uses=0] + br i1 false, label %bb278.i8617, label %bb187.i8591 +bb187.i8591: ; preds = %bb182.i8560 + %tmp245.i8588 = srem i64 0, 86400000 ; [#uses=1] + br i1 false, label %bb264.i8592, label %bb265.i8606 +bb264.i8592: ; preds = %bb187.i8591 + ret void +bb265.i8606: ; preds = %bb187.i8591 + %tmp268269.i8593 = trunc i64 %tmp245.i8588 to i32 ; [#uses=1] + %tmp273.i8594 = srem i32 %tmp268269.i8593, 1000 ; [#uses=1] + %tmp273274.i8595 = trunc i32 %tmp273.i8594 to i16 ; [#uses=1] + br label %invcont5814 +bb278.i8617: ; preds = %bb182.i8560 + %timeOnly50.0.i8622 = add i32 0, 0 ; [#uses=1] + br i1 false, label %bb440.i8663, label %bb448.i8694 +bb440.i8663: ; preds = %bb278.i8617 + invoke void @_Z10wxOnAssertPKwiPKcS0_S0_( i32* getelementptr ([27 x i32]* @.str, i32 0, i32 0), i32 1717, i8* getelementptr ([6 x i8]* @_ZZNK10wxDateTime5GetTmERKNS_8TimeZoneEE12__FUNCTION__, i32 0, i32 0), i32* getelementptr ([29 x i32]* @.str33, i32 0, i32 0), i32* getelementptr ([14 x i32]* @.str4, i32 0, i32 0) ) + to label %bb448.i8694 unwind label %lpad +bb448.i8694: ; preds = %bb440.i8663, %bb278.i8617 + %tmp477.i8669 = srem i32 %timeOnly50.0.i8622, 1000 ; [#uses=1] + %tmp477478.i8670 = trunc i32 %tmp477.i8669 to i16 ; [#uses=1] + br label %invcont5814 +invcont5814: ; preds = %bb448.i8694, %bb265.i8606 + %tmp812.0.0 = phi i16 [ %tmp477478.i8670, %bb448.i8694 ], [ %tmp273274.i8595, %bb265.i8606 ] ; [#uses=1] + %tmp58165817 = zext i16 %tmp812.0.0 to i32 ; [#uses=1] + invoke void (%struct.wxString*, i32*, ...)* @_ZN8wxString6FormatEPKwz( %struct.wxString* noalias sret null, i32* null, i32 %tmp58165817 ) + to label %invcont5831 unwind label %lpad +invcont5831: ; preds = %invcont5814 + %tmp5862 = invoke i8 @_ZN12wxStringBase10ConcatSelfEmPKwm( %struct.wxStringBase* null, i32 0, i32* null, i32 0 ) zeroext + to label %bb7834 unwind label %lpad8185 ; [#uses=0] +bb5968: ; preds = %bb3314 + invoke void (%struct.wxString*, i32*, ...)* @_ZN8wxString6FormatEPKwz( %struct.wxString* noalias sret null, i32* null, i32 0 ) + to label %invcont5981 unwind label %lpad +invcont5981: ; preds = %bb5968 + ret void +bb6118: ; preds = %bb3314 + ret void +bb6406: ; preds = %bb3314 + ret void +bb6556: ; preds = %bb3314 + ret void +bb6708: ; preds = %bb3314 + ret void +bb6860: ; preds = %bb3314 + ret void +bb7158: ; preds = %bb3314 + ret void +bb7308: ; preds = %bb3314 + ret void +bb7595: ; preds = %bb3314 + ret void +bb7806: ; preds = %bb3314 + %tmp7814 = invoke %struct.wxStringBase* @_ZN12wxStringBase6appendEmw( %struct.wxStringBase* null, i32 1, i32 0 ) + to label %bb7834 unwind label %lpad ; <%struct.wxStringBase*> [#uses=0] +bb7819: ; preds = %bb3314 + ret void +bb7834: ; preds = %bb7806, %invcont5831 + br label %bb3261 +lpad: ; preds = %bb7806, %bb5968, %invcont5814, %bb440.i8663, %bb155.i8541, %bb5657, %bb3306 + ret void +lpad8185: ; preds = %invcont5831 + ret void +} + +declare void @_Z10wxOnAssertPKwiPKcS0_S0_(i32*, i32, i8*, i32*, i32*) + +declare i8 @_ZN12wxStringBase10ConcatSelfEmPKwm(%struct.wxStringBase*, i32, i32*, i32) zeroext + +declare %struct.tm* @gmtime_r(i32*, %struct.tm*) + +declare i16 @_ZNK10wxDateTime12GetDayOfYearERKNS_8TimeZoneE(%struct.wxDateTime*, %"struct.wxDateTime::TimeZone"*) zeroext + +declare %struct.wxStringBase* @_ZN12wxStringBase6appendEmw(%struct.wxStringBase*, i32, i32) + +declare %struct.wxStringBase* @_ZN12wxStringBaseaSEPKw(%struct.wxStringBase*, i32*) + +declare void @_ZN8wxString6FormatEPKwz(%struct.wxString* noalias sret , i32*, ...) -- 2.34.1