diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-06-20 22:21:56 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-06-20 22:21:56 +0000 |
commit | 40238f04511443300a9470f97e0078a1c6538a18 (patch) | |
tree | 76a85dbf2809274f2e4cc4b62599a0e2fb17666c /clang/lib/Sema/SemaChecking.cpp | |
parent | 1efb69cdcaefea30be95beec8b4aa23f29dbf31c (diff) | |
download | bcm5719-llvm-40238f04511443300a9470f97e0078a1c6538a18.tar.gz bcm5719-llvm-40238f04511443300a9470f97e0078a1c6538a18.zip |
Avoid repeatedly evaluating subexpressions when checking for unsequenced
operations in the case where evaluating a subexpression fails. No functionality
change, but test/Sema/many-logical-ops.c gets ~100x faster with this change.
llvm-svn: 184489
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 729de0d1cd8..deb1ba1ba76 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5387,6 +5387,35 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { llvm::SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect; }; + /// RAII object wrapping the visitation of a subexpression which we might + /// choose to evaluate as a constant. If any subexpression is evaluated and + /// found to be non-constant, this allows us to suppress the evaluation of + /// the outer expression. + class EvaluationTracker { + public: + EvaluationTracker(SequenceChecker &Self) + : Self(Self), Prev(Self.EvalTracker), EvalOK(true) { + Self.EvalTracker = this; + } + ~EvaluationTracker() { + Self.EvalTracker = Prev; + if (Prev) + Prev->EvalOK &= EvalOK; + } + + bool evaluate(const Expr *E, bool &Result) { + if (!EvalOK || E->isValueDependent()) + return false; + EvalOK = E->EvaluateAsBooleanCondition(Result, Self.SemaRef.Context); + return EvalOK; + } + + private: + SequenceChecker &Self; + EvaluationTracker *Prev; + bool EvalOK; + } *EvalTracker; + /// \brief Find the object which is produced by the specified expression, /// if any. Object getObject(Expr *E, bool Mod) const { @@ -5468,7 +5497,8 @@ public: SequenceChecker(Sema &S, Expr *E, llvm::SmallVectorImpl<Expr*> &WorkList) : EvaluatedExprVisitor<SequenceChecker>(S.Context), SemaRef(S), - Region(Tree.root()), ModAsSideEffect(0), WorkList(WorkList) { + Region(Tree.root()), ModAsSideEffect(0), WorkList(WorkList), + EvalTracker(0) { Visit(E); } @@ -5581,14 +5611,14 @@ public: // value computation of the RHS, and hence before the value computation // of the '&&' itself, unless the LHS evaluates to zero. We treat them // as if they were unconditionally sequenced. + EvaluationTracker Eval(*this); { SequencedSubexpression Sequenced(*this); Visit(BO->getLHS()); } bool Result; - if (!BO->getLHS()->isValueDependent() && - BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) { + if (Eval.evaluate(BO->getLHS(), Result)) { if (!Result) Visit(BO->getRHS()); } else { @@ -5602,14 +5632,14 @@ public: } } void VisitBinLAnd(BinaryOperator *BO) { + EvaluationTracker Eval(*this); { SequencedSubexpression Sequenced(*this); Visit(BO->getLHS()); } bool Result; - if (!BO->getLHS()->isValueDependent() && - BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) { + if (Eval.evaluate(BO->getLHS(), Result)) { if (Result) Visit(BO->getRHS()); } else { @@ -5620,12 +5650,12 @@ public: // Only visit the condition, unless we can be sure which subexpression will // be chosen. void VisitAbstractConditionalOperator(AbstractConditionalOperator *CO) { + EvaluationTracker Eval(*this); SequencedSubexpression Sequenced(*this); Visit(CO->getCond()); bool Result; - if (!CO->getCond()->isValueDependent() && - CO->getCond()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) + if (Eval.evaluate(CO->getCond(), Result)) Visit(Result ? CO->getTrueExpr() : CO->getFalseExpr()); else { WorkList.push_back(CO->getTrueExpr()); |