mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 19:49:36 +00:00
[analyzer] Improve performance of the SVal simplification mechanism.
When neither LHS nor RHS of a binary operator expression can be simplified, return the original expression instead of re-evaluating the binary operator. Such re-evaluation was causing recusrive re-simplification which caused the algorithmic complexity to explode. Differential Revision: https://reviews.llvm.org/D47155 llvm-svn: 333670
This commit is contained in:
parent
745918ff87
commit
16a1f64ccf
@ -367,6 +367,15 @@ public:
|
||||
return loc::ConcreteInt(BasicVals.getValue(integer));
|
||||
}
|
||||
|
||||
/// Make an SVal that represents the given symbol. This follows the convention
|
||||
/// of representing Loc-type symbols (symbolic pointers and references)
|
||||
/// as Loc values wrapping the symbol rather than as plain symbol values.
|
||||
SVal makeSymbolVal(SymbolRef Sym) {
|
||||
if (Loc::isLocType(Sym->getType()))
|
||||
return makeLoc(Sym);
|
||||
return nonloc::SymbolVal(Sym);
|
||||
}
|
||||
|
||||
/// Return a memory region for the 'this' object reference.
|
||||
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D,
|
||||
const StackFrameContext *SFC);
|
||||
|
@ -1222,6 +1222,10 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
|
||||
ProgramStateRef State;
|
||||
SValBuilder &SVB;
|
||||
|
||||
static bool isUnchanged(SymbolRef Sym, SVal Val) {
|
||||
return Sym == Val.getAsSymbol();
|
||||
}
|
||||
|
||||
public:
|
||||
Simplifier(ProgramStateRef State)
|
||||
: State(State), SVB(State->getStateManager().getSValBuilder()) {}
|
||||
@ -1231,8 +1235,7 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
|
||||
SVB.getKnownValue(State, nonloc::SymbolVal(S)))
|
||||
return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I)
|
||||
: (SVal)SVB.makeIntVal(*I);
|
||||
return Loc::isLocType(S->getType()) ? (SVal)SVB.makeLoc(S)
|
||||
: nonloc::SymbolVal(S);
|
||||
return SVB.makeSymbolVal(S);
|
||||
}
|
||||
|
||||
// TODO: Support SymbolCast. Support IntSymExpr when/if we actually
|
||||
@ -1240,6 +1243,8 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
|
||||
|
||||
SVal VisitSymIntExpr(const SymIntExpr *S) {
|
||||
SVal LHS = Visit(S->getLHS());
|
||||
if (isUnchanged(S->getLHS(), LHS))
|
||||
return SVB.makeSymbolVal(S);
|
||||
SVal RHS;
|
||||
// By looking at the APSInt in the right-hand side of S, we cannot
|
||||
// figure out if it should be treated as a Loc or as a NonLoc.
|
||||
@ -1264,6 +1269,8 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
|
||||
SVal VisitSymSymExpr(const SymSymExpr *S) {
|
||||
SVal LHS = Visit(S->getLHS());
|
||||
SVal RHS = Visit(S->getRHS());
|
||||
if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS))
|
||||
return SVB.makeSymbolVal(S);
|
||||
return SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType());
|
||||
}
|
||||
|
||||
@ -1274,13 +1281,20 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
|
||||
SVal VisitNonLocSymbolVal(nonloc::SymbolVal V) {
|
||||
// Simplification is much more costly than computing complexity.
|
||||
// For high complexity, it may be not worth it.
|
||||
if (V.getSymbol()->computeComplexity() > 100)
|
||||
return V;
|
||||
return Visit(V.getSymbol());
|
||||
}
|
||||
|
||||
SVal VisitSVal(SVal V) { return V; }
|
||||
};
|
||||
|
||||
return Simplifier(State).Visit(V);
|
||||
// A crude way of preventing this function from calling itself from evalBinOp.
|
||||
static bool isReentering = false;
|
||||
if (isReentering)
|
||||
return V;
|
||||
|
||||
isReentering = true;
|
||||
SVal SimplifiedV = Simplifier(State).Visit(V);
|
||||
isReentering = false;
|
||||
|
||||
return SimplifiedV;
|
||||
}
|
||||
|
30
clang/test/Analysis/hangs.c
Normal file
30
clang/test/Analysis/hangs.c
Normal file
@ -0,0 +1,30 @@
|
||||
// RUN: %clang_analyze_cc1 -analyzer-checker core -verify %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
// Stuff that used to hang.
|
||||
|
||||
int g();
|
||||
|
||||
int f(int y) {
|
||||
return y + g();
|
||||
}
|
||||
|
||||
int produce_a_very_large_symbol(int x) {
|
||||
return f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
|
||||
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(x))))))))))))))))))))))))))))))));
|
||||
}
|
||||
|
||||
void produce_an_exponentially_exploding_symbol(int x, int y) {
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
x += y; y += x + g();
|
||||
}
|
Loading…
Reference in New Issue
Block a user