Skip to content

Commit

Permalink
[SCEV] Limit max size of AddRecExpr during evolving
Browse files Browse the repository at this point in the history
When SCEV calculates product of two SCEVAddRecs from the same loop, it
tries to combine them into one big AddRecExpr. If the sizes of the initial
SCEVs were `S1` and `S2`, the size of their product is `S1 + S2 - 1`, and every
operand of the resulting SCEV is combined from operands of initial SCEV and
has much higher complexity than they have.

As result, if we try to calculate something like:
  %x1 = {a,+,b}
  %x2 = mul i32 %x1, %x1
  %x3 = mul i32 %x2, %x1
  %x4 = mul i32 %x3, %x2
  ...
The size of such SCEVs grows as `2^N`, and the arguments
become more and more complex as we go forth. This leads
to long compilation and huge memory consumption.

This patch sets a limit after which we don't try to combine two
`SCEVAddRecExpr`s into one. By default, max allowed size of the
resulting AddRecExpr is set to 16.

Differential Revision: https://reviews.llvm.org/D35664

llvm-svn: 308847
  • Loading branch information
Max Kazantsev committed Jul 23, 2017
1 parent 4c29ca4 commit 0e9e079
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
11 changes: 11 additions & 0 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Expand Up @@ -162,6 +162,11 @@ static cl::opt<unsigned>
cl::desc("Maximum depth of recursive SExt/ZExt"),
cl::init(8));

static cl::opt<unsigned>
MaxAddRecSize("scalar-evolution-max-add-rec-size", cl::Hidden,
cl::desc("Max coefficients in AddRec during evolving"),
cl::init(16));

//===----------------------------------------------------------------------===//
// SCEV class definitions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2878,6 +2883,12 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
if (!OtherAddRec || OtherAddRec->getLoop() != AddRecLoop)
continue;

// Limit max number of arguments to avoid creation of unreasonably big
// SCEVAddRecs with very complex operands.
if (AddRec->getNumOperands() + OtherAddRec->getNumOperands() - 1 >
MaxAddRecSize)
continue;

bool Overflow = false;
Type *Ty = AddRec->getType();
bool LargerThan64Bits = getTypeSizeInBits(Ty) > 64;
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/Analysis/ScalarEvolution/max-addrec-size.ll
@@ -0,0 +1,33 @@
; RUN: opt -analyze -scalar-evolution -scalar-evolution-max-add-rec-size=3 < %s | FileCheck %s

; Show that we are able to avoid creation of huge SCEVs by capping the max
; AddRec size.
define i32 @test_01(i32 %a, i32 %b) {

; CHECK-LABEL: Classifying expressions for: @test_01
; CHECK-NEXT: %iv = phi i32 [ %a, %entry ], [ %iv.next, %loop ]
; CHECK-NEXT: --> {%a,+,%b}<%loop> U: full-set S: full-set
; CHECK-NEXT: %iv.next = add i32 %iv, %b
; CHECK-NEXT: --> {(%a + %b),+,%b}<%loop> U: full-set S: full-set
; CHECK-NEXT: %x1 = mul i32 %iv, %iv.next
; CHECK-NEXT: --> {((%a + %b) * %a),+,(((2 * %a) + (2 * %b)) * %b),+,(2 * %b * %b)}<%loop> U: full-set S: full-set
; CHECK-NEXT: %x2 = mul i32 %x1, %x1
; CHECK-NEXT: --> ({((%a + %b) * %a),+,(((2 * %a) + (2 * %b)) * %b),+,(2 * %b * %b)}<%loop> * {((%a + %b) * %a),+,(((2 * %a) + (2 * %b)) * %b),+,(2 * %b * %b)}<%loop>) U: full-set S: full-set
; CHECK-NEXT: %x3 = mul i32 %x2, %x1
; CHECK-NEXT: --> ({((%a + %b) * %a),+,(((2 * %a) + (2 * %b)) * %b),+,(2 * %b * %b)}<%loop> * {((%a + %b) * %a),+,(((2 * %a) + (2 * %b)) * %b),+,(2 * %b * %b)}<%loop> * {((%a + %b) * %a),+,(((2 * %a) + (2 * %b)) * %b),+,(2 * %b * %b)}<%loop>) U: full-set S: full-set

entry:
br label %loop

loop:
%iv = phi i32 [ %a, %entry ], [ %iv.next, %loop ]
%iv.next = add i32 %iv, %b
%cond = icmp slt i32 %iv.next, 1000
br i1 %cond, label %loop, label %exit

exit:
%x1 = mul i32 %iv, %iv.next
%x2 = mul i32 %x1, %x1
%x3 = mul i32 %x2, %x1
ret i32 %x3
}

0 comments on commit 0e9e079

Please sign in to comment.