From: David Majnemer Date: Wed, 17 Feb 2016 18:41:44 +0000 (+0000) Subject: Merging r260164: X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=c75c50f45b3d6d1d61ce6b411d12cedaadd71d5b;ds=sidebyside Merging r260164: ------------------------------------------------------------------------ r260164 | akaylor | 2016-02-08 14:52:51 -0800 (Mon, 08 Feb 2016) | 5 lines [regalloc][WinEH] Do not mark intervals as not spillable if they contain a regmask Differential Revision: http://reviews.llvm.org/D16831 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_38@261125 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index edade3164a3..f1ea2c03f13 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -544,6 +544,11 @@ namespace llvm { return true; } + // Returns true if any segment in the live range contains any of the + // provided slot indexes. Slots which occur in holes between + // segments will not cause the function to return true. + bool isLiveAtIndexes(ArrayRef Slots) const; + bool operator<(const LiveRange& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp index abc655ac34c..26aa46fb6c2 100644 --- a/lib/CodeGen/CalcSpillWeights.cpp +++ b/lib/CodeGen/CalcSpillWeights.cpp @@ -213,8 +213,11 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) { if (!Spillable) return; - // Mark li as unspillable if all live ranges are tiny. - if (li.isZeroLength(LIS.getSlotIndexes())) { + // Mark li as unspillable if all live ranges are tiny and the interval + // is not live at any reg mask. If the interval is live at a reg mask + // spilling may be required. + if (li.isZeroLength(LIS.getSlotIndexes()) && + !li.isLiveAtIndexes(LIS.getRegMaskSlots())) { li.markNotSpillable(); return; } diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp index bb3488348f2..50158006211 100644 --- a/lib/CodeGen/LiveInterval.cpp +++ b/lib/CodeGen/LiveInterval.cpp @@ -748,6 +748,40 @@ void LiveRange::flushSegmentSet() { verify(); } +bool LiveRange::isLiveAtIndexes(ArrayRef Slots) const { + ArrayRef::iterator SlotI = Slots.begin(); + ArrayRef::iterator SlotE = Slots.end(); + + // If there are no regmask slots, we have nothing to search. + if (SlotI == SlotE) + return false; + + // Start our search at the first segment that ends after the first slot. + const_iterator SegmentI = find(*SlotI); + const_iterator SegmentE = end(); + + // If there are no segments that end after the first slot, we're done. + if (SegmentI == SegmentE) + return false; + + // Look for each slot in the live range. + for ( ; SlotI != SlotE; ++SlotI) { + // Go to the next segment that ends after the current slot. + // The slot may be within a hole in the range. + SegmentI = advanceTo(SegmentI, *SlotI); + if (SegmentI == SegmentE) + return false; + + // If this segment contains the slot, we're done. + if (SegmentI->contains(*SlotI)) + return true; + // Otherwise, look for the next slot. + } + + // We didn't find a segment containing any of the slots. + return false; +} + void LiveInterval::freeSubRange(SubRange *S) { S->~SubRange(); // Memory was allocated with BumpPtr allocator and is not freed here. diff --git a/test/CodeGen/X86/regalloc-spill-at-ehpad.ll b/test/CodeGen/X86/regalloc-spill-at-ehpad.ll new file mode 100644 index 00000000000..32cc9e781fb --- /dev/null +++ b/test/CodeGen/X86/regalloc-spill-at-ehpad.ll @@ -0,0 +1,75 @@ +; RUN: llc -regalloc=greedy -mtriple=x86_64-pc-windows-msvc < %s -o - | FileCheck %s + +; This test checks for proper handling of a condition where the greedy register +; allocator encounters a very short interval that contains no uses but does +; contain an EH pad unwind edge, which requires spilling. Previously the +; register allocator marked a interval like this as unspillable, resulting in +; a compilation failure. + + +; The following checks that the value %p is reloaded within the catch handler. +; CHECK-LABEL: "?catch$8@?0?test@4HA": +; CHECK: .seh_endprologue +; CHECK: movq -16(%rbp), %rax +; CHECK: movb $0, (%rax) + +define i32* @test(i32* %a) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { +entry: + %call = call i32 @f() + %p = bitcast i32* %a to i8* + br i1 undef, label %if.end, label %if.else + +if.else: ; preds = %entry + br i1 undef, label %cond.false.i, label %if.else.else + +if.else.else: ; preds = %if.else + br i1 undef, label %cond.true.i, label %cond.false.i + +cond.true.i: ; preds = %if.else.else + br label %invoke.cont + +cond.false.i: ; preds = %if.else.else, %if.else + %call.i = invoke i32 @f() + to label %invoke.cont unwind label %catch.dispatch + +catch.dispatch: ; preds = %cond.false.i + %tmp0 = catchswitch within none [label %catch] unwind label %ehcleanup + +catch: ; preds = %catch.dispatch + %tmp1 = catchpad within %tmp0 [i8* null, i32 64, i8* null] + %p.0 = getelementptr inbounds i8, i8* %p, i64 0 + store i8 0, i8* %p.0, align 8 + invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) [ "funclet"(token %tmp1) ] + to label %noexc unwind label %ehcleanup + +noexc: ; preds = %catch + unreachable + +invoke.cont: ; preds = %cond.false.i, %cond.true.i + %cond.i = phi i32 [ %call, %cond.true.i ], [ %call.i, %cond.false.i ] + %cmp = icmp eq i32 %cond.i, -1 + %tmp3 = select i1 %cmp, i32 4, i32 0 + br label %if.end + +if.end: ; preds = %invoke.cont, %entry + %state.0 = phi i32 [ %tmp3, %invoke.cont ], [ 4, %entry ] + %p.1 = getelementptr inbounds i8, i8* %p, i64 0 + invoke void @g(i8* %p.1, i32 %state.0) + to label %invoke.cont.1 unwind label %ehcleanup + +invoke.cont.1: ; preds = %if.end + ret i32* %a + +ehcleanup: ; preds = %if.end, %catch, %catch.dispatch + %tmp4 = cleanuppad within none [] + cleanupret from %tmp4 unwind to caller +} + +%eh.ThrowInfo = type { i32, i32, i32, i32 } + +declare i32 @__CxxFrameHandler3(...) + +declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) + +declare i32 @f() +declare void @g(i8*, i32)