Commit 28be27a0 authored by Duncan P. N. Exon Smith's avatar Duncan P. N. Exon Smith
Browse files

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.
------------------------------------------------------------------------

llvm-svn: 223716
parent 92215b0d
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/Support/raw_ostream.h"
#include <deque>
#include <numeric>

using namespace llvm;
using namespace llvm::bfi_detail;
@@ -123,7 +123,11 @@ static void combineWeight(Weight &W, const Weight &OtherW) {
  }
  assert(W.Type == OtherW.Type);
  assert(W.TargetNode == OtherW.TargetNode);
  assert(W.Amount < W.Amount + OtherW.Amount && "Unexpected overflow");
  assert(OtherW.Amount && "Expected non-zero weight");
  if (W.Amount > W.Amount + OtherW.Amount)
    // Saturate on overflow.
    W.Amount = UINT64_MAX;
  else
    W.Amount += OtherW.Amount;
}
static void combineWeightsBySorting(WeightList &Weights) {
@@ -207,11 +211,19 @@ void Distribution::normalize() {
    Shift = 33 - countLeadingZeros(Total);

  // 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;
  }

  // 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;

  // Sum the weights to each node and shift right if necessary.
+40 −0
Original line number Diff line number Diff line
; 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}