about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Solver/FastCexSolver.cpp66
1 files changed, 60 insertions, 6 deletions
diff --git a/lib/Solver/FastCexSolver.cpp b/lib/Solver/FastCexSolver.cpp
index 6882682a..ea5427e3 100644
--- a/lib/Solver/FastCexSolver.cpp
+++ b/lib/Solver/FastCexSolver.cpp
@@ -732,6 +732,8 @@ public:
   }
 
   void propogateExactValues(ref<Expr> e, CexValueData range) {
+    //llvm::cout << e << " \\in " << range << "\n";
+
     switch (e->getKind()) {
     case Expr::Constant: {
       // FIXME: Assert that range contains this constant.
@@ -743,6 +745,37 @@ public:
     case Expr::NotOptimized: break;
 
     case Expr::Read: {
+      ReadExpr *re = cast<ReadExpr>(e);
+      const Array *array = re->updates.root;
+      CexObjectData &cod = getObjectData(array);
+      CexValueData index = evalRangeForExpr(re->index);
+        
+      for (const UpdateNode *un = re->updates.head; un; un = un->next) {
+        CexValueData ui = evalRangeForExpr(un->index);
+
+        // If these indices can't alias, continue propogation
+        if (!ui.mayEqual(index))
+          continue;
+
+        // Otherwise if we know they alias, propogate into the write value.
+        if (ui.mustEqual(index) || re->index == un->index)
+          propogateExactValues(un->value, range);
+        return;
+      }
+
+      // We reached the initial array write, update the exact range if possible.
+      if (index.isFixed()) {
+        CexValueData cvd = cod.getExactValues(index.min());
+        if (range.min() > cvd.min()) {
+          assert(range.min() <= cvd.max());
+          cvd = CexValueData(range.min(), cvd.max());
+        }
+        if (range.max() < cvd.max()) {
+          assert(range.max() >= cvd.min());
+          cvd = CexValueData(cvd.min(), range.max());
+        }
+        cod.setExactValues(index.min(), cvd);
+      }
       break;
     }
 
@@ -785,6 +818,22 @@ public:
       // Comparison
 
     case Expr::Eq: {
+      BinaryExpr *be = cast<BinaryExpr>(e);
+      if (range.isFixed()) {
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left)) {
+          uint64_t value = CE->getConstantValue();
+          if (range.min()) {
+            // If the equality is true, then propogate the value.
+            propogateExactValue(be->right, value);
+          } else {
+            // If the equality is false and the comparison is of booleans, then
+            // we can infer the value to propogate.
+            if (be->right->getWidth() == Expr::Bool) {
+              propogateExactValue(be->right, !value);
+            }
+          }
+        }
+      }
       break;
     }
 
@@ -808,7 +857,7 @@ public:
     }
   }
 
-  ValueRange evalRangeForExpr(ref<Expr> &e) {
+  ValueRange evalRangeForExpr(const ref<Expr> &e) {
     CexRangeEvaluator ce(objects);
     return ce.evaluate(e);
   }
@@ -871,9 +920,10 @@ static bool propogateValues(const Query& query, CexData &cd,
   }
 
   // Check the result.
+  bool hasSatisfyingAssignment = true;
   if (checkExpr) {
     if (!cd.evaluatePossible(query.expr)->isFalse())
-      return false;
+      hasSatisfyingAssignment = false;
 
     // If the query is known to be true, then we have proved validity.
     if (cd.evaluateExact(query.expr)->isTrue()) {
@@ -884,8 +934,8 @@ static bool propogateValues(const Query& query, CexData &cd,
 
   for (ConstraintManager::const_iterator it = query.constraints.begin(), 
          ie = query.constraints.end(); it != ie; ++it) {
-    if (!cd.evaluatePossible(*it)->isTrue())
-      return false;
+    if (hasSatisfyingAssignment && !cd.evaluatePossible(*it)->isTrue())
+      hasSatisfyingAssignment = false;
 
     // If this constraint is known to be false, then we can prove anything, so
     // the query is valid.
@@ -895,8 +945,12 @@ static bool propogateValues(const Query& query, CexData &cd,
     }
   }
 
-  isValid = false;
-  return true;
+  if (hasSatisfyingAssignment) {
+    isValid = false;
+    return true;
+  }
+
+  return false;
 }
 
 IncompleteSolver::PartialValidity