]> granicus.if.org Git - clang/commitdiff
Avoid repeatedly evaluating subexpressions when checking for unsequenced
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 20 Jun 2013 22:21:56 +0000 (22:21 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 20 Jun 2013 22:21:56 +0000 (22:21 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184489 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaChecking.cpp

index 729de0d1cd891ce8c4ef44a669cbcbac5da7fec1..deb1ba1ba76fe19fd5d6f499d5c5ab9fadf41aed 100644 (file)
@@ -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());