klee
STPBuilder.cpp
Go to the documentation of this file.
1//===-- STPBuilder.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#include "klee/Config/config.h"
10#ifdef ENABLE_STP
11#include "STPBuilder.h"
12
13#include "klee/ADT/Bits.h"
14#include "klee/Expr/Expr.h"
15#include "klee/Solver/Solver.h"
17
18#include "ConstantDivision.h"
19
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/Support/CommandLine.h"
22
23#include <cstdio>
24
25#define vc_bvBoolExtract IAMTHESPAWNOFSATAN
26// unclear return
27#define vc_bvLeftShiftExpr IAMTHESPAWNOFSATAN
28#define vc_bvRightShiftExpr IAMTHESPAWNOFSATAN
29// bad refcnt'ng
30#define vc_bvVar32LeftShiftExpr IAMTHESPAWNOFSATAN
31#define vc_bvVar32RightShiftExpr IAMTHESPAWNOFSATAN
32#define vc_bvVar32DivByPowOfTwoExpr IAMTHESPAWNOFSATAN
33#define vc_bvCreateMemoryArray IAMTHESPAWNOFSATAN
34#define vc_bvReadMemoryArray IAMTHESPAWNOFSATAN
35#define vc_bvWriteToMemoryArray IAMTHESPAWNOFSATAN
36
37#include <algorithm> // max, min
38#include <cassert>
39#include <map>
40#include <sstream>
41#include <vector>
42
43using namespace klee;
44
45namespace {
46 llvm::cl::opt<bool>
47 UseConstructHash("use-construct-hash-stp",
48 llvm::cl::desc("Use hash-consing during STP query construction (default=true)"),
49 llvm::cl::init(true),
50 llvm::cl::cat(klee::ExprCat));
51}
52
54
55
56STPArrayExprHash::~STPArrayExprHash() {
57 for (ArrayHashIter it = _array_hash.begin(); it != _array_hash.end(); ++it) {
58 ::VCExpr array_expr = it->second;
59 if (array_expr) {
60 ::vc_DeleteExpr(array_expr);
61 array_expr = 0;
62 }
63 }
64
65
67 it != _update_node_hash.end(); ++it) {
68 ::VCExpr un_expr = it->second;
69 if (un_expr) {
70 ::vc_DeleteExpr(un_expr);
71 un_expr = 0;
72 }
73 }
74}
75
76/***/
77
78STPBuilder::STPBuilder(::VC _vc, bool _optimizeDivides)
79 : vc(_vc), optimizeDivides(_optimizeDivides) {
80
81}
82
83STPBuilder::~STPBuilder() {
84
85}
86
88
89/* Warning: be careful about what c_interface functions you use. Some of
90 them look like they cons memory but in fact don't, which is bad when
91 you call vc_DeleteExpr on them. */
92
93::VCExpr STPBuilder::buildVar(const char *name, unsigned width) {
94 // XXX don't rebuild if this stuff cons's
95 ::Type t = (width==1) ? vc_boolType(vc) : vc_bvType(vc, width);
96 ::VCExpr res = vc_varExpr(vc, const_cast<char*>(name), t);
98 return res;
99}
100
101::VCExpr STPBuilder::buildArray(const char *name, unsigned indexWidth, unsigned valueWidth) {
102 // XXX don't rebuild if this stuff cons's
103 ::Type t1 = vc_bvType(vc, indexWidth);
104 ::Type t2 = vc_bvType(vc, valueWidth);
105 ::Type t = vc_arrayType(vc, t1, t2);
106 ::VCExpr res = vc_varExpr(vc, const_cast<char*>(name), t);
107 vc_DeleteExpr(t);
108 vc_DeleteExpr(t2);
109 vc_DeleteExpr(t1);
110 return res;
111}
112
114 return vc_trueExpr(vc);
115}
117 return vc_falseExpr(vc);
118}
119ExprHandle STPBuilder::bvOne(unsigned width) {
120 return bvZExtConst(width, 1);
121}
122ExprHandle STPBuilder::bvZero(unsigned width) {
123 return bvZExtConst(width, 0);
124}
125ExprHandle STPBuilder::bvMinusOne(unsigned width) {
126 return bvSExtConst(width, (int64_t) -1);
127}
128ExprHandle STPBuilder::bvConst32(unsigned width, uint32_t value) {
129 return vc_bvConstExprFromInt(vc, width, value);
130}
131ExprHandle STPBuilder::bvConst64(unsigned width, uint64_t value) {
132 return vc_bvConstExprFromLL(vc, width, value);
133}
134ExprHandle STPBuilder::bvZExtConst(unsigned width, uint64_t value) {
135 if (width <= 64)
136 return bvConst64(width, value);
137
138 ExprHandle expr = bvConst64(64, value), zero = bvConst64(64, 0);
139 for (width -= 64; width > 64; width -= 64)
140 expr = vc_bvConcatExpr(vc, zero, expr);
141 return vc_bvConcatExpr(vc, bvConst64(width, 0), expr);
142}
143ExprHandle STPBuilder::bvSExtConst(unsigned width, uint64_t value) {
144 if (width <= 64)
145 return bvConst64(width, value);
146 return vc_bvSignExtend(vc, bvConst64(64, value), width);
147}
148
150 return vc_eqExpr(vc, bvExtract(expr, bit, bit), bvOne(1));
151}
152ExprHandle STPBuilder::bvExtract(ExprHandle expr, unsigned top, unsigned bottom) {
153 return vc_bvExtract(vc, expr, top, bottom);
154}
156 assert((vc_getBVLength(vc, a) == vc_getBVLength(vc, b)) && "a and b should be same type");
157 return vc_eqExpr(vc, a, b);
158}
159
160// logical right shift
161ExprHandle STPBuilder::bvRightShift(ExprHandle expr, unsigned shift) {
162 unsigned width = vc_getBVLength(vc, expr);
163
164 if (shift==0) {
165 return expr;
166 } else if (shift>=width) {
167 return bvZero(width); // Overshift to zero
168 } else {
169 return vc_bvConcatExpr(vc,
170 bvZero(shift),
171 bvExtract(expr, width - 1, shift));
172 }
173}
174
175// logical left shift
176ExprHandle STPBuilder::bvLeftShift(ExprHandle expr, unsigned shift) {
177 unsigned width = vc_getBVLength(vc, expr);
178
179 if (shift==0) {
180 return expr;
181 } else if (shift>=width) {
182 return bvZero(width); // Overshift to zero
183 } else {
184 // stp shift does "expr @ [0 x s]" which we then have to extract,
185 // rolling our own gives slightly smaller exprs
186 return vc_bvConcatExpr(vc,
187 bvExtract(expr, width - shift - 1, 0),
188 bvZero(shift));
189 }
190}
191
193 unsigned width,
194 unsigned &shiftBits) {
195 // Assuming width is power of 2
196 llvm::APInt sw(32, width);
197 shiftBits = sw.getActiveBits();
198
199 // get the shift amount (looking only at the bits appropriate for the given
200 // width)
201 return vc_bvExtract(vc, shift, shiftBits - 1, 0);
202}
203
204// left shift by a variable amount on an expression of the specified width
206 unsigned width = vc_getBVLength(vc, expr);
207 ExprHandle res = bvZero(width);
208
209 unsigned shiftBits = 0;
210 ExprHandle shift_ext = extractPartialShiftValue(shift, width, shiftBits);
211
212 // construct a big if-then-elif-elif-... with one case per possible shift
213 // amount
214 for (int i = width - 1; i >= 0; i--) {
215 res = vc_iteExpr(vc, eqExpr(shift_ext, bvConst32(shiftBits, i)),
216 bvLeftShift(expr, i), res);
217 }
218
219 // If overshifting, shift to zero
220 ExprHandle ex =
221 vc_bvLtExpr(vc, shift, bvConst32(vc_getBVLength(vc, shift), width));
222
223 res = vc_iteExpr(vc, ex, res, bvZero(width));
224 return res;
225}
226
227// logical right shift by a variable amount on an expression of the specified
228// width
230 unsigned width = vc_getBVLength(vc, expr);
231 ExprHandle res = bvZero(width);
232
233 unsigned shiftBits = 0;
234 ExprHandle shift_ext = extractPartialShiftValue(shift, width, shiftBits);
235
236 // construct a big if-then-elif-elif-... with one case per possible shift
237 // amount
238 for (int i = width - 1; i >= 0; i--) {
239 res = vc_iteExpr(vc, eqExpr(shift_ext, bvConst32(shiftBits, i)),
240 bvRightShift(expr, i), res);
241 }
242
243 // If overshifting, shift to zero
244 // If overshifting, shift to zero
245 ExprHandle ex =
246 vc_bvLtExpr(vc, shift, bvConst32(vc_getBVLength(vc, shift), width));
247 res = vc_iteExpr(vc, ex, res, bvZero(width));
248
249 return res;
250}
251
252// arithmetic right shift by a variable amount on an expression of the specified
253// width
255 unsigned width = vc_getBVLength(vc, expr);
256
257 unsigned shiftBits = 0;
258 ExprHandle shift_ext = extractPartialShiftValue(shift, width, shiftBits);
259
260 // get the sign bit to fill with
261 ExprHandle signedBool = bvBoolExtract(expr, width - 1);
262
263 // start with the result if shifting by width-1
264 ExprHandle res = constructAShrByConstant(expr, width - 1, signedBool);
265
266 // construct a big if-then-elif-elif-... with one case per possible shift
267 // amount
268 // XXX more efficient to move the ite on the sign outside all exprs?
269 // XXX more efficient to sign extend, right shift, then extract lower bits?
270 for (int i = width - 2; i >= 0; i--) {
271 res = vc_iteExpr(vc, eqExpr(shift_ext, bvConst32(shiftBits, i)),
272 constructAShrByConstant(expr, i, signedBool), res);
273 }
274
275 // If overshifting, shift to zero
276 ExprHandle ex =
277 vc_bvLtExpr(vc, shift, bvConst32(vc_getBVLength(vc, shift), width));
278 res = vc_iteExpr(vc, ex, res, bvZero(width));
279 return res;
280}
281
283 unsigned shift,
284 ExprHandle isSigned) {
285 unsigned width = vc_getBVLength(vc, expr);
286
287 if (shift==0) {
288 return expr;
289 } else if (shift>=width) {
290 return bvZero(width); // Overshift to zero
291 } else {
292 return vc_iteExpr(vc,
293 isSigned,
294 ExprHandle(vc_bvConcatExpr(vc,
295 bvMinusOne(shift),
296 bvExtract(expr, width - 1, shift))),
297 bvRightShift(expr, shift));
298 }
299}
300
301ExprHandle STPBuilder::constructMulByConstant(ExprHandle expr, unsigned width, uint64_t x) {
302 uint64_t add, sub;
303 ExprHandle res = 0;
304
305 // expr*x == expr*(add-sub) == expr*add - expr*sub
307
308 // legal, these would overflow completely
311
312 for (int j=63; j>=0; j--) {
313 uint64_t bit = 1LL << j;
314
315 if ((add&bit) || (sub&bit)) {
316 assert(!((add&bit) && (sub&bit)) && "invalid mult constants");
317 ExprHandle op = bvLeftShift(expr, j);
318
319 if (add&bit) {
320 if (res) {
321 res = vc_bvPlusExpr(vc, width, res, op);
322 } else {
323 res = op;
324 }
325 } else {
326 if (res) {
327 res = vc_bvMinusExpr(vc, width, res, op);
328 } else {
329 res = vc_bvUMinusExpr(vc, op);
330 }
331 }
332 }
333 }
334
335 if (!res)
336 res = bvZero(width);
337
338 return res;
339}
340
341/*
342 * Compute the 32-bit unsigned integer division of n by a divisor d based on
343 * the constants derived from the constant divisor d.
344 *
345 * Returns n/d without doing explicit division. The cost is 2 adds, 3 shifts,
346 * and a (64-bit) multiply.
347 *
348 * @param n numerator (dividend) as an expression
349 * @param width number of bits used to represent the value
350 * @param d the divisor
351 *
352 * @return n/d without doing explicit division
353 */
354ExprHandle STPBuilder::constructUDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d) {
355 assert(width==32 && "can only compute udiv constants for 32-bit division");
356
357 // Compute the constants needed to compute n/d for constant d w/o
358 // division by d.
359 uint32_t mprime, sh1, sh2;
360 ComputeUDivConstants32(d, mprime, sh1, sh2);
361 ExprHandle expr_sh1 = bvConst32( 32, sh1);
362 ExprHandle expr_sh2 = bvConst32( 32, sh2);
363
364 // t1 = MULUH(mprime, n) = ( (uint64_t)mprime * (uint64_t)n ) >> 32
365 ExprHandle expr_n_64 = vc_bvConcatExpr( vc, bvZero(32), expr_n ); //extend to 64 bits
366 ExprHandle t1_64bits = constructMulByConstant( expr_n_64, 64, (uint64_t)mprime );
367 ExprHandle t1 = vc_bvExtract( vc, t1_64bits, 63, 32 ); //upper 32 bits
368
369 // n/d = (((n - t1) >> sh1) + t1) >> sh2;
370 ExprHandle n_minus_t1 = vc_bvMinusExpr( vc, width, expr_n, t1 );
371 ExprHandle shift_sh1 = bvVarRightShift( n_minus_t1, expr_sh1);
372 ExprHandle plus_t1 = vc_bvPlusExpr( vc, width, shift_sh1, t1 );
373 ExprHandle res = bvVarRightShift( plus_t1, expr_sh2);
374
375 return res;
376}
377
378/*
379 * Compute the 32-bitnsigned integer division of n by a divisor d based on
380 * the constants derived from the constant divisor d.
381 *
382 * Returns n/d without doing explicit division. The cost is 3 adds, 3 shifts,
383 * a (64-bit) multiply, and an XOR.
384 *
385 * @param n numerator (dividend) as an expression
386 * @param width number of bits used to represent the value
387 * @param d the divisor
388 *
389 * @return n/d without doing explicit division
390 */
391ExprHandle STPBuilder::constructSDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d) {
392 // Refactor using APInt::ms APInt::magic();
393 assert(width==32 && "can only compute udiv constants for 32-bit division");
394
395 // Compute the constants needed to compute n/d for constant d w/o division by d.
396 int32_t mprime, dsign, shpost;
397 ComputeSDivConstants32(d, mprime, dsign, shpost);
398 ExprHandle expr_dsign = bvConst32( 32, dsign);
399 ExprHandle expr_shpost = bvConst32( 32, shpost);
400
401 // q0 = n + MULSH( mprime, n ) = n + (( (int64_t)mprime * (int64_t)n ) >> 32)
402 int64_t mprime_64 = (int64_t)mprime;
403
404 ExprHandle expr_n_64 = vc_bvSignExtend( vc, expr_n, 64 );
405 ExprHandle mult_64 = constructMulByConstant( expr_n_64, 64, mprime_64 );
406 ExprHandle mulsh = vc_bvExtract( vc, mult_64, 63, 32 ); //upper 32-bits
407 ExprHandle n_plus_mulsh = vc_bvPlusExpr( vc, width, expr_n, mulsh );
408
409 // Improved variable arithmetic right shift: sign extend, shift,
410 // extract.
411 ExprHandle extend_npm = vc_bvSignExtend( vc, n_plus_mulsh, 64 );
412 ExprHandle shift_npm = bvVarRightShift( extend_npm, expr_shpost);
413 ExprHandle shift_shpost = vc_bvExtract( vc, shift_npm, 31, 0 ); //lower 32-bits
414
415 // XSIGN(n) is -1 if n is negative, positive one otherwise
416 ExprHandle is_signed = bvBoolExtract( expr_n, 31 );
417 ExprHandle neg_one = bvMinusOne(32);
418 ExprHandle xsign_of_n = vc_iteExpr( vc, is_signed, neg_one, bvZero(32) );
419
420 // q0 = (n_plus_mulsh >> shpost) - XSIGN(n)
421 ExprHandle q0 = vc_bvMinusExpr( vc, width, shift_shpost, xsign_of_n );
422
423 // n/d = (q0 ^ dsign) - dsign
424 ExprHandle q0_xor_dsign = vc_bvXorExpr( vc, q0, expr_dsign );
425 ExprHandle res = vc_bvMinusExpr( vc, width, q0_xor_dsign, expr_dsign );
426
427 return res;
428}
429
430::VCExpr STPBuilder::getInitialArray(const Array *root) {
431
432 assert(root);
433 ::VCExpr array_expr;
434 bool hashed = _arr_hash.lookupArrayExpr(root, array_expr);
435
436 if (!hashed) {
437 // STP uniques arrays by name, so we make sure the name is unique by
438 // using the size of the array hash as a counter.
439 std::string unique_id = llvm::utostr(_arr_hash._array_hash.size());
440 std::string unique_name = root->name + unique_id;
441
442 array_expr = buildArray(unique_name.c_str(), root->getDomain(),
443 root->getRange());
444
445 if (root->isConstantArray()) {
446 // FIXME: Flush the concrete values into STP. Ideally we would do this
447 // using assertions, which is much faster, but we need to fix the caching
448 // to work correctly in that case.
449 for (unsigned i = 0, e = root->size; i != e; ++i) {
450 ::VCExpr prev = array_expr;
451 array_expr = vc_writeExpr(vc, prev,
453 construct(root->constantValues[i], 0));
454 vc_DeleteExpr(prev);
455 }
456 }
457
458 _arr_hash.hashArrayExpr(root, array_expr);
459 }
460
461 return array_expr;
462}
463
464ExprHandle STPBuilder::getInitialRead(const Array *root, unsigned index) {
465 return vc_readExpr(vc, getInitialArray(root), bvConst32(32, index));
466}
467
468::VCExpr STPBuilder::getArrayForUpdate(const Array *root,
469 const UpdateNode *un) {
470 if (!un) {
471 return getInitialArray(root);
472 }
473 else {
474 // FIXME: This really needs to be non-recursive.
475 ::VCExpr un_expr;
476 bool hashed = _arr_hash.lookupUpdateNodeExpr(un, un_expr);
477
478 if (!hashed) {
479 un_expr =
480 vc_writeExpr(vc, getArrayForUpdate(root, un->next.get()),
481 construct(un->index, 0), construct(un->value, 0));
482
483 _arr_hash.hashUpdateNodeExpr(un, un_expr);
484 }
485
486 return un_expr;
487 }
488}
489
492ExprHandle STPBuilder::construct(ref<Expr> e, int *width_out) {
493 if (!UseConstructHash || isa<ConstantExpr>(e)) {
494 return constructActual(e, width_out);
495 } else {
497 constructed.find(e);
498 if (it!=constructed.end()) {
499 if (width_out)
500 *width_out = it->second.second;
501 return it->second.first;
502 } else {
503 int width;
504 if (!width_out) width_out = &width;
505 ExprHandle res = constructActual(e, width_out);
506 constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
507 return res;
508 }
509 }
510}
511
512
516 int width;
517 if (!width_out) width_out = &width;
518
520
521 switch (e->getKind()) {
522 case Expr::Constant: {
523 ConstantExpr *CE = cast<ConstantExpr>(e);
524 *width_out = CE->getWidth();
525
526 // Coerce to bool if necessary.
527 if (*width_out == 1)
528 return CE->isTrue() ? getTrue() : getFalse();
529
530 // Fast path.
531 if (*width_out <= 32)
532 return bvConst32(*width_out, CE->getZExtValue(32));
533 if (*width_out <= 64)
534 return bvConst64(*width_out, CE->getZExtValue());
535
536 ref<ConstantExpr> Tmp = CE;
537 ExprHandle Res = bvConst64(64, Tmp->Extract(0, 64)->getZExtValue());
538 while (Tmp->getWidth() > 64) {
539 Tmp = Tmp->Extract(64, Tmp->getWidth()-64);
540 unsigned Width = std::min(64U, Tmp->getWidth());
541 Res = vc_bvConcatExpr(vc, bvConst64(Width,
542 Tmp->Extract(0, Width)->getZExtValue()),
543 Res);
544 }
545 return Res;
546 }
547
548 // Special
549 case Expr::NotOptimized: {
550 NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
551 return construct(noe->src, width_out);
552 }
553
554 case Expr::Read: {
555 ReadExpr *re = cast<ReadExpr>(e);
556 assert(re && re->updates.root);
557 *width_out = re->updates.root->getRange();
558 return vc_readExpr(
559 vc, getArrayForUpdate(re->updates.root, re->updates.head.get()),
560 construct(re->index, 0));
561 }
562
563 case Expr::Select: {
564 SelectExpr *se = cast<SelectExpr>(e);
565 ExprHandle cond = construct(se->cond, 0);
566 ExprHandle tExpr = construct(se->trueExpr, width_out);
567 ExprHandle fExpr = construct(se->falseExpr, width_out);
568 return vc_iteExpr(vc, cond, tExpr, fExpr);
569 }
570
571 case Expr::Concat: {
572 ConcatExpr *ce = cast<ConcatExpr>(e);
573 unsigned numKids = ce->getNumKids();
574 ExprHandle res = construct(ce->getKid(numKids-1), 0);
575 for (int i=numKids-2; i>=0; i--) {
576 res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0), res);
577 }
578 *width_out = ce->getWidth();
579 return res;
580 }
581
582 case Expr::Extract: {
583 ExtractExpr *ee = cast<ExtractExpr>(e);
584 ExprHandle src = construct(ee->expr, width_out);
585 *width_out = ee->getWidth();
586 if (*width_out==1) {
587 return bvBoolExtract(src, ee->offset);
588 } else {
589 return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset);
590 }
591 }
592
593 // Casting
594
595 case Expr::ZExt: {
596 int srcWidth;
597 CastExpr *ce = cast<CastExpr>(e);
598 ExprHandle src = construct(ce->src, &srcWidth);
599 *width_out = ce->getWidth();
600 if (srcWidth==1) {
601 return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out));
602 } else {
603 return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src);
604 }
605 }
606
607 case Expr::SExt: {
608 int srcWidth;
609 CastExpr *ce = cast<CastExpr>(e);
610 ExprHandle src = construct(ce->src, &srcWidth);
611 *width_out = ce->getWidth();
612 if (srcWidth==1) {
613 return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out));
614 } else {
615 return vc_bvSignExtend(vc, src, *width_out);
616 }
617 }
618
619 // Arithmetic
620
621 case Expr::Add: {
622 AddExpr *ae = cast<AddExpr>(e);
623 ExprHandle left = construct(ae->left, width_out);
624 ExprHandle right = construct(ae->right, width_out);
625 assert(*width_out!=1 && "uncanonicalized add");
626 return vc_bvPlusExpr(vc, *width_out, left, right);
627 }
628
629 case Expr::Sub: {
630 SubExpr *se = cast<SubExpr>(e);
631 ExprHandle left = construct(se->left, width_out);
632 ExprHandle right = construct(se->right, width_out);
633 assert(*width_out!=1 && "uncanonicalized sub");
634 return vc_bvMinusExpr(vc, *width_out, left, right);
635 }
636
637 case Expr::Mul: {
638 MulExpr *me = cast<MulExpr>(e);
639 ExprHandle right = construct(me->right, width_out);
640 assert(*width_out!=1 && "uncanonicalized mul");
641
642 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left))
643 if (CE->getWidth() <= 64)
644 return constructMulByConstant(right, *width_out,
645 CE->getZExtValue());
646
647 ExprHandle left = construct(me->left, width_out);
648 return vc_bvMultExpr(vc, *width_out, left, right);
649 }
650
651 case Expr::UDiv: {
652 UDivExpr *de = cast<UDivExpr>(e);
653 ExprHandle left = construct(de->left, width_out);
654 assert(*width_out!=1 && "uncanonicalized udiv");
655
656 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
657 if (CE->getWidth() <= 64) {
658 uint64_t divisor = CE->getZExtValue();
659
660 if (bits64::isPowerOfTwo(divisor)) {
661 return bvRightShift(left,
662 bits64::indexOfSingleBit(divisor));
663 } else if (optimizeDivides) {
664 if (*width_out == 32) //only works for 32-bit division
665 return constructUDivByConstant( left, *width_out,
666 (uint32_t) divisor);
667 }
668 }
669 }
670
671 ExprHandle right = construct(de->right, width_out);
672 return vc_bvDivExpr(vc, *width_out, left, right);
673 }
674
675 case Expr::SDiv: {
676 SDivExpr *de = cast<SDivExpr>(e);
677 ExprHandle left = construct(de->left, width_out);
678 assert(*width_out!=1 && "uncanonicalized sdiv");
679
680 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right))
681 if (optimizeDivides) {
682 llvm::APInt divisor = CE->getAPValue();
683 if (divisor != llvm::APInt(CE->getWidth(),1, false /*unsigned*/) &&
684 divisor != llvm::APInt(CE->getWidth(), -1, true /*signed*/))
685 if (*width_out == 32) //only works for 32-bit division
686 return constructSDivByConstant( left, *width_out,
687 CE->getZExtValue(32));
688 }
689 // XXX need to test for proper handling of sign, not sure I
690 // trust STP
691 ExprHandle right = construct(de->right, width_out);
692 return vc_sbvDivExpr(vc, *width_out, left, right);
693 }
694
695 case Expr::URem: {
696 URemExpr *de = cast<URemExpr>(e);
697 ExprHandle left = construct(de->left, width_out);
698 assert(*width_out!=1 && "uncanonicalized urem");
699
700 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
701 if (CE->getWidth() <= 64) {
702 uint64_t divisor = CE->getZExtValue();
703
704 if (bits64::isPowerOfTwo(divisor)) {
705 unsigned bits = bits64::indexOfSingleBit(divisor);
706
707 // special case for modding by 1 or else we bvExtract -1:0
708 if (bits == 0) {
709 return bvZero(*width_out);
710 } else {
711 return vc_bvConcatExpr(vc,
712 bvZero(*width_out - bits),
713 bvExtract(left, bits - 1, 0));
714 }
715 }
716
717 // Use fast division to compute modulo without explicit division for
718 // constant divisor.
719
720 if (optimizeDivides) {
721 if (*width_out == 32) { //only works for 32-bit division
722 ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor );
723 ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
724 ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
725 return rem;
726 }
727 }
728 }
729 }
730
731 ExprHandle right = construct(de->right, width_out);
732 return vc_bvModExpr(vc, *width_out, left, right);
733 }
734
735 case Expr::SRem: {
736 SRemExpr *de = cast<SRemExpr>(e);
737 ExprHandle left = construct(de->left, width_out);
738 ExprHandle right = construct(de->right, width_out);
739 assert(*width_out!=1 && "uncanonicalized srem");
740
741#if 0 //not faster per first benchmark
742 if (optimizeDivides) {
743 if (ConstantExpr *cre = de->right->asConstant()) {
744 uint64_t divisor = cre->asUInt64;
745
746 //use fast division to compute modulo without explicit division for constant divisor
747 if( *width_out == 32 ) { //only works for 32-bit division
748 ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor );
749 ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
750 ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
751 return rem;
752 }
753 }
754 }
755#endif
756
757 // XXX implement my fast path and test for proper handling of sign
758 return vc_sbvRemExpr(vc, *width_out, left, right);
759 }
760
761 // Bitwise
762
763 case Expr::Not: {
764 NotExpr *ne = cast<NotExpr>(e);
765 ExprHandle expr = construct(ne->expr, width_out);
766 if (*width_out==1) {
767 return vc_notExpr(vc, expr);
768 } else {
769 return vc_bvNotExpr(vc, expr);
770 }
771 }
772
773 case Expr::And: {
774 AndExpr *ae = cast<AndExpr>(e);
775 ExprHandle left = construct(ae->left, width_out);
776 ExprHandle right = construct(ae->right, width_out);
777 if (*width_out==1) {
778 return vc_andExpr(vc, left, right);
779 } else {
780 return vc_bvAndExpr(vc, left, right);
781 }
782 }
783
784 case Expr::Or: {
785 OrExpr *oe = cast<OrExpr>(e);
786 ExprHandle left = construct(oe->left, width_out);
787 ExprHandle right = construct(oe->right, width_out);
788 if (*width_out==1) {
789 return vc_orExpr(vc, left, right);
790 } else {
791 return vc_bvOrExpr(vc, left, right);
792 }
793 }
794
795 case Expr::Xor: {
796 XorExpr *xe = cast<XorExpr>(e);
797 ExprHandle left = construct(xe->left, width_out);
798 ExprHandle right = construct(xe->right, width_out);
799
800 if (*width_out==1) {
801 // XXX check for most efficient?
802 return vc_iteExpr(vc, left,
803 ExprHandle(vc_notExpr(vc, right)), right);
804 } else {
805 return vc_bvXorExpr(vc, left, right);
806 }
807 }
808
809 case Expr::Shl: {
810 ShlExpr *se = cast<ShlExpr>(e);
811 ExprHandle left = construct(se->left, width_out);
812 assert(*width_out!=1 && "uncanonicalized shl");
813
814 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
815 return bvLeftShift(left, (unsigned) CE->getLimitedValue());
816 } else {
817 int shiftWidth;
818 ExprHandle amount = construct(se->right, &shiftWidth);
819 return bvVarLeftShift( left, amount);
820 }
821 }
822
823 case Expr::LShr: {
824 LShrExpr *lse = cast<LShrExpr>(e);
825 ExprHandle left = construct(lse->left, width_out);
826 assert(*width_out!=1 && "uncanonicalized lshr");
827
828 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
829 return bvRightShift(left, (unsigned) CE->getLimitedValue());
830 } else {
831 int shiftWidth;
832 ExprHandle amount = construct(lse->right, &shiftWidth);
833 return bvVarRightShift( left, amount);
834 }
835 }
836
837 case Expr::AShr: {
838 AShrExpr *ase = cast<AShrExpr>(e);
839 ExprHandle left = construct(ase->left, width_out);
840 assert(*width_out!=1 && "uncanonicalized ashr");
841
842 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
843 unsigned shift = (unsigned) CE->getLimitedValue();
844 ExprHandle signedBool = bvBoolExtract(left, *width_out-1);
845 return constructAShrByConstant(left, shift, signedBool);
846 } else {
847 int shiftWidth;
848 ExprHandle amount = construct(ase->right, &shiftWidth);
849 return bvVarArithRightShift( left, amount);
850 }
851 }
852
853 // Comparison
854
855 case Expr::Eq: {
856 EqExpr *ee = cast<EqExpr>(e);
857 ExprHandle left = construct(ee->left, width_out);
858 ExprHandle right = construct(ee->right, width_out);
859 if (*width_out==1) {
860 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
861 if (CE->isTrue())
862 return right;
863 return vc_notExpr(vc, right);
864 } else {
865 return vc_iffExpr(vc, left, right);
866 }
867 } else {
868 *width_out = 1;
869 return vc_eqExpr(vc, left, right);
870 }
871 }
872
873 case Expr::Ult: {
874 UltExpr *ue = cast<UltExpr>(e);
875 ExprHandle left = construct(ue->left, width_out);
876 ExprHandle right = construct(ue->right, width_out);
877 assert(*width_out!=1 && "uncanonicalized ult");
878 *width_out = 1;
879 return vc_bvLtExpr(vc, left, right);
880 }
881
882 case Expr::Ule: {
883 UleExpr *ue = cast<UleExpr>(e);
884 ExprHandle left = construct(ue->left, width_out);
885 ExprHandle right = construct(ue->right, width_out);
886 assert(*width_out!=1 && "uncanonicalized ule");
887 *width_out = 1;
888 return vc_bvLeExpr(vc, left, right);
889 }
890
891 case Expr::Slt: {
892 SltExpr *se = cast<SltExpr>(e);
893 ExprHandle left = construct(se->left, width_out);
894 ExprHandle right = construct(se->right, width_out);
895 assert(*width_out!=1 && "uncanonicalized slt");
896 *width_out = 1;
897 return vc_sbvLtExpr(vc, left, right);
898 }
899
900 case Expr::Sle: {
901 SleExpr *se = cast<SleExpr>(e);
902 ExprHandle left = construct(se->left, width_out);
903 ExprHandle right = construct(se->right, width_out);
904 assert(*width_out!=1 && "uncanonicalized sle");
905 *width_out = 1;
906 return vc_sbvLeExpr(vc, left, right);
907 }
908
909 // unused due to canonicalization
910#if 0
911 case Expr::Ne:
912 case Expr::Ugt:
913 case Expr::Uge:
914 case Expr::Sgt:
915 case Expr::Sge:
916#endif
917
918 default:
919 assert(0 && "unhandled Expr type");
920 return vc_trueExpr(vc);
921 }
922}
923#endif // ENABLE_STP
#define add(name, handler, ret)
void vc_DeleteExpr(void *)
void hashArrayExpr(const Array *array, T &exp)
Definition: ArrayExprHash.h:94
bool lookupUpdateNodeExpr(const UpdateNode *un, T &exp) const
void hashUpdateNodeExpr(const UpdateNode *un, T &exp)
UpdateNodeHash::const_iterator UpdateNodeHashConstIter
Definition: ArrayExprHash.h:69
bool lookupArrayExpr(const Array *array, T &exp) const
Definition: ArrayExprHash.h:77
ArrayHash::iterator ArrayHashIter
Definition: ArrayExprHash.h:64
Expr::Width getRange() const
Definition: Expr.h:530
bool isConstantArray() const
Definition: Expr.h:525
const unsigned size
Definition: Expr.h:489
const std::vector< ref< ConstantExpr > > constantValues
Definition: Expr.h:498
const std::string name
Definition: Expr.h:486
Expr::Width getDomain() const
Definition: Expr.h:529
Width getWidth() const
Definition: Expr.h:849
ref< Expr > src
Definition: Expr.h:843
ref< Expr > getKid(unsigned i) const
Definition: Expr.h:697
Width getWidth() const
Definition: Expr.h:691
unsigned getNumKids() const
Definition: Expr.h:696
bool isTrue() const
isTrue - Is this the true expression.
Definition: Expr.h:1099
Width getWidth() const
Definition: Expr.h:1009
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
Definition: Expr.h:1037
static ref< ConstantExpr > alloc(const llvm::APInt &v)
Definition: Expr.h:1065
const llvm::APInt & getAPValue() const
Definition: Expr.h:1019
uint64_t getZExtValue(unsigned bits=64) const
Definition: Expr.h:1030
virtual Kind getKind() const =0
@ Xor
Definition: Expr.h:149
@ Not
Definition: Expr.h:133
@ Ule
Definition: Expr.h:158
@ LShr
Definition: Expr.h:151
@ Sge
Not used in canonical form.
Definition: Expr.h:164
@ Add
Definition: Expr.h:138
@ Select
Definition: Expr.h:124
@ Ne
Not used in canonical form.
Definition: Expr.h:156
@ And
Definition: Expr.h:147
@ ZExt
Definition: Expr.h:129
@ URem
Definition: Expr.h:143
@ SDiv
Definition: Expr.h:142
@ NotOptimized
Definition: Expr.h:120
@ Mul
Definition: Expr.h:140
@ AShr
Definition: Expr.h:152
@ Extract
Definition: Expr.h:126
@ Read
Definition: Expr.h:123
@ Constant
Definition: Expr.h:113
@ Ugt
Not used in canonical form.
Definition: Expr.h:159
@ Sub
Definition: Expr.h:139
@ Ult
Definition: Expr.h:157
@ Shl
Definition: Expr.h:150
@ SRem
Definition: Expr.h:144
@ Concat
Definition: Expr.h:125
@ Or
Definition: Expr.h:148
@ Sle
Definition: Expr.h:162
@ Sgt
Not used in canonical form.
Definition: Expr.h:163
@ Slt
Definition: Expr.h:161
@ Uge
Not used in canonical form.
Definition: Expr.h:160
@ SExt
Definition: Expr.h:130
@ UDiv
Definition: Expr.h:141
@ Eq
Definition: Expr.h:155
unsigned offset
Definition: Expr.h:746
Width getWidth() const
Definition: Expr.h:759
ref< Expr > expr
Definition: Expr.h:745
ref< Expr > src
Definition: Expr.h:415
Class representing a one byte read from an array.
Definition: Expr.h:565
ref< Expr > index
Definition: Expr.h:572
UpdateList updates
Definition: Expr.h:571
ExprHandle constructUDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d)
ExprHandle bvOne(unsigned width)
ExprHandle bvMinusOne(unsigned width)
ExprHandle eqExpr(ExprHandle a, ExprHandle b)
ExprHandle bvRightShift(ExprHandle expr, unsigned shift)
ExprHandle extractPartialShiftValue(ExprHandle shift, unsigned width, unsigned &shiftBits)
ExprHandle getInitialRead(const Array *os, unsigned index)
ExprHandle bvZExtConst(unsigned width, uint64_t value)
ExprHandle bvConst64(unsigned width, uint64_t value)
::VCExpr getArrayForUpdate(const Array *root, const UpdateNode *un)
ExprHandle constructAShrByConstant(ExprHandle expr, unsigned shift, ExprHandle isSigned)
ExprHandle constructSDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d)
ExprHandle getTrue()
::VCExpr buildVar(const char *name, unsigned width)
ExprHandle bvExtract(ExprHandle expr, unsigned top, unsigned bottom)
ExprHandle bvZero(unsigned width)
ExprHandle bvVarLeftShift(ExprHandle expr, ExprHandle shift)
STPArrayExprHash _arr_hash
Definition: STPBuilder.h:74
::VCExpr getInitialArray(const Array *os)
ExprHandle bvLeftShift(ExprHandle expr, unsigned shift)
ExprHandle bvVarRightShift(ExprHandle expr, ExprHandle shift)
ExprHandle bvSExtConst(unsigned width, uint64_t value)
ExprHandle bvBoolExtract(ExprHandle expr, int bit)
ExprHandle construct(ref< Expr > e, int *width_out)
bool optimizeDivides
Definition: STPBuilder.h:72
ExprHandle constructMulByConstant(ExprHandle expr, unsigned width, uint64_t x)
ExprHandle getFalse()
ExprHandle bvConst32(unsigned width, uint32_t value)
::VCExpr buildArray(const char *name, unsigned indexWidth, unsigned valueWidth)
STPBuilder(::VC _vc, bool _optimizeDivides=true)
ExprHandle constructActual(ref< Expr > e, int *width_out)
ExprHandle bvVarArithRightShift(ExprHandle expr, ExprHandle shift)
ExprHashMap< std::pair< ExprHandle, unsigned > > constructed
Definition: STPBuilder.h:67
Class representing an if-then-else expression.
Definition: Expr.h:610
ref< Expr > cond
Definition: Expr.h:616
ref< Expr > trueExpr
Definition: Expr.h:616
ref< Expr > falseExpr
Definition: Expr.h:616
ref< UpdateNode > head
pointer to the most recent update node
Definition: Expr.h:546
const Array * root
Definition: Expr.h:543
Class representing a byte update of an array.
Definition: Expr.h:451
ref< Expr > index
Definition: Expr.h:459
const ref< UpdateNode > next
Definition: Expr.h:458
ref< Expr > value
Definition: Expr.h:459
uint64_t truncateToNBits(uint64_t x, unsigned N)
Definition: Bits.h:78
unsigned indexOfSingleBit(uint64_t x)
Definition: Bits.h:98
uint64_t isPowerOfTwo(uint64_t x)
Definition: Bits.h:91
ref< Expr > ExprHandle
Definition: Parser.h:27
uint64_t sub(uint64_t l, uint64_t r, unsigned inWidth)
uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth)
Statistic queryConstructs
Definition: main.cpp:291
void ComputeMultConstants64(uint64_t multiplicand, uint64_t &add, uint64_t &sub)
void ComputeUDivConstants32(uint32_t d, uint32_t &mprime, uint32_t &sh1, uint32_t &sh2)
void ComputeSDivConstants32(int32_t d, int32_t &mprime, int32_t &dsign, int32_t &shpost)
llvm::cl::OptionCategory ExprCat