Merging r223500 (this time for real):

------------------------------------------------------------------------
r223500 | dexonsmith | 2014-12-05 11:13:42 -0800 (Fri, 05 Dec 2014) | 9 lines

BFI: Saturate when combining edges to a successor

When a loop gets bundled up, its outgoing edges are quite large, and can
just barely overflow 64-bits.  If one successor has multiple incoming
edges -- and that successor is getting all the incoming mass --
combining just its edges can overflow.  Handle that by saturating rather
than asserting.

This fixes PR21622.
------------------------------------------------------------------------


git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_35@223716 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2014-12-08 23:29:14 +00:00
parent c2594296e6
commit 9696b167f2
2 changed files with 57 additions and 5 deletions

View File

@ -14,7 +14,7 @@
#include "llvm/Analysis/BlockFrequencyInfoImpl.h" #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
#include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/SCCIterator.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <deque> #include <numeric>
using namespace llvm; using namespace llvm;
using namespace llvm::bfi_detail; using namespace llvm::bfi_detail;
@ -123,8 +123,12 @@ static void combineWeight(Weight &W, const Weight &OtherW) {
} }
assert(W.Type == OtherW.Type); assert(W.Type == OtherW.Type);
assert(W.TargetNode == OtherW.TargetNode); assert(W.TargetNode == OtherW.TargetNode);
assert(W.Amount < W.Amount + OtherW.Amount && "Unexpected overflow"); assert(OtherW.Amount && "Expected non-zero weight");
W.Amount += OtherW.Amount; if (W.Amount > W.Amount + OtherW.Amount)
// Saturate on overflow.
W.Amount = UINT64_MAX;
else
W.Amount += OtherW.Amount;
} }
static void combineWeightsBySorting(WeightList &Weights) { static void combineWeightsBySorting(WeightList &Weights) {
// Sort so edges to the same node are adjacent. // Sort so edges to the same node are adjacent.
@ -207,11 +211,19 @@ void Distribution::normalize() {
Shift = 33 - countLeadingZeros(Total); Shift = 33 - countLeadingZeros(Total);
// Early exit if nothing needs to be scaled. // Early exit if nothing needs to be scaled.
if (!Shift) if (!Shift) {
// If we didn't overflow then combineWeights() shouldn't have changed the
// sum of the weights, but let's double-check.
assert(Total == std::accumulate(Weights.begin(), Weights.end(), UINT64_C(0),
[](uint64_t Sum, const Weight &W) {
return Sum + W.Amount;
}) &&
"Expected total to be correct");
return; return;
}
// Recompute the total through accumulation (rather than shifting it) so that // Recompute the total through accumulation (rather than shifting it) so that
// it's accurate after shifting. // it's accurate after shifting and any changes combineWeights() made above.
Total = 0; Total = 0;
// Sum the weights to each node and shift right if necessary. // Sum the weights to each node and shift right if necessary.

View File

@ -0,0 +1,40 @@
; RUN: opt < %s -analyze -block-freq | FileCheck %s
; PR21622: Check for a crasher when the sum of exits to the same successor of a
; loop overflows.
; CHECK-LABEL: Printing analysis {{.*}} for function 'extremely_likely_loop_successor':
; CHECK-NEXT: block-frequency-info: extremely_likely_loop_successor
define void @extremely_likely_loop_successor() {
; CHECK-NEXT: entry: float = 1.0, int = [[ENTRY:[0-9]+]]
entry:
br label %loop
; CHECK-NEXT: loop: float = 1.0,
loop:
%exit.1.cond = call i1 @foo()
br i1 %exit.1.cond, label %exit, label %loop.2, !prof !0
; CHECK-NEXT: loop.2: float = 0.0000000
loop.2:
%exit.2.cond = call i1 @foo()
br i1 %exit.2.cond, label %exit, label %loop.3, !prof !0
; CHECK-NEXT: loop.3: float = 0.0000000
loop.3:
%exit.3.cond = call i1 @foo()
br i1 %exit.3.cond, label %exit, label %loop.4, !prof !0
; CHECK-NEXT: loop.4: float = 0.0,
loop.4:
%exit.4.cond = call i1 @foo()
br i1 %exit.4.cond, label %exit, label %loop, !prof !0
; CHECK-NEXT: exit: float = 1.0, int = [[ENTRY]]
exit:
ret void
}
declare i1 @foo()
!0 = metadata !{metadata !"branch_weights", i32 4294967295, i32 1}