diff options
author | Andrea Mattavelli <andreamattavelli@gmail.com> | 2017-11-22 18:01:29 +0000 |
---|---|---|
committer | Cristian Cadar <c.cadar@imperial.ac.uk> | 2018-10-23 18:53:46 +0300 |
commit | 1a9662670ebdef07269e1abfc3f0315bdb33277c (patch) | |
tree | b9cb5938af34aefc6b960d0f666b82a1b29ffde1 /lib/Expr/ArrayExprVisitor.cpp | |
parent | a53fade6e85394ef95dfaaa1c264149e85ea5451 (diff) | |
download | klee-1a9662670ebdef07269e1abfc3f0315bdb33277c.tar.gz |
Added support for KLEE value-based array optimization
Diffstat (limited to 'lib/Expr/ArrayExprVisitor.cpp')
-rw-r--r-- | lib/Expr/ArrayExprVisitor.cpp | 93 |
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(); +} |