Skip to content

Commit

Permalink
[SCEV] Add a threshold to restrict number of mul operands to be inlin…
Browse files Browse the repository at this point in the history
…ed into SCEV

This is to avoid inlining too many multiplication operands into a SCEV, which could 
take exponential time in the worst case.

Reviewers: Sanjoy Das, Mehdi Amini, Michael Zolotukhin

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

llvm-svn: 284784
  • Loading branch information
lihuang916 committed Oct 20, 2016
1 parent 476cbf9 commit fcfe8cd
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
7 changes: 7 additions & 0 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Expand Up @@ -121,6 +121,11 @@ static cl::opt<bool>
cl::desc("Verify no dangling value in ScalarEvolution's "
"ExprValueMap (slow)"));

static cl::opt<unsigned> MulOpsInlineThreshold(
"scev-mulops-inline-threshold", cl::Hidden,
cl::desc("Threshold for inlining multiplication operands into a SCEV"),
cl::init(1000));

//===----------------------------------------------------------------------===//
// SCEV class definitions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2516,6 +2521,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
if (Idx < Ops.size()) {
bool DeletedMul = false;
while (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[Idx])) {
if (Ops.size() > MulOpsInlineThreshold)
break;
// If we have an mul, expand the mul operands onto the end of the operands
// list.
Ops.erase(Ops.begin()+Idx);
Expand Down
29 changes: 29 additions & 0 deletions llvm/test/Analysis/ScalarEvolution/max-mulops-inline.ll
@@ -0,0 +1,29 @@
; RUN: opt -analyze -scalar-evolution -scev-mulops-inline-threshold=1 < %s | FileCheck --check-prefix=CHECK1 %s
; RUN: opt -analyze -scalar-evolution -scev-mulops-inline-threshold=10 < %s | FileCheck --check-prefix=CHECK10 %s

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@a = local_unnamed_addr global i32 0, align 4
@b = local_unnamed_addr global i32 0, align 4

define i32 @main() local_unnamed_addr {

; CHECK1: %mul.1 = mul nsw i32 %mul, %mul
; CHECK1: --> ((%a.promoted * %a.promoted) * (%a.promoted * %a.promoted))

; CHECK10: %mul.1 = mul nsw i32 %mul, %mul
; CHECK10: --> (%a.promoted * %a.promoted * %a.promoted * %a.promoted)

entry:
%a.promoted = load i32, i32* @a, align 4
%mul = mul nsw i32 %a.promoted, %a.promoted
%mul.1 = mul nsw i32 %mul, %mul
%mul.2 = mul nsw i32 %mul.1, %mul.1
%mul.3 = mul nsw i32 %mul.2, %mul.2
%mul.4 = mul nsw i32 %mul.3, %mul.3
%mul.5 = mul nsw i32 %mul.4, %mul.4
store i32 %mul.5, i32* @a, align 4
store i32 31, i32* @b, align 4
ret i32 0
}

0 comments on commit fcfe8cd

Please sign in to comment.