diff options
author | Tanya Lattner <tonic@nondot.org> | 2009-02-13 23:53:40 +0000 |
---|---|---|
committer | Tanya Lattner <tonic@nondot.org> | 2009-02-13 23:53:40 +0000 |
commit | c1a60e850e9f8bfe2a4cd6cc8774ca34b35cbdc6 (patch) | |
tree | 94c8df37d6da74e47e7daee5930711740e42d444 | |
parent | 93639fb5cda4ccee74cc605ca4f8bf98b59fc163 (diff) |
Merge from mainline.
Fix PR3486. Fix a bug in code that manually patch physical register live interval after its sub-register is coalesced with a virtual register.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_25@64509 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/CodeGen/LiveIntervalAnalysis.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 11 | ||||
-rw-r--r-- | lib/CodeGen/SimpleRegisterCoalescing.cpp | 39 | ||||
-rw-r--r-- | test/CodeGen/X86/2009-02-08-CoalescerBug.ll | 22 |
4 files changed, 60 insertions, 16 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index b87214f5e2..aec72858c8 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -282,6 +282,10 @@ namespace llvm { I = r2iMap_.insert(std::make_pair(reg, createInterval(reg))).first; return *I->second; } + + /// dupInterval - Duplicate a live interval. The caller is responsible for + /// managing the allocated memory. + LiveInterval *dupInterval(LiveInterval *li); /// addLiveRangeToEndOfBlock - Given a register and an instruction, /// adds a live range from that instruction to the end of its MBB. diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 8e8e8ff6d0..985a3fa163 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -824,11 +824,18 @@ bool LiveIntervals::findReachableMBBs(unsigned Start, unsigned End, } LiveInterval* LiveIntervals::createInterval(unsigned reg) { - float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? - HUGE_VALF : 0.0F; + float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? HUGE_VALF : 0.0F; return new LiveInterval(reg, Weight); } +/// dupInterval - Duplicate a live interval. The caller is responsible for +/// managing the allocated memory. +LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) { + LiveInterval *NewLI = createInterval(li->reg); + NewLI->Copy(*li, getVNInfoAllocator()); + return NewLI; +} + /// getVNInfoSourceReg - Helper function that parses the specified VNInfo /// copy field and returns the source register that defines it. unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const { diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index f3ffc69ccc..8aec579a81 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -1322,6 +1322,15 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { DOUT << " and "; DstInt.print(DOUT, tri_); DOUT << ": "; + // Save a copy of the virtual register live interval. We'll manually + // merge this into the "real" physical register live interval this is + // coalesced with. + LiveInterval *SavedLI = 0; + if (RealDstReg) + SavedLI = li_->dupInterval(&SrcInt); + else if (RealSrcReg) + SavedLI = li_->dupInterval(&DstInt); + // Check if it is necessary to propagate "isDead" property. if (!isExtSubReg && !isInsSubReg) { MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg, false); @@ -1413,21 +1422,17 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { if (RealDstReg || RealSrcReg) { LiveInterval &RealInt = li_->getOrCreateInterval(RealDstReg ? RealDstReg : RealSrcReg); - SmallSet<const VNInfo*, 4> CopiedValNos; - for (LiveInterval::Ranges::const_iterator I = ResSrcInt->ranges.begin(), - E = ResSrcInt->ranges.end(); I != E; ++I) { - const LiveRange *DstLR = ResDstInt->getLiveRangeContaining(I->start); - assert(DstLR && "Invalid joined interval!"); - const VNInfo *DstValNo = DstLR->valno; - if (CopiedValNos.insert(DstValNo)) { - VNInfo *ValNo = RealInt.getNextValue(DstValNo->def, DstValNo->copy, - li_->getVNInfoAllocator()); - ValNo->hasPHIKill = DstValNo->hasPHIKill; - RealInt.addKills(ValNo, DstValNo->kills); - RealInt.MergeValueInAsValue(*ResDstInt, DstValNo, ValNo); - } + for (LiveInterval::const_vni_iterator I = SavedLI->vni_begin(), + E = SavedLI->vni_end(); I != E; ++I) { + const VNInfo *ValNo = *I; + VNInfo *NewValNo = RealInt.getNextValue(ValNo->def, ValNo->copy, + li_->getVNInfoAllocator()); + NewValNo->hasPHIKill = ValNo->hasPHIKill; + NewValNo->redefByEC = ValNo->redefByEC; + RealInt.addKills(NewValNo, ValNo->kills); + RealInt.MergeValueInAsValue(*SavedLI, ValNo, NewValNo); } - + RealInt.weight += SavedLI->weight; DstReg = RealDstReg ? RealDstReg : RealSrcReg; } @@ -1497,6 +1502,12 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // being merged. li_->removeInterval(SrcReg); + // Manually deleted the live interval copy. + if (SavedLI) { + SavedLI->clear(); + delete SavedLI; + } + if (isEmpty) { // Now the copy is being coalesced away, the val# previously defined // by the copy is being defined by an IMPLICIT_DEF which defines a zero diff --git a/test/CodeGen/X86/2009-02-08-CoalescerBug.ll b/test/CodeGen/X86/2009-02-08-CoalescerBug.ll new file mode 100644 index 0000000000..cd30c1e7e4 --- /dev/null +++ b/test/CodeGen/X86/2009-02-08-CoalescerBug.ll @@ -0,0 +1,22 @@ +; RUN: llvm-as < %s | llc -march=x86 +; PR3486 + +define i32 @foo(i8 signext %p_26) nounwind { +entry: + %0 = icmp eq i8 %p_26, 0 ; <i1> [#uses=2] + %or.cond = or i1 false, %0 ; <i1> [#uses=2] + %iftmp.1.0 = zext i1 %or.cond to i16 ; <i16> [#uses=1] + br i1 %0, label %bb.i, label %bar.exit + +bb.i: ; preds = %entry + %1 = zext i1 %or.cond to i32 ; <i32> [#uses=1] + %2 = sdiv i32 %1, 0 ; <i32> [#uses=1] + %3 = trunc i32 %2 to i16 ; <i16> [#uses=1] + br label %bar.exit + +bar.exit: ; preds = %bb.i, %entry + %4 = phi i16 [ %3, %bb.i ], [ %iftmp.1.0, %entry ] ; <i16> [#uses=1] + %5 = trunc i16 %4 to i8 ; <i8> [#uses=1] + %6 = sext i8 %5 to i32 ; <i32> [#uses=1] + ret i32 %6 +} |