mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
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: 223500
This commit is contained in:
parent
5f7eada35a
commit
c2d918ec4e
@ -14,6 +14,7 @@
|
||||
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
|
||||
#include "llvm/ADT/SCCIterator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <numeric>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::bfi_detail;
|
||||
@ -122,8 +123,12 @@ 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");
|
||||
W.Amount += OtherW.Amount;
|
||||
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) {
|
||||
// Sort so edges to the same node are adjacent.
|
||||
@ -206,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.
|
||||
|
@ -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}
|
Loading…
Reference in New Issue
Block a user