From 0222a8cfb8f8f3f67e4a07164eb1ecf9c44e6f64 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 20 Oct 2009 01:31:09 +0000 Subject: [PATCH] If the physical register being spilled does not have an interval, spill its sub-registers instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84586 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/LiveIntervalAnalysis.cpp | 26 +++++++-- test/CodeGen/X86/2009-10-19-EmergencySpill.ll | 54 +++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/X86/2009-10-19-EmergencySpill.ll diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 93d3d4c8389..51d6bb1b9ad 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -2603,7 +2603,19 @@ bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li, tri_->isSuperRegister(*AS, SpillReg)); bool Cut = false; - LiveInterval &pli = getInterval(SpillReg); + SmallVector PRegs; + if (hasInterval(SpillReg)) + PRegs.push_back(SpillReg); + else { + SmallSet Added; + for (const unsigned* AS = tri_->getSubRegisters(SpillReg); *AS; ++AS) + if (Added.insert(*AS) && hasInterval(*AS)) { + PRegs.push_back(*AS); + for (const unsigned* ASS = tri_->getSubRegisters(*AS); *ASS; ++ASS) + Added.insert(*ASS); + } + } + SmallPtrSet SeenMIs; for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg), E = mri_->reg_end(); I != E; ++I) { @@ -2613,8 +2625,12 @@ bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li, continue; SeenMIs.insert(MI); LiveIndex Index = getInstructionIndex(MI); - if (pli.liveAt(Index)) { - vrm.addEmergencySpill(SpillReg, MI); + for (unsigned i = 0, e = PRegs.size(); i != e; ++i) { + unsigned PReg = PRegs[i]; + LiveInterval &pli = getInterval(PReg); + if (!pli.liveAt(Index)) + continue; + vrm.addEmergencySpill(PReg, MI); LiveIndex StartIdx = getLoadIndex(Index); LiveIndex EndIdx = getNextSlot(getStoreIndex(Index)); if (pli.isInOneLiveRange(StartIdx, EndIdx)) { @@ -2626,12 +2642,12 @@ bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li, Msg << "Ran out of registers during register allocation!"; if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { Msg << "\nPlease check your inline asm statement for invalid " - << "constraints:\n"; + << "constraints:\n"; MI->print(Msg, tm_); } llvm_report_error(Msg.str()); } - for (const unsigned* AS = tri_->getSubRegisters(SpillReg); *AS; ++AS) { + for (const unsigned* AS = tri_->getSubRegisters(PReg); *AS; ++AS) { if (!hasInterval(*AS)) continue; LiveInterval &spli = getInterval(*AS); diff --git a/test/CodeGen/X86/2009-10-19-EmergencySpill.ll b/test/CodeGen/X86/2009-10-19-EmergencySpill.ll new file mode 100644 index 00000000000..ba44a2e64fe --- /dev/null +++ b/test/CodeGen/X86/2009-10-19-EmergencySpill.ll @@ -0,0 +1,54 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin10 -disable-fp-elim +; rdar://7291624 + +%union.RtreeCoord = type { float } +%struct.RtreeCell = type { i64, [10 x %union.RtreeCoord] } +%struct.Rtree = type { i32, i32*, i32, i32, i32, i32, i8*, i8* } +%struct.RtreeNode = type { i32*, i64, i32, i32, i8*, i32* } + +define fastcc void @nodeOverwriteCell(%struct.Rtree* nocapture %pRtree, %struct.RtreeNode* nocapture %pNode, %struct.RtreeCell* nocapture %pCell, i32 %iCell) nounwind ssp { +entry: + %0 = load i8** undef, align 8 ; [#uses=2] + %1 = load i32* undef, align 8 ; [#uses=1] + %2 = mul i32 %1, %iCell ; [#uses=1] + %3 = add nsw i32 %2, 4 ; [#uses=1] + %4 = sext i32 %3 to i64 ; [#uses=2] + %5 = load i64* null, align 8 ; [#uses=2] + %6 = lshr i64 %5, 48 ; [#uses=1] + %7 = trunc i64 %6 to i8 ; [#uses=1] + store i8 %7, i8* undef, align 1 + %8 = lshr i64 %5, 8 ; [#uses=1] + %9 = trunc i64 %8 to i8 ; [#uses=1] + %.sum4 = add i64 %4, 6 ; [#uses=1] + %10 = getelementptr inbounds i8* %0, i64 %.sum4 ; [#uses=1] + store i8 %9, i8* %10, align 1 + %11 = getelementptr inbounds %struct.Rtree* %pRtree, i64 0, i32 3 ; [#uses=1] + br i1 undef, label %bb.nph, label %bb2 + +bb.nph: ; preds = %entry + %tmp25 = add i64 %4, 11 ; [#uses=1] + br label %bb + +bb: ; preds = %bb, %bb.nph + %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=3] + %scevgep = getelementptr %struct.RtreeCell* %pCell, i64 0, i32 1, i64 %indvar ; <%union.RtreeCoord*> [#uses=1] + %scevgep12 = bitcast %union.RtreeCoord* %scevgep to i32* ; [#uses=1] + %tmp = shl i64 %indvar, 2 ; [#uses=1] + %tmp26 = add i64 %tmp, %tmp25 ; [#uses=1] + %scevgep27 = getelementptr i8* %0, i64 %tmp26 ; [#uses=1] + %12 = load i32* %scevgep12, align 4 ; [#uses=1] + %13 = lshr i32 %12, 24 ; [#uses=1] + %14 = trunc i32 %13 to i8 ; [#uses=1] + store i8 %14, i8* undef, align 1 + store i8 undef, i8* %scevgep27, align 1 + %15 = load i32* %11, align 4 ; [#uses=1] + %16 = shl i32 %15, 1 ; [#uses=1] + %17 = icmp sgt i32 %16, undef ; [#uses=1] + %indvar.next = add i64 %indvar, 1 ; [#uses=1] + br i1 %17, label %bb, label %bb2 + +bb2: ; preds = %bb, %entry + %18 = getelementptr inbounds %struct.RtreeNode* %pNode, i64 0, i32 3 ; [#uses=1] + store i32 1, i32* %18, align 4 + ret void +}