klee
ArrayExprRewriter.cpp
Go to the documentation of this file.
1//===-- ArrayExprRewriter.cpp ---------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
11
12#include "klee/ADT/BitArray.h"
15
16#include <llvm/ADT/APInt.h>
17
18#include <cassert>
19#include <cstdint>
20#include <set>
21#include <utility>
22
23using namespace klee;
24
26ExprRewriter::createOptExpr(const ref<Expr> &e, const array2idx_ty &arrays,
27 const mapIndexOptimizedExpr_ty &idx_valIdx) {
28 return rewrite(e, arrays, idx_valIdx);
29}
30
32 const mapIndexOptimizedExpr_ty &idx_valIdx) {
33 ref<Expr> notFound;
34 std::vector<ref<Expr>> eqExprs;
35 bool invert = false;
36 for (auto &element : arrays) {
37 const Array *arr = element.first;
38 std::vector<ref<Expr>> indexes = element.second;
39
41 idxt_v.visit(e);
42
43 assert((idxt_v.getWidth() % element.first->range == 0) &&
44 "Read is not aligned");
45
46 Expr::Width width = idxt_v.getWidth() / element.first->range;
47 if (auto e = idxt_v.getMul()) {
48 // If we have a MulExpr in the index, we can optimize our search by
49 // skipping all those indexes that are not multiple of such value.
50 // In fact, they will be rejected by the MulExpr interpreter since it
51 // will not find any integer solution
52 auto ce = dyn_cast<ConstantExpr>(e);
53 assert(ce && "Not a constant expression");
54
55 llvm::APInt val = ce->getAPValue();
56 uint64_t mulVal = val.getZExtValue();
57 // So far we try to limit this optimization, but we may try some more
58 // aggressive conditions (i.e. mulVal > width)
59 if (width == 1 && mulVal > 1)
60 width = mulVal;
61 }
62
63 for (std::vector<ref<Expr>>::const_iterator index_it = indexes.begin();
64 index_it != indexes.end(); ++index_it) {
65 if (idx_valIdx.find((*index_it)) == idx_valIdx.end()) {
66 continue;
67 }
68 auto opt_indexes = idx_valIdx.at((*index_it));
69 if (opt_indexes.empty()) {
70 // We continue with other solutions
71 continue;
72 } else if (opt_indexes.size() == 1) {
73 // We treat this case as a special one, and we create an EqExpr (e.g.
74 // k==i)
75 eqExprs.push_back(createEqExpr((*index_it), opt_indexes[0]));
76 } else {
77 Expr::Width idxWidth = (*index_it).get()->getWidth();
78 unsigned set = 0;
79 BitArray ba(arr->size / width);
80 for (auto &vals : opt_indexes) {
81 auto ce = dyn_cast<ConstantExpr>(vals);
82 llvm::APInt v = ce->getAPValue();
83 ba.set(v.getZExtValue() / width);
84 set++;
85 }
86 if (set > 0 && set < arr->size / width)
87 invert =
88 ((float)set / (float)(arr->size / width)) > 0.5 ? true : false;
89 int start = -1;
90 for (unsigned i = 0; i < arr->size / width; ++i) {
91 if ((!invert && ba.get(i)) || (invert && !ba.get(i))) {
92 if (start < 0)
93 start = i;
94 } else {
95 if (start >= 0) {
96 if (i - start == 1) {
97 eqExprs.push_back(createEqExpr(
98 (*index_it),
99 ConstantExpr::create(start * width, idxWidth)));
100 } else {
101 // create range expr
102 ref<Expr> s = ConstantExpr::create(start * width, idxWidth);
103 ref<Expr> e = ConstantExpr::create((i - 1) * width, idxWidth);
104 eqExprs.push_back(createRangeExpr((*index_it), s, e));
105 }
106 start = -1;
107 }
108 }
109 }
110 if (start >= 0) {
111 if ((arr->size / width) - start == 1) {
112 eqExprs.push_back(createEqExpr(
113 (*index_it), ConstantExpr::create(start * width, idxWidth)));
114 } else {
115 // create range expr
116 ref<Expr> s = ConstantExpr::create(start * width, idxWidth);
118 ((arr->size / width) - 1) * width, idxWidth);
119 eqExprs.push_back(createRangeExpr((*index_it), s, e));
120 }
121 }
122 }
123 }
124 }
125 if (eqExprs.empty()) {
126 return notFound;
127 } else if (eqExprs.size() == 1) {
128 if (isa<AndExpr>(eqExprs[0])) {
129 return EqExpr::alloc(
130 ConstantExpr::alloc(invert ? 0 : 1, (eqExprs[0])->getWidth()),
131 eqExprs[0]);
132 }
133 return invert ? NotExpr::alloc(eqExprs[0]) : eqExprs[0];
134 } else {
135 // We have found at least 2 indexes, we combine them using an OrExpr (e.g.
136 // k==i|k==j)
137 ref<Expr> orExpr = concatenateOrExpr(eqExprs.begin(), eqExprs.end());
138 // Create Eq expression for true branch
139 return EqExpr::alloc(
140 ConstantExpr::alloc(invert ? 0 : 1, (orExpr)->getWidth()), orExpr);
141 }
142}
143
145 const std::vector<ref<Expr>>::const_iterator begin,
146 const std::vector<ref<Expr>>::const_iterator end) {
147 if (begin + 2 == end) {
148 return OrExpr::alloc(ZExtExpr::alloc((*begin), Expr::Int32),
149 ZExtExpr::alloc((*(begin + 1)), Expr::Int32));
150 } else {
151 return OrExpr::alloc(ZExtExpr::alloc((*begin), Expr::Int32),
152 concatenateOrExpr(begin + 1, end));
153 }
154}
155
157 const ref<Expr> &valIndex) {
158 return EqExpr::alloc(valIndex, index);
159}
160
162 const ref<Expr> &valStart,
163 const ref<Expr> &valEnd) {
164 return AndExpr::alloc(UleExpr::alloc(valStart, index),
165 UleExpr::alloc(index, valEnd));
166}
const unsigned size
Definition: Expr.h:489
bool get(unsigned idx)
Definition: BitArray.h:34
void set(unsigned idx)
Definition: BitArray.h:35
static ref< ConstantExpr > create(uint64_t v, Width w)
Definition: Expr.h:1079
static ref< ConstantExpr > alloc(const llvm::APInt &v)
Definition: Expr.h:1065
static ref< Expr > createRangeExpr(const ref< Expr > &index, const ref< Expr > &valStart, const ref< Expr > &valEnd)
static ref< Expr > concatenateOrExpr(const std::vector< ref< Expr > >::const_iterator begin, const std::vector< ref< Expr > >::const_iterator end)
static ref< Expr > rewrite(const ref< Expr > &e, const array2idx_ty &arrays, const mapIndexOptimizedExpr_ty &idx_valIdx)
static ref< Expr > createEqExpr(const ref< Expr > &index, const ref< Expr > &valIndex)
ref< Expr > visit(const ref< Expr > &e)
Definition: ExprVisitor.cpp:26
static const Width Int32
Definition: Expr.h:103
unsigned Width
The type of an expression is simply its width, in bits.
Definition: Expr.h:97
static ref< Expr > alloc(const ref< Expr > &e)
Definition: Expr.h:801
Definition: main.cpp:291
std::map< ref< Expr >, std::vector< ref< Expr > > > mapIndexOptimizedExpr_ty
std::map< const Array *, std::vector< ref< Expr > > > array2idx_ty