about summary refs log tree commit diff homepage
path: root/lib/Expr/ArrayExprVisitor.cpp
diff options
context:
space:
mode:
authorAndrea Mattavelli <andreamattavelli@gmail.com>2017-11-22 18:01:29 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2018-10-23 18:53:46 +0300
commit1a9662670ebdef07269e1abfc3f0315bdb33277c (patch)
treeb9cb5938af34aefc6b960d0f666b82a1b29ffde1 /lib/Expr/ArrayExprVisitor.cpp
parenta53fade6e85394ef95dfaaa1c264149e85ea5451 (diff)
downloadklee-1a9662670ebdef07269e1abfc3f0315bdb33277c.tar.gz
Added support for KLEE value-based array optimization
Diffstat (limited to 'lib/Expr/ArrayExprVisitor.cpp')
-rw-r--r--lib/Expr/ArrayExprVisitor.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/lib/Expr/ArrayExprVisitor.cpp b/lib/Expr/ArrayExprVisitor.cpp
index 26ddbb95..fa92b66c 100644
--- a/lib/Expr/ArrayExprVisitor.cpp
+++ b/lib/Expr/ArrayExprVisitor.cpp
@@ -169,3 +169,96 @@ ExprVisitor::Action IndexTransformationExprVisitor::visitMul(const MulExpr &e) {
     mul = e.getKid(1);
   return Action::doChildren();
 }
+
+//-------------------------- VALUE-BASED OPTIMIZATION------------------------//
+ExprVisitor::Action ArrayReadExprVisitor::visitConcat(const ConcatExpr &ce) {
+  ReadExpr *base = ArrayExprHelper::hasOrderedReads(ce);
+  if (base) {
+    return inspectRead(ce.hash(), ce.getWidth(), *base);
+  }
+  return Action::doChildren();
+}
+ExprVisitor::Action ArrayReadExprVisitor::visitRead(const ReadExpr &re) {
+  return inspectRead(re.hash(), re.getWidth(), re);
+}
+// This method is a mess because I want to avoid looping over the UpdateList
+// values twice
+ExprVisitor::Action ArrayReadExprVisitor::inspectRead(unsigned hash,
+                                                      Expr::Width width,
+                                                      const ReadExpr &re) {
+  // pre(*): index is symbolic
+  if (!isa<ConstantExpr>(re.index)) {
+    if (readInfo.find(&re) == readInfo.end()) {
+      if (re.updates.root->isSymbolicArray() && !re.updates.head) {
+        return Action::doChildren();
+      }
+      if (re.updates.head) {
+        // Check preconditions on UpdateList nodes
+        bool hasConcreteValues = false;
+        for (const UpdateNode *un = re.updates.head; un; un = un->next) {
+          // Symbolic case - \inv(update): index is concrete
+          if (!isa<ConstantExpr>(un->index)) {
+            incompatible = true;
+            break;
+          } else if (!isa<ConstantExpr>(un->value)) {
+            // We tell the optimization that there is a symbolic value,
+            // otherwise we rely on the concrete optimization procedure
+            symbolic = true;
+          } else if (re.updates.root->isSymbolicArray() &&
+                     isa<ConstantExpr>(un->value)) {
+            // We can optimize symbolic array, but only if they have
+            // at least one concrete value
+            hasConcreteValues = true;
+          }
+        }
+        // Symbolic case - if array is symbolic, then we need at least one
+        // concrete value
+        if (re.updates.root->isSymbolicArray()) {
+          if (hasConcreteValues)
+            symbolic = true;
+          else
+            incompatible = true;
+        }
+
+        if (incompatible)
+          return Action::skipChildren();
+      }
+      symbolic |= re.updates.root->isSymbolicArray();
+      reads.push_back(&re);
+      readInfo.emplace(&re, std::make_pair(hash, width));
+    }
+    return Action::skipChildren();
+  }
+  return Action::doChildren();
+}
+
+ExprVisitor::Action
+ArrayValueOptReplaceVisitor::visitConcat(const ConcatExpr &ce) {
+  auto found = optimized.find(ce.hash());
+  if (found != optimized.end()) {
+    return Action::changeTo((*found).second.get());
+  }
+  return Action::doChildren();
+}
+ExprVisitor::Action ArrayValueOptReplaceVisitor::visitRead(const ReadExpr &re) {
+  auto found = optimized.find(re.hash());
+  if (found != optimized.end()) {
+    return Action::changeTo((*found).second.get());
+  }
+  return Action::doChildren();
+}
+
+ExprVisitor::Action IndexCleanerVisitor::visitMul(const MulExpr &e) {
+  if (mul) {
+    if (!isa<ConstantExpr>(e.getKid(0)))
+      index = e.getKid(0);
+    else if (!isa<ConstantExpr>(e.getKid(1)))
+      index = e.getKid(1);
+    mul = false;
+  }
+  return Action::doChildren();
+}
+ExprVisitor::Action IndexCleanerVisitor::visitRead(const ReadExpr &re) {
+  mul = false;
+  return Action::doChildren();
+}