mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-14 03:45:33 +00:00
[SCEV] Prohibit SCEV transformations for huge SCEVs
Currently SCEV attempts to limit transformations so that they do not work with big SCEVs (that may take almost infinite compile time). But for this, it uses heuristics such as recursion depth and number of operands, which do not give us a guarantee that we don't actually have big SCEVs. This situation is still possible, though it is not likely to happen. However, the bug PR33494 showed a bunch of simple corner case tests where we still produce huge SCEVs, even not reaching big recursion depth etc. This patch introduces a concept of 'huge' SCEVs. A SCEV is huge if its expression size (intoduced in D35989) exceeds some threshold value. We prohibit optimizing transformations if any of SCEVs we are dealing with is huge. This gives us a reliable check that we don't spend too much time working with them. As the next step, we can possibly get rid of old limiting mechanisms, such as recursion depth thresholds. Differential Revision: https://reviews.llvm.org/D35990 Reviewed By: reames llvm-svn: 352728
This commit is contained in:
parent
108b892939
commit
b37419ef66
@ -211,6 +211,11 @@ static cl::opt<unsigned>
|
||||
cl::desc("Max coefficients in AddRec during evolving"),
|
||||
cl::init(8));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
HugeExprThreshold("scalar-evolution-huge-expr-threshold", cl::Hidden,
|
||||
cl::desc("Size of the expression which is considered huge"),
|
||||
cl::init(4096));
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SCEV class definitions
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -845,6 +850,17 @@ static inline int sizeOfSCEV(const SCEV *S) {
|
||||
return F.Size;
|
||||
}
|
||||
|
||||
/// Returns true if the subtree of \p S contains at least HugeExprThreshold
|
||||
/// nodes.
|
||||
static bool isHugeExpression(const SCEV *S) {
|
||||
return S->getExpressionSize() >= HugeExprThreshold;
|
||||
}
|
||||
|
||||
/// Returns true of \p Ops contains a huge SCEV (see definition above).
|
||||
static bool hasHugeExpression(ArrayRef<const SCEV *> Ops) {
|
||||
return any_of(Ops, isHugeExpression);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> {
|
||||
@ -2404,7 +2420,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
}
|
||||
|
||||
// Limit recursion calls depth.
|
||||
if (Depth > MaxArithDepth)
|
||||
if (Depth > MaxArithDepth || hasHugeExpression(Ops))
|
||||
return getOrCreateAddExpr(Ops, Flags);
|
||||
|
||||
// Okay, check to see if the same value occurs in the operand list more than
|
||||
@ -2883,7 +2899,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
Flags = StrengthenNoWrapFlags(this, scMulExpr, Ops, Flags);
|
||||
|
||||
// Limit recursion calls depth.
|
||||
if (Depth > MaxArithDepth)
|
||||
if (Depth > MaxArithDepth || hasHugeExpression(Ops))
|
||||
return getOrCreateMulExpr(Ops, Flags);
|
||||
|
||||
// If there are any constants, fold them together.
|
||||
@ -3056,7 +3072,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
// Limit max number of arguments to avoid creation of unreasonably big
|
||||
// SCEVAddRecs with very complex operands.
|
||||
if (AddRec->getNumOperands() + OtherAddRec->getNumOperands() - 1 >
|
||||
MaxAddRecSize)
|
||||
MaxAddRecSize || isHugeExpression(AddRec) ||
|
||||
isHugeExpression(OtherAddRec))
|
||||
continue;
|
||||
|
||||
bool Overflow = false;
|
||||
|
41
llvm/test/Analysis/ScalarEvolution/huge_expression_limit.ll
Normal file
41
llvm/test/Analysis/ScalarEvolution/huge_expression_limit.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
|
||||
; RUN: opt < %s -analyze -scalar-evolution -scalar-evolution-huge-expr-threshold=1 | FileCheck %s
|
||||
|
||||
define void @test(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
|
||||
; CHECK-LABEL: 'test'
|
||||
; CHECK-NEXT: Classifying expressions for: @test
|
||||
; CHECK-NEXT: %add1 = add i32 %a, %b
|
||||
; CHECK-NEXT: --> (%a + %b) U: full-set S: full-set
|
||||
; CHECK-NEXT: %add2 = add i32 %add1, %c
|
||||
; CHECK-NEXT: --> ((%a + %b) + %c) U: full-set S: full-set
|
||||
; CHECK-NEXT: %add3 = add i32 %add2, %d
|
||||
; CHECK-NEXT: --> (((%a + %b) + %c) + %d) U: full-set S: full-set
|
||||
; CHECK-NEXT: %add4 = add i32 %add3, %e
|
||||
; CHECK-NEXT: --> ((((%a + %b) + %c) + %d) + %e) U: full-set S: full-set
|
||||
; CHECK-NEXT: %add5 = add i32 %add4, %f
|
||||
; CHECK-NEXT: --> (((((%a + %b) + %c) + %d) + %e) + %f) U: full-set S: full-set
|
||||
; CHECK-NEXT: %mul1 = mul i32 %a, %b
|
||||
; CHECK-NEXT: --> (%a * %b) U: full-set S: full-set
|
||||
; CHECK-NEXT: %mul2 = mul i32 %mul1, %c
|
||||
; CHECK-NEXT: --> ((%a * %b) * %c) U: full-set S: full-set
|
||||
; CHECK-NEXT: %mul3 = mul i32 %mul2, %d
|
||||
; CHECK-NEXT: --> (((%a * %b) * %c) * %d) U: full-set S: full-set
|
||||
; CHECK-NEXT: %mul4 = mul i32 %mul3, %e
|
||||
; CHECK-NEXT: --> ((((%a * %b) * %c) * %d) * %e) U: full-set S: full-set
|
||||
; CHECK-NEXT: %mul5 = mul i32 %mul4, %f
|
||||
; CHECK-NEXT: --> (((((%a * %b) * %c) * %d) * %e) * %f) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @test
|
||||
;
|
||||
%add1 = add i32 %a, %b
|
||||
%add2 = add i32 %add1, %c
|
||||
%add3 = add i32 %add2, %d
|
||||
%add4 = add i32 %add3, %e
|
||||
%add5 = add i32 %add4, %f
|
||||
|
||||
%mul1 = mul i32 %a, %b
|
||||
%mul2 = mul i32 %mul1, %c
|
||||
%mul3 = mul i32 %mul2, %d
|
||||
%mul4 = mul i32 %mul3, %e
|
||||
%mul5 = mul i32 %mul4, %f
|
||||
ret void
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt < %s -loop-reduce -S | FileCheck %s
|
||||
; RUN: opt < %s -scalar-evolution-huge-expr-threshold=1000000 -loop-reduce -S | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-i32:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
Loading…
x
Reference in New Issue
Block a user