GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv_rewrite_rules_simplification.h Lines: 619 747 82.9 %
Date: 2021-08-14 Branches: 1810 4290 42.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Aina Niemetz, Mathias Preiner
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * [[ Add one-line brief description here ]]
14
 *
15
 * [[ Add lengthier description here ]]
16
 * \todo document this file
17
 */
18
19
#include "cvc5_private.h"
20
21
#pragma once
22
23
#include "options/bv_options.h"
24
#include "theory/bv/theory_bv_rewrite_rules.h"
25
#include "theory/bv/theory_bv_utils.h"
26
#include "theory/rewriter.h"
27
#include "util/bitvector.h"
28
29
namespace cvc5 {
30
namespace theory {
31
namespace bv {
32
33
/* -------------------------------------------------------------------------- */
34
35
/**
36
 * BitOfConst
37
 */
38
template <>
39
616899
inline bool RewriteRule<BitOfConst>::applies(TNode node)
40
{
41
616899
  return node.getKind() == kind::BITVECTOR_BITOF && node[0].isConst();
42
}
43
44
template <>
45
59
inline Node RewriteRule<BitOfConst>::apply(TNode node)
46
{
47
59
  size_t pos = node.getOperator().getConst<BitVectorBitOf>().d_bitIndex;
48
59
  return utils::getBit(node[0], pos) ? utils::mkTrue() : utils::mkFalse();
49
}
50
51
/* -------------------------------------------------------------------------- */
52
53
/**
54
 * BvIteConstCond
55
 *
56
 * BITVECTOR_ITE with constant condition
57
 */
58
template <>
59
26601
inline bool RewriteRule<BvIteConstCond>::applies(TNode node)
60
{
61
26601
  return (node.getKind() == kind::BITVECTOR_ITE && node[0].isConst());
62
}
63
64
template <>
65
513
inline Node RewriteRule<BvIteConstCond>::apply(TNode node)
66
{
67
1026
  Debug("bv-rewrite") << "RewriteRule<BvIteConstCond>(" << node << ")"
68
513
                      << std::endl;
69
513
  return utils::isZero(node[0]) ? node[2] : node[1];
70
}
71
72
/* -------------------------------------------------------------------------- */
73
74
/**
75
 * BvIteEqualChildren
76
 *
77
 * BITVECTOR_ITE with term_then = term_else
78
 */
79
template <>
80
26675
inline bool RewriteRule<BvIteEqualChildren>::applies(TNode node)
81
{
82
26675
  return (node.getKind() == kind::BITVECTOR_ITE && node[1] == node[2]);
83
}
84
85
template <>
86
587
inline Node RewriteRule<BvIteEqualChildren>::apply(TNode node)
87
{
88
1174
  Debug("bv-rewrite") << "RewriteRule<BvIteEqualChildren>(" << node << ")"
89
587
                      << std::endl;
90
587
  return node[1];
91
}
92
93
/* -------------------------------------------------------------------------- */
94
95
/**
96
 * BvIteConstChildren
97
 *
98
 * BITVECTOR_ITE with constant children of size one
99
 */
100
template <>
101
24175
inline bool RewriteRule<BvIteConstChildren>::applies(TNode node)
102
{
103
24175
  return (node.getKind() == kind::BITVECTOR_ITE
104
48350
          && utils::getSize(node[1]) == 1
105
81740
          && node[1].isConst() && node[2].isConst());
106
}
107
108
template <>
109
290
inline Node RewriteRule<BvIteConstChildren>::apply(TNode node)
110
{
111
580
  Debug("bv-rewrite") << "RewriteRule<BvIteConstChildren>(" << node << ")"
112
290
                      << std::endl;
113
290
  if (utils::isOne(node[1]) && utils::isZero(node[2]))
114
  {
115
254
    return node[0];
116
  }
117
36
  Assert(utils::isZero(node[1]) && utils::isOne(node[2]));
118
36
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, node[0]);
119
}
120
121
/* -------------------------------------------------------------------------- */
122
123
/**
124
 * BvIteEqualCond
125
 *
126
 * Nested BITVECTOR_ITE with cond_outer == cond_inner
127
 *
128
 * c0 ? (c0 ? t0 : e0) : e1              ->  c0 ? t0 : e1
129
 * c0 ? t0             : (c0 ? t1 : e1)  ->  c0 ? t0 : e1
130
 * c0 ? (c0 ? t0 : e0) : (c0 ? t1 : e1)  ->  c0 ? t0 : e1
131
 */
132
template <>
133
23894
inline bool RewriteRule<BvIteEqualCond>::applies(TNode node)
134
{
135
  return (
136
23894
      node.getKind() == kind::BITVECTOR_ITE
137
71700
      && ((node[1].getKind() == kind::BITVECTOR_ITE && node[0] == node[1][0])
138
47486
          || (node[2].getKind() == kind::BITVECTOR_ITE
139
57807
              && node[0] == node[2][0])));
140
}
141
142
template <>
143
9
inline Node RewriteRule<BvIteEqualCond>::apply(TNode node)
144
{
145
18
  Debug("bv-rewrite") << "RewriteRule<BvIteEqualCond>(" << node << ")"
146
9
                      << std::endl;
147
36
  Node t0 = node[1].getKind() == kind::BITVECTOR_ITE && node[0] == node[1][0]
148
45
                ? node[1][1]
149
18
                : node[1];
150
33
  Node e1 = node[2].getKind() == kind::BITVECTOR_ITE && node[0] == node[2][0]
151
36
                ? node[2][2]
152
18
                : node[2];
153
18
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ITE, node[0], t0, e1);
154
}
155
156
/* -------------------------------------------------------------------------- */
157
158
/**
159
 * BvIteMergeThenIf
160
 *
161
 * Nested BITVECTOR_ITE of the form
162
 *   c0 ? (c1 ? t1 : e1) : t1  ->  c0 AND NOT(c1) ? e1 : t1
163
 */
164
template <>
165
23636
inline bool RewriteRule<BvIteMergeThenIf>::applies(TNode node)
166
{
167
23636
  return (node.getKind() == kind::BITVECTOR_ITE
168
47272
          && node[1].getKind() == kind::BITVECTOR_ITE
169
73872
          && node[1][1] == node[2]);
170
}
171
172
template <>
173
50
inline Node RewriteRule<BvIteMergeThenIf>::apply(TNode node)
174
{
175
100
  Debug("bv-rewrite") << "RewriteRule<BvIteMergeThenIf>(" << node << ")"
176
50
                      << std::endl;
177
50
  NodeManager* nm = NodeManager::currentNM();
178
50
  Assert(node[1].getKind() == kind::BITVECTOR_ITE);
179
  Node cond = nm->mkNode(kind::BITVECTOR_AND,
180
                         node[0],
181
100
                         nm->mkNode(kind::BITVECTOR_NOT, node[1][0]));
182
100
  return nm->mkNode(kind::BITVECTOR_ITE, cond, node[1][2], node[2]);
183
}
184
185
/* -------------------------------------------------------------------------- */
186
187
/**
188
 * BvIteMergeElseIf
189
 *
190
 * Nested BITVECTOR_ITE of the form
191
 *   c0 ? (c1 ? t1 : e1) : e1  ->  c0 AND c1 ? t1 : e1
192
 */
193
template <>
194
23608
inline bool RewriteRule<BvIteMergeElseIf>::applies(TNode node)
195
{
196
23608
  return (node.getKind() == kind::BITVECTOR_ITE
197
47216
          && node[1].getKind() == kind::BITVECTOR_ITE
198
73722
          && node[1][2] == node[2]);
199
}
200
201
template <>
202
22
inline Node RewriteRule<BvIteMergeElseIf>::apply(TNode node)
203
{
204
44
  Debug("bv-rewrite") << "RewriteRule<BvIteMergeElseIf>(" << node << ")"
205
22
                      << std::endl;
206
22
  NodeManager* nm = NodeManager::currentNM();
207
22
  Assert(node[1].getKind() == kind::BITVECTOR_ITE);
208
44
  Node cond = nm->mkNode(kind::BITVECTOR_AND, node[0], node[1][0]);
209
44
  return nm->mkNode(kind::BITVECTOR_ITE, cond, node[1][1], node[2]);
210
}
211
212
/* -------------------------------------------------------------------------- */
213
214
/**
215
 * BvIteMergeThenElse
216
 *
217
 * Nested BITVECTOR_ITE of the form
218
 *   c0 ? t0 : (c1 ? t0 : e1)  ->  NOT(c0) AND NOT(c1) ? e1 : t0
219
 */
220
template <>
221
23677
inline bool RewriteRule<BvIteMergeThenElse>::applies(TNode node)
222
{
223
23677
  return (node.getKind() == kind::BITVECTOR_ITE
224
47354
          && node[2].getKind() == kind::BITVECTOR_ITE
225
81141
          && node[1] == node[2][1]);
226
}
227
228
template <>
229
91
inline Node RewriteRule<BvIteMergeThenElse>::apply(TNode node)
230
{
231
182
  Debug("bv-rewrite") << "RewriteRule<BvIteMergeThenElse>(" << node << ")"
232
91
                      << std::endl;
233
91
  NodeManager* nm = NodeManager::currentNM();
234
91
  Assert(node[2].getKind() == kind::BITVECTOR_ITE);
235
  Node cond = nm->mkNode(kind::BITVECTOR_AND,
236
182
                         nm->mkNode(kind::BITVECTOR_NOT, node[0]),
237
364
                         nm->mkNode(kind::BITVECTOR_NOT, node[2][0]));
238
182
  return nm->mkNode(kind::BITVECTOR_ITE, cond, node[2][2], node[1]);
239
}
240
241
/* -------------------------------------------------------------------------- */
242
243
/**
244
 * BvIteMergeElseElse
245
 *
246
 * Nested BITVECTOR_ITE of the form
247
 *   c0 ? t0 : (c1 ? t1 : t0)  ->  NOT(c0) AND c1 ? t1 : t0
248
 */
249
template <>
250
23608
inline bool RewriteRule<BvIteMergeElseElse>::applies(TNode node)
251
{
252
23608
  return (node.getKind() == kind::BITVECTOR_ITE
253
47216
          && node[2].getKind() == kind::BITVECTOR_ITE
254
80796
          && node[1] == node[2][2]);
255
}
256
257
template <>
258
22
inline Node RewriteRule<BvIteMergeElseElse>::apply(TNode node)
259
{
260
44
  Debug("bv-rewrite") << "RewriteRule<BvIteMergeElseElse>(" << node << ")"
261
22
                      << std::endl;
262
22
  NodeManager* nm = NodeManager::currentNM();
263
22
  Assert(node[2].getKind() == kind::BITVECTOR_ITE);
264
  Node cond = nm->mkNode(kind::BITVECTOR_AND,
265
44
                         nm->mkNode(kind::BITVECTOR_NOT, node[0]),
266
88
                         node[2][0]);
267
44
  return nm->mkNode(kind::BITVECTOR_ITE, cond, node[2][1], node[1]);
268
}
269
270
/* -------------------------------------------------------------------------- */
271
272
/**
273
 * BvComp
274
 *
275
 * BITVECTOR_COMP of children of size 1 with one constant child
276
 */
277
template <>
278
43338
inline bool RewriteRule<BvComp>::applies(TNode node)
279
{
280
43338
  return (node.getKind() == kind::BITVECTOR_COMP
281
86676
          && utils::getSize(node[0]) == 1
282
135287
          && (node[0].isConst() || node[1].isConst()));
283
}
284
285
template <>
286
1483
inline Node RewriteRule<BvComp>::apply(TNode node)
287
{
288
1483
  Debug("bv-rewrite") << "RewriteRule<BvComp>(" << node << ")" << std::endl;
289
1483
  NodeManager* nm = NodeManager::currentNM();
290
1483
  if (node[0].isConst())
291
  {
292
566
    return utils::isZero(node[0]) ? nm->mkNode(kind::BITVECTOR_NOT, node[1])
293
283
                                  : Node(node[1]);
294
  }
295
2400
  return utils::isZero(node[1]) ? nm->mkNode(kind::BITVECTOR_NOT, node[0])
296
1200
                                : Node(node[0]);
297
}
298
299
/* -------------------------------------------------------------------------- */
300
301
/**
302
 * ShlByConst
303
 *
304
 * Left Shift by constant amount
305
 */
306
template<> inline
307
35660
bool RewriteRule<ShlByConst>::applies(TNode node) {
308
  // if the shift amount is constant
309
106980
  return (node.getKind() == kind::BITVECTOR_SHL &&
310
106980
          node[1].getKind() == kind::CONST_BITVECTOR);
311
}
312
313
template<> inline
314
13667
Node RewriteRule<ShlByConst>::apply(TNode node) {
315
13667
  Debug("bv-rewrite") << "RewriteRule<ShlByConst>(" << node << ")" << std::endl;
316
27334
  Integer amount = node[1].getConst<BitVector>().toInteger();
317
13667
  if (amount == 0) {
318
2508
    return node[0];
319
  }
320
22318
  Node a = node[0];
321
11159
  uint32_t size = utils::getSize(a);
322
323
324
11159
  if (amount >= Integer(size)) {
325
    // if we are shifting more than the length of the bitvector return 0
326
7942
    return utils::mkZero(size);
327
  }
328
329
  // make sure we do not lose information casting
330
3217
  Assert(amount < Integer(1).multiplyByPow2(32));
331
332
3217
  uint32_t uint32_amount = amount.toUnsignedInt();
333
334
6434
  Node left = utils::mkExtract(a, size - 1 - uint32_amount, 0);
335
6434
  Node right = utils::mkZero(uint32_amount);
336
3217
  return utils::mkConcat(left, right);
337
}
338
339
/* -------------------------------------------------------------------------- */
340
341
/**
342
 * LshrByConst
343
 *
344
 * Right Logical Shift by constant amount
345
 */
346
347
template<> inline
348
41294
bool RewriteRule<LshrByConst>::applies(TNode node) {
349
  // if the shift amount is constant
350
123882
  return (node.getKind() == kind::BITVECTOR_LSHR &&
351
123882
          node[1].getKind() == kind::CONST_BITVECTOR);
352
}
353
354
template<> inline
355
14792
Node RewriteRule<LshrByConst>::apply(TNode node) {
356
14792
  Debug("bv-rewrite") << "RewriteRule<LshrByConst>(" << node << ")" << std::endl;
357
29584
  Integer amount = node[1].getConst<BitVector>().toInteger();
358
14792
  if (amount == 0) {
359
2585
    return node[0];
360
  }
361
362
24414
  Node a = node[0];
363
12207
  uint32_t size = utils::getSize(a);
364
365
366
12207
  if (amount >= Integer(size)) {
367
    // if we are shifting more than the length of the bitvector return 0
368
9685
    return utils::mkZero(size);
369
  }
370
371
  // make sure we do not lose information casting
372
2522
  Assert(amount < Integer(1).multiplyByPow2(32));
373
374
2522
  uint32_t uint32_amount = amount.toUnsignedInt();
375
5044
  Node right = utils::mkExtract(a, size - 1, uint32_amount);
376
5044
  Node left = utils::mkZero(uint32_amount);
377
2522
  return utils::mkConcat(left, right);
378
}
379
380
/* -------------------------------------------------------------------------- */
381
382
/**
383
 * AshrByConst
384
 *
385
 * Right Arithmetic Shift by constant amount
386
 */
387
388
template<> inline
389
7006
bool RewriteRule<AshrByConst>::applies(TNode node) {
390
  // if the shift amount is constant
391
21018
  return (node.getKind() == kind::BITVECTOR_ASHR &&
392
21018
          node[1].getKind() == kind::CONST_BITVECTOR);
393
}
394
395
template<> inline
396
791
Node RewriteRule<AshrByConst>::apply(TNode node) {
397
791
  Debug("bv-rewrite") << "RewriteRule<AshrByConst>(" << node << ")" << std::endl;
398
1582
  Integer amount = node[1].getConst<BitVector>().toInteger();
399
791
  if (amount == 0) {
400
115
    return node[0];
401
  }
402
403
1352
  Node a = node[0];
404
676
  uint32_t size = utils::getSize(a);
405
1352
  Node sign_bit = utils::mkExtract(a, size-1, size-1);
406
407
676
  if (amount >= Integer(size)) {
408
    // if we are shifting more than the length of the bitvector return n repetitions
409
    // of the first bit
410
130
    return utils::mkConcat(sign_bit, size);
411
  }
412
413
  // make sure we do not lose information casting
414
546
  Assert(amount < Integer(1).multiplyByPow2(32));
415
416
546
  uint32_t uint32_amount = amount.toUnsignedInt();
417
546
  if (uint32_amount == 0) {
418
    return a;
419
  }
420
421
1092
  Node left = utils::mkConcat(sign_bit, uint32_amount);
422
1092
  Node right = utils::mkExtract(a, size - 1, uint32_amount);
423
546
  return utils::mkConcat(left, right);
424
}
425
426
/* -------------------------------------------------------------------------- */
427
428
/**
429
 * BitwiseIdemp
430
 *
431
 * (a bvand a) ==> a
432
 * (a bvor a)  ==> a
433
 */
434
435
template<> inline
436
bool RewriteRule<BitwiseIdemp>::applies(TNode node) {
437
  Unreachable();
438
  return ((node.getKind() == kind::BITVECTOR_AND ||
439
           node.getKind() == kind::BITVECTOR_OR) &&
440
          node.getNumChildren() == 2 &&
441
          node[0] == node[1]);
442
}
443
444
template<> inline
445
Node RewriteRule<BitwiseIdemp>::apply(TNode node) {
446
  Unreachable();
447
  Debug("bv-rewrite") << "RewriteRule<BitwiseIdemp>(" << node << ")" << std::endl;
448
  return node[0];
449
}
450
451
/* -------------------------------------------------------------------------- */
452
453
/**
454
 * AndZero
455
 *
456
 * (a bvand 0) ==> 0
457
 */
458
459
template<> inline
460
bool RewriteRule<AndZero>::applies(TNode node) {
461
  Unreachable();
462
  unsigned size = utils::getSize(node);
463
  return (node.getKind() == kind::BITVECTOR_AND  &&
464
          node.getNumChildren() == 2 &&
465
          (node[0] == utils::mkConst(size, 0) ||
466
           node[1] == utils::mkConst(size, 0)));
467
}
468
469
template<> inline
470
Node RewriteRule<AndZero>::apply(TNode node) {
471
  Unreachable();
472
  Debug("bv-rewrite") << "RewriteRule<AndZero>(" << node << ")" << std::endl;
473
  return utils::mkConst(utils::getSize(node), 0);
474
}
475
476
/* -------------------------------------------------------------------------- */
477
478
/**
479
 * AndOne
480
 *
481
 * (a bvand 1) ==> a
482
 */
483
484
template<> inline
485
bool RewriteRule<AndOne>::applies(TNode node) {
486
  Unreachable();
487
  unsigned size = utils::getSize(node);
488
  Node ones = utils::mkOnes(size);
489
  return (node.getKind() == kind::BITVECTOR_AND  &&
490
          node.getNumChildren() == 2 &&
491
          (node[0] == ones ||
492
           node[1] == ones));
493
}
494
495
template<> inline
496
Node RewriteRule<AndOne>::apply(TNode node) {
497
  Unreachable();
498
  Debug("bv-rewrite") << "RewriteRule<AndOne>(" << node << ")" << std::endl;
499
  unsigned size = utils::getSize(node);
500
501
  if (node[0] == utils::mkOnes(size)) {
502
    return node[1];
503
  } else {
504
    Assert(node[1] == utils::mkOnes(size));
505
    return node[0];
506
  }
507
}
508
509
/* -------------------------------------------------------------------------- */
510
511
/**
512
 * AndOrXorConcatPullUp
513
 *
514
 * Match:       x_m <op> concat(y_my, <const>_n, z_mz)
515
 *              <const>_n in { 0_n, 1_n, ~0_n }
516
 *
517
 * Rewrites to: concat(x[m-1:m-my]  <op> y,
518
 *                     x[m-my-1:mz] <op> <const>_n,
519
 *                     x[mz-1:0]    <op> z)
520
 */
521
522
template <>
523
282730
inline bool RewriteRule<AndOrXorConcatPullUp>::applies(TNode node)
524
{
525
565460
  if (node.getKind() != kind::BITVECTOR_AND
526
204895
      && node.getKind() != kind::BITVECTOR_OR
527
382385
      && node.getKind() != kind::BITVECTOR_XOR)
528
  {
529
91530
    return false;
530
  }
531
532
382400
  TNode n;
533
534
1051381
  for (const TNode& c : node)
535
  {
536
868138
    if (c.getKind() == kind::BITVECTOR_CONCAT)
537
    {
538
52790
      for (const TNode& cc : c)
539
      {
540
50208
        if (cc.isConst())
541
        {
542
5375
          n = cc;
543
5375
          break;
544
        }
545
      }
546
7957
      break;
547
    }
548
  }
549
191200
  if (n.isNull()) return false;
550
5375
  return utils::isZero(n) || utils::isOne(n) || utils::isOnes(n);
551
}
552
553
template <>
554
2667
inline Node RewriteRule<AndOrXorConcatPullUp>::apply(TNode node)
555
{
556
5334
  Debug("bv-rewrite") << "RewriteRule<AndOrXorConcatPullUp>(" << node << ")"
557
2667
                      << std::endl;
558
  uint32_t m, my, mz;
559
  size_t nc;
560
2667
  Kind kind = node.getKind();
561
5334
  TNode concat;
562
5334
  Node x, y, z, c;
563
5334
  NodeBuilder xb(kind);
564
5334
  NodeBuilder yb(kind::BITVECTOR_CONCAT);
565
5334
  NodeBuilder zb(kind::BITVECTOR_CONCAT);
566
5334
  NodeBuilder res(kind::BITVECTOR_CONCAT);
567
2667
  NodeManager* nm = NodeManager::currentNM();
568
569
8454
  for (const TNode& child : node)
570
  {
571
5787
    if (concat.isNull() && child.getKind() == kind::BITVECTOR_CONCAT)
572
    {
573
2667
      concat = child;
574
    }
575
    else
576
    {
577
3120
      xb << child;
578
    }
579
  }
580
2667
  x = xb.getNumChildren() > 1 ? xb.constructNode() : xb[0];
581
582
10771
  for (const TNode& child : concat)
583
  {
584
8104
    if (c.isNull())
585
    {
586
6786
      if (utils::isZero(child) || utils::isOne(child) || utils::isOnes(child))
587
      {
588
2667
        c = child;
589
      }
590
      else
591
      {
592
4119
        yb << child;
593
      }
594
    }
595
    else
596
    {
597
1318
      zb << child;
598
    }
599
  }
600
2667
  Assert(!c.isNull());
601
2667
  Assert(yb.getNumChildren() || zb.getNumChildren());
602
603
2667
  if ((nc = yb.getNumChildren()) > 0)
604
  {
605
1528
    y = nc > 1 ? yb.constructNode() : yb[0];
606
  }
607
2667
  if ((nc = zb.getNumChildren()) > 0)
608
  {
609
1145
    z = nc > 1 ? zb.constructNode() : zb[0];
610
  }
611
2667
  m = utils::getSize(x);
612
#ifdef CVC5_ASSERTIONS
613
2667
  uint32_t n = utils::getSize(c);
614
#endif
615
2667
  my = y.isNull() ? 0 : utils::getSize(y);
616
2667
  mz = z.isNull() ? 0 : utils::getSize(z);
617
2667
  Assert(mz == m - my - n);
618
2667
  Assert(my || mz);
619
620
2667
  if (my)
621
  {
622
1528
    res << nm->mkNode(kind, utils::mkExtract(x, m - 1, m - my), y);
623
  }
624
625
2667
  res << nm->mkNode(kind, utils::mkExtract(x, m - my - 1, mz), c);
626
627
2667
  if (mz)
628
  {
629
1145
    res << nm->mkNode(kind, utils::mkExtract(x, mz - 1, 0), z);
630
  }
631
632
5334
  return res;
633
}
634
635
/* -------------------------------------------------------------------------- */
636
637
/**
638
 * OrZero
639
 *
640
 * (a bvor 0) ==> a
641
 */
642
643
template<> inline
644
bool RewriteRule<OrZero>::applies(TNode node) {
645
  Unreachable();
646
  unsigned size = utils::getSize(node);
647
  return (node.getKind() == kind::BITVECTOR_OR  &&
648
          node.getNumChildren() == 2 &&
649
          (node[0] == utils::mkConst(size, 0) ||
650
           node[1] == utils::mkConst(size, 0)));
651
}
652
653
template<> inline
654
Node RewriteRule<OrZero>::apply(TNode node) {
655
  Unreachable();
656
  Debug("bv-rewrite") << "RewriteRule<OrZero>(" << node << ")" << std::endl;
657
658
  unsigned size = utils::getSize(node);
659
  if (node[0] == utils::mkConst(size, 0)) {
660
    return node[1];
661
  } else {
662
    Assert(node[1] == utils::mkConst(size, 0));
663
    return node[0];
664
  }
665
}
666
667
/* -------------------------------------------------------------------------- */
668
669
/**
670
 * OrOne
671
 *
672
 * (a bvor 1) ==> 1
673
 */
674
675
template<> inline
676
bool RewriteRule<OrOne>::applies(TNode node) {
677
  Unreachable();
678
  unsigned size = utils::getSize(node);
679
  Node ones = utils::mkOnes(size);
680
  return (node.getKind() == kind::BITVECTOR_OR  &&
681
          node.getNumChildren() == 2 &&
682
          (node[0] == ones ||
683
           node[1] == ones));
684
}
685
686
template<> inline
687
Node RewriteRule<OrOne>::apply(TNode node) {
688
  Unreachable();
689
  Debug("bv-rewrite") << "RewriteRule<OrOne>(" << node << ")" << std::endl;
690
  return utils::mkOnes(utils::getSize(node));
691
}
692
693
/* -------------------------------------------------------------------------- */
694
695
/**
696
 * XorDuplicate
697
 *
698
 * (a bvxor a) ==> 0
699
 */
700
701
template<> inline
702
bool RewriteRule<XorDuplicate>::applies(TNode node) {
703
  Unreachable();
704
  return (node.getKind() == kind::BITVECTOR_XOR &&
705
          node.getNumChildren() == 2 &&
706
          node[0] == node[1]);
707
}
708
709
template<> inline
710
Node RewriteRule<XorDuplicate>::apply(TNode node) {
711
  Unreachable();
712
  Debug("bv-rewrite") << "RewriteRule<XorDuplicate>(" << node << ")" << std::endl;
713
  return utils::mkZero(utils::getSize(node));
714
}
715
716
/* -------------------------------------------------------------------------- */
717
718
/**
719
 * XorOne
720
 *
721
 * (a bvxor 1) ==> ~a
722
 */
723
724
template<> inline
725
5225
bool RewriteRule<XorOne>::applies(TNode node) {
726
5225
  if (node.getKind() != kind::BITVECTOR_XOR) {
727
1028
    return false;
728
  }
729
8394
  Node ones = utils::mkOnes(utils::getSize(node));
730
11163
  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
731
7754
    if (node[i] == ones) {
732
788
      return true;
733
    }
734
  }
735
3409
  return false;
736
}
737
738
template <>
739
394
inline Node RewriteRule<XorOne>::apply(TNode node)
740
{
741
394
  Debug("bv-rewrite") << "RewriteRule<XorOne>(" << node << ")" << std::endl;
742
394
  NodeManager *nm = NodeManager::currentNM();
743
788
  Node ones = utils::mkOnes(utils::getSize(node));
744
788
  std::vector<Node> children;
745
394
  bool found_ones = false;
746
  // XorSimplify should have been called before
747
1204
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
748
  {
749
810
    if (node[i] == ones)
750
    {
751
      // make sure only ones occurs only once
752
394
      found_ones = !found_ones;
753
    }
754
    else
755
    {
756
416
      children.push_back(node[i]);
757
    }
758
  }
759
760
394
  Node result = utils::mkNaryNode(kind::BITVECTOR_XOR, children);
761
394
  if (found_ones)
762
  {
763
394
    result = nm->mkNode(kind::BITVECTOR_NOT, result);
764
  }
765
788
  return result;
766
}
767
768
/* -------------------------------------------------------------------------- */
769
770
/**
771
 * XorZero
772
 *
773
 * (a bvxor 0) ==> a
774
 */
775
776
template<> inline
777
9867
bool RewriteRule<XorZero>::applies(TNode node) {
778
9867
  if (node.getKind() != kind::BITVECTOR_XOR) {
779
505
    return false;
780
  }
781
18724
  Node zero = utils::mkConst(utils::getSize(node), 0);
782
25348
  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
783
17494
    if (node[i] == zero) {
784
1508
      return true;
785
    }
786
  }
787
7854
  return false;
788
}
789
790
template <>
791
754
inline Node RewriteRule<XorZero>::apply(TNode node)
792
{
793
754
  Debug("bv-rewrite") << "RewriteRule<XorZero>(" << node << ")" << std::endl;
794
1508
  std::vector<Node> children;
795
1508
  Node zero = utils::mkConst(utils::getSize(node), 0);
796
797
  // XorSimplify should have been called before
798
2272
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
799
  {
800
1518
    if (node[i] != zero)
801
    {
802
764
      children.push_back(node[i]);
803
    }
804
  }
805
754
  Node res = utils::mkNaryNode(kind::BITVECTOR_XOR, children);
806
1508
  return res;
807
}
808
809
/* -------------------------------------------------------------------------- */
810
811
/**
812
 * BitwiseNotAnd
813
 *
814
 * (a bvand (~ a)) ==> 0
815
 */
816
817
template<> inline
818
bool RewriteRule<BitwiseNotAnd>::applies(TNode node) {
819
  Unreachable();
820
  return (node.getKind() == kind::BITVECTOR_AND &&
821
          node.getNumChildren() == 2 &&
822
          ((node[0].getKind() == kind::BITVECTOR_NOT && node[0][0] == node[1]) ||
823
           (node[1].getKind() == kind::BITVECTOR_NOT && node[1][0] == node[0])));
824
}
825
826
template<> inline
827
Node RewriteRule<BitwiseNotAnd>::apply(TNode node) {
828
  Unreachable();
829
  Debug("bv-rewrite") << "RewriteRule<BitwiseNegAnd>(" << node << ")" << std::endl;
830
  return utils::mkZero(utils::getSize(node));
831
}
832
833
/* -------------------------------------------------------------------------- */
834
835
/**
836
 * BitwiseNegOr
837
 *
838
 * (a bvor (~ a)) ==> 1
839
 */
840
841
template<> inline
842
bool RewriteRule<BitwiseNotOr>::applies(TNode node) {
843
  Unreachable();
844
  return (node.getKind() == kind::BITVECTOR_OR &&
845
          node.getNumChildren() == 2 &&
846
          ((node[0].getKind() == kind::BITVECTOR_NOT && node[0][0] == node[1]) ||
847
           (node[1].getKind() == kind::BITVECTOR_NOT && node[1][0] == node[0])));
848
}
849
850
template<> inline
851
Node RewriteRule<BitwiseNotOr>::apply(TNode node) {
852
  Unreachable();
853
  Debug("bv-rewrite") << "RewriteRule<BitwiseNotOr>(" << node << ")" << std::endl;
854
  uint32_t size = utils::getSize(node);
855
  return utils::mkOnes(size);
856
}
857
858
/* -------------------------------------------------------------------------- */
859
860
/**
861
 * XorNot
862
 *
863
 * ((~ a) bvxor (~ b)) ==> (a bvxor b)
864
 */
865
866
template<> inline
867
bool RewriteRule<XorNot>::applies(TNode node) {
868
  Unreachable();
869
}
870
871
template <>
872
inline Node RewriteRule<XorNot>::apply(TNode node)
873
{
874
  Unreachable();
875
  Debug("bv-rewrite") << "RewriteRule<XorNot>(" << node << ")" << std::endl;
876
  Node a = node[0][0];
877
  Node b = node[1][0];
878
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_XOR, a, b);
879
}
880
881
/* -------------------------------------------------------------------------- */
882
883
/**
884
 * NotXor
885
 *
886
 * ~(a bvxor b) ==> (~ a bvxor b)
887
 */
888
889
template<> inline
890
bool RewriteRule<NotXor>::applies(TNode node) {
891
  return (node.getKind() == kind::BITVECTOR_NOT &&
892
          node[0].getKind() == kind::BITVECTOR_XOR);
893
}
894
895
template <>
896
inline Node RewriteRule<NotXor>::apply(TNode node)
897
{
898
  Debug("bv-rewrite") << "RewriteRule<NotXor>(" << node << ")" << std::endl;
899
  std::vector<Node> children;
900
  TNode::iterator child_it = node[0].begin();
901
  children.push_back(
902
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, *child_it));
903
  for (++child_it; child_it != node[0].end(); ++child_it)
904
  {
905
    children.push_back(*child_it);
906
  }
907
  return utils::mkSortedNode(kind::BITVECTOR_XOR, children);
908
}
909
910
/* -------------------------------------------------------------------------- */
911
912
/**
913
 * NotIdemp
914
 *
915
 * ~ (~ a) ==> a
916
 */
917
918
template<> inline
919
91551
bool RewriteRule<NotIdemp>::applies(TNode node) {
920
235419
  return (node.getKind() == kind::BITVECTOR_NOT &&
921
235419
          node[0].getKind() == kind::BITVECTOR_NOT);
922
}
923
924
template<> inline
925
497
Node RewriteRule<NotIdemp>::apply(TNode node) {
926
497
  Debug("bv-rewrite") << "RewriteRule<NotIdemp>(" << node << ")" << std::endl;
927
497
  return node[0][0];
928
}
929
930
/* -------------------------------------------------------------------------- */
931
932
/**
933
 * LtSelf
934
 *
935
 * a < a ==> false
936
 */
937
938
template<> inline
939
bool RewriteRule<LtSelf>::applies(TNode node) {
940
  return ((node.getKind() == kind::BITVECTOR_ULT ||
941
           node.getKind() == kind::BITVECTOR_SLT) &&
942
          node[0] == node[1]);
943
}
944
945
template<> inline
946
Node RewriteRule<LtSelf>::apply(TNode node) {
947
  Debug("bv-rewrite") << "RewriteRule<LtSelf>(" << node << ")" << std::endl;
948
  return utils::mkFalse();
949
}
950
951
/* -------------------------------------------------------------------------- */
952
953
/**
954
 * LteSelf
955
 *
956
 * a <= a ==> true
957
 */
958
959
template<> inline
960
bool RewriteRule<LteSelf>::applies(TNode node) {
961
  return ((node.getKind() == kind::BITVECTOR_ULE ||
962
           node.getKind() == kind::BITVECTOR_SLE) &&
963
          node[0] == node[1]);
964
}
965
966
template<> inline
967
Node RewriteRule<LteSelf>::apply(TNode node) {
968
  Debug("bv-rewrite") << "RewriteRule<LteSelf>(" << node << ")" << std::endl;
969
  return utils::mkTrue();
970
}
971
972
/* -------------------------------------------------------------------------- */
973
974
/**
975
 * ZeroUlt
976
 *
977
 * 0 < a ==> a != 0
978
 */
979
980
template <>
981
inline bool RewriteRule<ZeroUlt>::applies(TNode node)
982
{
983
  return (node.getKind() == kind::BITVECTOR_ULT
984
          && node[0] == utils::mkZero(utils::getSize(node[0])));
985
}
986
987
template <>
988
inline Node RewriteRule<ZeroUlt>::apply(TNode node)
989
{
990
  Debug("bv-rewrite") << "RewriteRule<ZeroUlt>(" << node << ")" << std::endl;
991
  NodeManager *nm = NodeManager::currentNM();
992
  return nm->mkNode(kind::NOT, nm->mkNode(kind::EQUAL, node[0], node[1]));
993
}
994
995
/* -------------------------------------------------------------------------- */
996
997
/**
998
 * UltZero
999
 *
1000
 * a < 0 ==> false
1001
 */
1002
1003
template<> inline
1004
96113
bool RewriteRule<UltZero>::applies(TNode node) {
1005
380537
  return (node.getKind() == kind::BITVECTOR_ULT &&
1006
380537
          node[1] == utils::mkZero(utils::getSize(node[0])));
1007
}
1008
1009
template<> inline
1010
469
Node RewriteRule<UltZero>::apply(TNode node) {
1011
469
  Debug("bv-rewrite") << "RewriteRule<UltZero>(" << node << ")" << std::endl;
1012
469
  return utils::mkFalse();
1013
}
1014
1015
1016
/* -------------------------------------------------------------------------- */
1017
1018
/**
1019
 *
1020
 */
1021
template<> inline
1022
bool RewriteRule<UltOne>::applies(TNode node) {
1023
  return (node.getKind() == kind::BITVECTOR_ULT &&
1024
          node[1] == utils::mkOne(utils::getSize(node[0])));
1025
}
1026
1027
template <>
1028
inline Node RewriteRule<UltOne>::apply(TNode node)
1029
{
1030
  Debug("bv-rewrite") << "RewriteRule<UltOne>(" << node << ")" << std::endl;
1031
  return NodeManager::currentNM()->mkNode(
1032
      kind::EQUAL, node[0], utils::mkZero(utils::getSize(node[0])));
1033
}
1034
1035
/* -------------------------------------------------------------------------- */
1036
1037
/**
1038
 *
1039
 */
1040
template<> inline
1041
bool RewriteRule<SltZero>::applies(TNode node) {
1042
  return (node.getKind() == kind::BITVECTOR_SLT &&
1043
          node[1] == utils::mkZero(utils::getSize(node[0])));
1044
}
1045
1046
template <>
1047
inline Node RewriteRule<SltZero>::apply(TNode node)
1048
{
1049
  Debug("bv-rewrite") << "RewriteRule<UltZero>(" << node << ")" << std::endl;
1050
  unsigned size = utils::getSize(node[0]);
1051
  Node most_significant_bit = utils::mkExtract(node[0], size - 1, size - 1);
1052
  return NodeManager::currentNM()->mkNode(
1053
      kind::EQUAL, most_significant_bit, utils::mkOne(1));
1054
}
1055
1056
/* -------------------------------------------------------------------------- */
1057
1058
/**
1059
 * UltSelf
1060
 *
1061
 * a < a ==> false
1062
 */
1063
1064
template<> inline
1065
bool RewriteRule<UltSelf>::applies(TNode node) {
1066
  return (node.getKind() == kind::BITVECTOR_ULT &&
1067
          node[1] == node[0]);
1068
}
1069
1070
template<> inline
1071
Node RewriteRule<UltSelf>::apply(TNode node) {
1072
  Debug("bv-rewrite") << "RewriteRule<UltSelf>(" << node << ")" << std::endl;
1073
  return utils::mkFalse();
1074
}
1075
1076
1077
/* -------------------------------------------------------------------------- */
1078
1079
/**
1080
 * UleZero
1081
 *
1082
 * a <= 0 ==> a = 0
1083
 */
1084
1085
template<> inline
1086
6466
bool RewriteRule<UleZero>::applies(TNode node) {
1087
25648
  return (node.getKind() == kind::BITVECTOR_ULE &&
1088
25648
          node[1] == utils::mkZero(utils::getSize(node[0])));
1089
}
1090
1091
template <>
1092
42
inline Node RewriteRule<UleZero>::apply(TNode node)
1093
{
1094
42
  Debug("bv-rewrite") << "RewriteRule<UleZero>(" << node << ")" << std::endl;
1095
42
  return NodeManager::currentNM()->mkNode(kind::EQUAL, node[0], node[1]);
1096
}
1097
1098
/* -------------------------------------------------------------------------- */
1099
1100
/**
1101
 * UleSelf
1102
 *
1103
 * a <= a ==> true
1104
 */
1105
1106
template<> inline
1107
6470
bool RewriteRule<UleSelf>::applies(TNode node) {
1108
25538
  return (node.getKind() == kind::BITVECTOR_ULE &&
1109
25538
          node[1] == node[0]);
1110
}
1111
1112
template<> inline
1113
46
Node RewriteRule<UleSelf>::apply(TNode node) {
1114
46
  Debug("bv-rewrite") << "RewriteRule<UleSelf>(" << node << ")" << std::endl;
1115
46
  return utils::mkTrue();
1116
}
1117
1118
/* -------------------------------------------------------------------------- */
1119
1120
/**
1121
 * ZeroUle
1122
 *
1123
 * 0 <= a ==> true
1124
 */
1125
1126
template<> inline
1127
6446
bool RewriteRule<ZeroUle>::applies(TNode node) {
1128
25634
  return (node.getKind() == kind::BITVECTOR_ULE &&
1129
25634
          node[0] == utils::mkZero(utils::getSize(node[0])));
1130
}
1131
1132
template<> inline
1133
22
Node RewriteRule<ZeroUle>::apply(TNode node) {
1134
22
  Debug("bv-rewrite") << "RewriteRule<ZeroUle>(" << node << ")" << std::endl;
1135
22
  return utils::mkTrue();
1136
}
1137
1138
/* -------------------------------------------------------------------------- */
1139
1140
/**
1141
 * UleMax
1142
 *
1143
 * a <= 11..1 ==> true
1144
 */
1145
1146
template<> inline
1147
6448
bool RewriteRule<UleMax>::applies(TNode node) {
1148
6448
  if (node.getKind()!= kind::BITVECTOR_ULE) {
1149
26
    return false;
1150
  }
1151
6422
  uint32_t size = utils::getSize(node[0]);
1152
6422
  return (node.getKind() == kind::BITVECTOR_ULE
1153
12844
          && node[1] == utils::mkOnes(size));
1154
}
1155
1156
template<> inline
1157
24
Node RewriteRule<UleMax>::apply(TNode node) {
1158
24
  Debug("bv-rewrite") << "RewriteRule<UleMax>(" << node << ")" << std::endl;
1159
24
  return utils::mkTrue();
1160
}
1161
1162
/* -------------------------------------------------------------------------- */
1163
1164
/**
1165
 * NotUlt
1166
 *
1167
 * ~ ( a < b) ==> b <= a
1168
 */
1169
1170
template<> inline
1171
bool RewriteRule<NotUlt>::applies(TNode node) {
1172
  return (node.getKind() == kind::NOT &&
1173
          node[0].getKind() == kind::BITVECTOR_ULT);
1174
}
1175
1176
template <>
1177
inline Node RewriteRule<NotUlt>::apply(TNode node)
1178
{
1179
  Debug("bv-rewrite") << "RewriteRule<NotUlt>(" << node << ")" << std::endl;
1180
  Node ult = node[0];
1181
  Node a = ult[0];
1182
  Node b = ult[1];
1183
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULE, b, a);
1184
}
1185
1186
/* -------------------------------------------------------------------------- */
1187
1188
/**
1189
 * NotUle
1190
 *
1191
 * ~ ( a <= b) ==> b < a
1192
 */
1193
1194
template<> inline
1195
bool RewriteRule<NotUle>::applies(TNode node) {
1196
  return (node.getKind() == kind::NOT &&
1197
          node[0].getKind() == kind::BITVECTOR_ULE);
1198
}
1199
1200
template <>
1201
inline Node RewriteRule<NotUle>::apply(TNode node)
1202
{
1203
  Debug("bv-rewrite") << "RewriteRule<NotUle>(" << node << ")" << std::endl;
1204
  Node ult = node[0];
1205
  Node a = ult[0];
1206
  Node b = ult[1];
1207
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, b, a);
1208
}
1209
1210
/* -------------------------------------------------------------------------- */
1211
1212
/**
1213
 * MultPow2
1214
 *
1215
 * (a * 2^k) ==> a[n-k-1:0] 0_k
1216
 */
1217
1218
template <>
1219
240368
inline bool RewriteRule<MultPow2>::applies(TNode node)
1220
{
1221
240368
  if (node.getKind() != kind::BITVECTOR_MULT)
1222
31775
    return false;
1223
1224
800032
  for (const Node& cn : node)
1225
  {
1226
603721
    bool cIsNeg = false;
1227
603721
    if (utils::isPow2Const(cn, cIsNeg))
1228
    {
1229
12282
      return true;
1230
    }
1231
  }
1232
196311
  return false;
1233
}
1234
1235
template <>
1236
6141
inline Node RewriteRule<MultPow2>::apply(TNode node)
1237
{
1238
6141
  Debug("bv-rewrite") << "RewriteRule<MultPow2>(" << node << ")" << std::endl;
1239
6141
  NodeManager *nm = NodeManager::currentNM();
1240
6141
  unsigned size = utils::getSize(node);
1241
12282
  std::vector<Node>  children;
1242
6141
  unsigned exponent = 0;
1243
6141
  bool isNeg = false;
1244
18506
  for (const Node& cn : node)
1245
  {
1246
12365
    bool cIsNeg = false;
1247
12365
    unsigned exp = utils::isPow2Const(cn, cIsNeg);
1248
12365
    if (exp) {
1249
6143
      exponent += exp - 1;
1250
6143
      if (cIsNeg)
1251
      {
1252
1406
        isNeg = !isNeg;
1253
      }
1254
    }
1255
    else {
1256
6222
      children.push_back(cn);
1257
    }
1258
  }
1259
6141
  if (exponent >= size)
1260
  {
1261
    return utils::mkZero(size);
1262
  }
1263
1264
12282
  Node a;
1265
6141
  if (children.empty())
1266
  {
1267
2
    a = utils::mkOne(size);
1268
  }
1269
  else
1270
  {
1271
6139
    a = utils::mkNaryNode(kind::BITVECTOR_MULT, children);
1272
  }
1273
1274
6141
  if (isNeg && size > 1)
1275
  {
1276
1402
    a = nm->mkNode(kind::BITVECTOR_NEG, a);
1277
  }
1278
6141
  if (exponent == 0)
1279
  {
1280
2
    return a;
1281
  }
1282
12278
  Node extract = utils::mkExtract(a, size - exponent - 1, 0);
1283
12278
  Node zeros = utils::mkConst(exponent, 0);
1284
6139
  return utils::mkConcat(extract, zeros);
1285
}
1286
1287
/* -------------------------------------------------------------------------- */
1288
1289
/**
1290
 * ExtractMultLeadingBit
1291
 *
1292
 * If the bit-vectors multiplied have enough leading zeros,
1293
 * we can determine that the top bits of the multiplication
1294
 * are zero and not compute them. Only apply for large bitwidths
1295
 * as this can interfere with other mult normalization rewrites such
1296
 * as flattening.
1297
 */
1298
1299
template<> inline
1300
140303
bool RewriteRule<ExtractMultLeadingBit>::applies(TNode node) {
1301
140303
  if (node.getKind() != kind::BITVECTOR_EXTRACT)
1302
47800
    return false;
1303
92503
  unsigned low = utils::getExtractLow(node);
1304
92503
  node = node[0];
1305
1306
186797
  if (node.getKind() != kind::BITVECTOR_MULT ||
1307
188452
      node.getNumChildren() != 2 ||
1308
95949
      utils::getSize(node) <= 64)
1309
92463
    return false;
1310
1311
184
  if (node[0].getKind() != kind::BITVECTOR_CONCAT ||
1312
168
      node[1].getKind() != kind::BITVECTOR_CONCAT ||
1313
288
      !node[0][0].isConst() ||
1314
104
      !node[1][0].isConst())
1315
8
    return false;
1316
1317
32
  unsigned n = utils::getSize(node);
1318
  // count number of leading zeroes
1319
64
  const Integer& int1 = node[0][0].getConst<BitVector>().toInteger();
1320
64
  const Integer& int2 = node[1][0].getConst<BitVector>().toInteger();
1321
32
  size_t int1_size = utils::getSize(node[0][0]);
1322
32
  size_t int2_size = utils::getSize(node[1][0]);
1323
32
  unsigned zeroes1 = int1.isZero() ? int1_size : int1_size - int1.length();
1324
32
  unsigned zeroes2 = int2.isZero() ? int2_size : int2_size - int2.length();
1325
1326
  // first k bits are not zero in the result
1327
32
  unsigned k = 2 * n - (zeroes1 + zeroes2);
1328
1329
32
  if (k > low)
1330
32
    return false;
1331
1332
  return true;
1333
}
1334
1335
template<> inline
1336
Node RewriteRule<ExtractMultLeadingBit>::apply(TNode node) {
1337
  Debug("bv-rewrite") << "RewriteRule<MultLeadingBit>(" << node << ")" << std::endl;
1338
1339
  unsigned bitwidth = utils::getSize(node);
1340
1341
  // node = node[0];
1342
  // const Integer& int1 = node[0][0].getConst<BitVector>().toInteger();
1343
  // const Integer& int2 = node[1][0].getConst<BitVector>().toInteger();
1344
  // unsigned zeroes1 = int1.isZero()? utils::getSize(node[0][0]) :
1345
  //                                   int1.length();
1346
1347
  // unsigned zeroes2 = int2.isZero()? utils::getSize(node[1][0]) :
1348
  //                                   int2.length();
1349
  // all bits >= k in the multiplier will have to be 0
1350
  // unsigned n = utils::getSize(node);
1351
  // unsigned k = 2 * n - (zeroes1 + zeroes2);
1352
  // Node extract1 = utils::mkExtract(node[0], k - 1, 0);
1353
  // Node extract2 = utils::mkExtract(node[1], k - 1, 0);
1354
  // Node k_zeroes = utils::mkConst(n - k, 0u);
1355
1356
  // NodeManager *nm = NodeManager::currentNM();
1357
  // Node new_mult = nm->mkNode(kind::BITVECTOR_MULT, extract1, extract2);
1358
  // Node result = utils::mkExtract(nm->mkNode(kind::BITVECTOR_CONCAT, k_zeroes, new_mult), high, low);
1359
1360
  // since the extract is over multiplier bits that have to be 0, return 0
1361
  Node result = utils::mkConst(bitwidth, 0u);
1362
  //  std::cout << "MultLeadingBit " << node <<" => " << result <<"\n";
1363
  return result;
1364
}
1365
1366
/* -------------------------------------------------------------------------- */
1367
1368
/**
1369
 * NegIdemp
1370
 *
1371
 * -(-a) ==> a
1372
 */
1373
1374
template<> inline
1375
32163
bool RewriteRule<NegIdemp>::applies(TNode node) {
1376
82345
  return (node.getKind() == kind::BITVECTOR_NEG &&
1377
82345
          node[0].getKind() == kind::BITVECTOR_NEG);
1378
}
1379
1380
template<> inline
1381
102
Node RewriteRule<NegIdemp>::apply(TNode node) {
1382
102
  Debug("bv-rewrite") << "RewriteRule<NegIdemp>(" << node << ")" << std::endl;
1383
102
  return node[0][0];
1384
}
1385
1386
/* -------------------------------------------------------------------------- */
1387
1388
/**
1389
 * UdivPow2
1390
 *
1391
 * (a udiv 2^k) ==> 0_k a[n-1: k]
1392
 */
1393
1394
template <>
1395
27012
inline bool RewriteRule<UdivPow2>::applies(TNode node)
1396
{
1397
27012
  bool isNeg = false;
1398
54024
  if (node.getKind() == kind::BITVECTOR_UDIV
1399
54024
      && utils::isPow2Const(node[1], isNeg))
1400
  {
1401
4408
    return !isNeg;
1402
  }
1403
22604
  return false;
1404
}
1405
1406
template <>
1407
1441
inline Node RewriteRule<UdivPow2>::apply(TNode node)
1408
{
1409
1441
  Debug("bv-rewrite") << "RewriteRule<UdivPow2>(" << node << ")" << std::endl;
1410
1441
  NodeManager *nm = NodeManager::currentNM();
1411
1441
  unsigned size = utils::getSize(node);
1412
2882
  Node a = node[0];
1413
1441
  bool isNeg = false;
1414
1441
  unsigned power = utils::isPow2Const(node[1], isNeg) - 1;
1415
1441
  Node ret;
1416
1441
  if (power == 0)
1417
  {
1418
874
    ret = a;
1419
  }
1420
  else
1421
  {
1422
1134
    Node extract = utils::mkExtract(a, size - 1, power);
1423
1134
    Node zeros = utils::mkConst(power, 0);
1424
1425
567
    ret = nm->mkNode(kind::BITVECTOR_CONCAT, zeros, extract);
1426
  }
1427
1441
  if (isNeg && size > 1)
1428
  {
1429
    ret = nm->mkNode(kind::BITVECTOR_NEG, ret);
1430
  }
1431
2882
  return ret;
1432
}
1433
1434
/* -------------------------------------------------------------------------- */
1435
1436
/**
1437
 * UdivZero
1438
 *
1439
 * (a udiv 0) ==> 111...1
1440
 */
1441
1442
template <>
1443
26569
inline bool RewriteRule<UdivZero>::applies(TNode node) {
1444
26569
  return (node.getKind() == kind::BITVECTOR_UDIV
1445
53138
          && node[1] == utils::mkConst(utils::getSize(node), 0));
1446
}
1447
1448
template <>
1449
96
inline Node RewriteRule<UdivZero>::apply(TNode node) {
1450
96
  Debug("bv-rewrite") << "RewriteRule<UdivZero>(" << node << ")" << std::endl;
1451
96
  return utils::mkOnes(utils::getSize(node));
1452
}
1453
1454
/* -------------------------------------------------------------------------- */
1455
1456
/**
1457
 * UdivOne
1458
 *
1459
 * (a udiv 1) ==> a
1460
 */
1461
1462
template <>
1463
24130
inline bool RewriteRule<UdivOne>::applies(TNode node) {
1464
24130
  return (node.getKind() == kind::BITVECTOR_UDIV
1465
48260
          && node[1] == utils::mkConst(utils::getSize(node), 1));
1466
}
1467
1468
template <>
1469
inline Node RewriteRule<UdivOne>::apply(TNode node) {
1470
  Debug("bv-rewrite") << "RewriteRule<UdivOne>(" << node << ")" << std::endl;
1471
  return node[0];
1472
}
1473
1474
/* -------------------------------------------------------------------------- */
1475
1476
/**
1477
 * UremPow2
1478
 *
1479
 * (a urem 2^k) ==> 0_(n-k) a[k-1:0]
1480
 */
1481
1482
template <>
1483
26421
inline bool RewriteRule<UremPow2>::applies(TNode node)
1484
{
1485
  bool isNeg;
1486
52842
  if (node.getKind() == kind::BITVECTOR_UREM
1487
52842
      && utils::isPow2Const(node[1], isNeg))
1488
  {
1489
3180
    return !isNeg;
1490
  }
1491
23241
  return false;
1492
}
1493
1494
template <>
1495
1183
inline Node RewriteRule<UremPow2>::apply(TNode node)
1496
{
1497
1183
  Debug("bv-rewrite") << "RewriteRule<UremPow2>(" << node << ")" << std::endl;
1498
2366
  TNode a = node[0];
1499
1183
  bool isNeg = false;
1500
1183
  unsigned power = utils::isPow2Const(node[1], isNeg) - 1;
1501
1183
  Node ret;
1502
1183
  if (power == 0)
1503
  {
1504
646
    ret = utils::mkZero(utils::getSize(node));
1505
  }
1506
  else
1507
  {
1508
1074
    Node extract = utils::mkExtract(a, power - 1, 0);
1509
1074
    Node zeros = utils::mkZero(utils::getSize(node) - power);
1510
537
    ret = NodeManager::currentNM()->mkNode(
1511
        kind::BITVECTOR_CONCAT, zeros, extract);
1512
  }
1513
2366
  return ret;
1514
}
1515
1516
/* -------------------------------------------------------------------------- */
1517
1518
/**
1519
 * UremOne
1520
 *
1521
 * (a urem 1) ==> 0
1522
 */
1523
1524
template<> inline
1525
24055
bool RewriteRule<UremOne>::applies(TNode node) {
1526
24055
  return (node.getKind() == kind::BITVECTOR_UREM
1527
48110
          && node[1] == utils::mkConst(utils::getSize(node), 1));
1528
}
1529
1530
template<> inline
1531
Node RewriteRule<UremOne>::apply(TNode node) {
1532
  Debug("bv-rewrite") << "RewriteRule<UremOne>(" << node << ")" << std::endl;
1533
  return utils::mkConst(utils::getSize(node), 0);
1534
}
1535
1536
/* -------------------------------------------------------------------------- */
1537
1538
/**
1539
 * UremSelf
1540
 *
1541
 * (a urem a) ==> 0
1542
 */
1543
1544
template<> inline
1545
24110
bool RewriteRule<UremSelf>::applies(TNode node) {
1546
24110
  return (node.getKind() == kind::BITVECTOR_UREM && node[0] == node[1]);
1547
}
1548
1549
template<> inline
1550
55
Node RewriteRule<UremSelf>::apply(TNode node) {
1551
55
  Debug("bv-rewrite") << "RewriteRule<UremSelf>(" << node << ")" << std::endl;
1552
55
  return utils::mkConst(utils::getSize(node), 0);
1553
}
1554
1555
/* -------------------------------------------------------------------------- */
1556
1557
/**
1558
 * ShiftZero
1559
 *
1560
 * (0_k >> a) ==> 0_k
1561
 */
1562
1563
template<> inline
1564
26399
bool RewriteRule<ShiftZero>::applies(TNode node) {
1565
44063
  return ((node.getKind() == kind::BITVECTOR_SHL ||
1566
23124
           node.getKind() == kind::BITVECTOR_LSHR ||
1567
137455
           node.getKind() == kind::BITVECTOR_ASHR) &&
1568
105596
          node[0] == utils::mkConst(utils::getSize(node), 0));
1569
}
1570
1571
template<> inline
1572
939
Node RewriteRule<ShiftZero>::apply(TNode node) {
1573
939
  Debug("bv-rewrite") << "RewriteRule<ShiftZero>(" << node << ")" << std::endl;
1574
939
  return node[0];
1575
}
1576
1577
/* -------------------------------------------------------------------------- */
1578
1579
/**
1580
 * UgtUrem
1581
 *
1582
 * (bvugt (bvurem T x) x)
1583
 *   ==>  (ite (= x 0_k) (bvugt T x) false)
1584
 *   ==>  (and (=> (= x 0_k) (bvugt T x)) (=> (not (= x 0_k)) false))
1585
 *   ==>  (and (=> (= x 0_k) (bvugt T x)) (= x 0_k))
1586
 *   ==>  (and (bvugt T x) (= x 0_k))
1587
 *   ==>  (and (bvugt T 0_k) (= x 0_k))
1588
 */
1589
1590
template <>
1591
3655
inline bool RewriteRule<UgtUrem>::applies(TNode node)
1592
{
1593
3655
  return (node.getKind() == kind::BITVECTOR_UGT
1594
7310
          && node[0].getKind() == kind::BITVECTOR_UREM
1595
11007
          && node[0][1] == node[1]);
1596
}
1597
1598
template <>
1599
12
inline Node RewriteRule<UgtUrem>::apply(TNode node)
1600
{
1601
12
  Debug("bv-rewrite") << "RewriteRule<UgtUrem>(" << node << ")" << std::endl;
1602
24
  const Node& T = node[0][0];
1603
24
  const Node& x = node[1];
1604
24
  Node zero = utils::mkConst(utils::getSize(x), 0);
1605
12
  NodeManager* nm = NodeManager::currentNM();
1606
  return nm->mkNode(kind::AND,
1607
24
                    nm->mkNode(kind::EQUAL, x, zero),
1608
48
                    nm->mkNode(kind::BITVECTOR_UGT, T, zero));
1609
}
1610
1611
/* -------------------------------------------------------------------------- */
1612
1613
/**
1614
 * BBAddNeg
1615
 *
1616
 * -a1 - a2 - ... - an + ak + ..  ==> - (a1 + a2 + ... + an) + ak
1617
 *
1618
 */
1619
1620
template <>
1621
inline bool RewriteRule<BBAddNeg>::applies(TNode node)
1622
{
1623
  if (node.getKind() != kind::BITVECTOR_ADD)
1624
  {
1625
    return false;
1626
  }
1627
1628
  unsigned neg_count = 0;
1629
  for(unsigned i = 0; i < node.getNumChildren(); ++i) {
1630
    if (node[i].getKind()== kind::BITVECTOR_NEG) {
1631
      ++neg_count;
1632
    }
1633
  }
1634
  return neg_count > 1;
1635
}
1636
1637
template <>
1638
inline Node RewriteRule<BBAddNeg>::apply(TNode node)
1639
{
1640
  Debug("bv-rewrite") << "RewriteRule<BBAddNeg>(" << node << ")" << std::endl;
1641
  NodeManager *nm = NodeManager::currentNM();
1642
  std::vector<Node> children;
1643
  unsigned neg_count = 0;
1644
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1645
  {
1646
    if (node[i].getKind() == kind::BITVECTOR_NEG)
1647
    {
1648
      ++neg_count;
1649
      children.push_back(nm->mkNode(kind::BITVECTOR_NOT, node[i][0]));
1650
    }
1651
    else
1652
    {
1653
      children.push_back(node[i]);
1654
    }
1655
  }
1656
  Assert(neg_count != 0);
1657
  children.push_back(utils::mkConst(utils::getSize(node), neg_count));
1658
1659
  return utils::mkNaryNode(kind::BITVECTOR_ADD, children);
1660
}
1661
1662
/* -------------------------------------------------------------------------- */
1663
1664
template<> inline
1665
55226
bool RewriteRule<MergeSignExtend>::applies(TNode node) {
1666
275390
  if (node.getKind() != kind::BITVECTOR_SIGN_EXTEND ||
1667
275390
      (node[0].getKind() != kind::BITVECTOR_SIGN_EXTEND &&
1668
164938
       node[0].getKind() != kind::BITVECTOR_ZERO_EXTEND))
1669
54486
    return false;
1670
740
  return true;
1671
}
1672
1673
template<> inline
1674
370
Node RewriteRule<MergeSignExtend>::apply(TNode node) {
1675
370
  Debug("bv-rewrite") << "RewriteRule<MergeSignExtend>(" << node << ")" << std::endl;
1676
  unsigned amount1 =
1677
370
      node.getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount;
1678
1679
370
  NodeManager* nm = NodeManager::currentNM();
1680
370
  if (node[0].getKind() == kind::BITVECTOR_ZERO_EXTEND) {
1681
    unsigned amount2 = node[0]
1682
370
                           .getOperator()
1683
185
                           .getConst<BitVectorZeroExtend>()
1684
185
                           .d_zeroExtendAmount;
1685
185
    if (amount2 == 0)
1686
    {
1687
138
      NodeBuilder nb(kind::BITVECTOR_SIGN_EXTEND);
1688
138
      Node op = nm->mkConst<BitVectorSignExtend>(BitVectorSignExtend(amount1));
1689
69
      nb << op << node[0][0];
1690
138
      Node res = nb;
1691
69
      return res;
1692
    }
1693
232
    NodeBuilder nb(kind::BITVECTOR_ZERO_EXTEND);
1694
    Node op = nm->mkConst<BitVectorZeroExtend>(
1695
232
        BitVectorZeroExtend(amount1 + amount2));
1696
116
    nb << op << node[0][0];
1697
232
    Node res = nb;
1698
116
    return res;
1699
  }
1700
185
  Assert(node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND);
1701
  unsigned amount2 =
1702
185
      node[0].getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount;
1703
185
  return utils::mkSignExtend(node[0][0], amount1 + amount2);
1704
}
1705
1706
/* -------------------------------------------------------------------------- */
1707
1708
/**
1709
 * ZeroExtendEqConst
1710
 *
1711
 * Rewrite zero_extend(x^n, m) = c^n+m to
1712
 *
1713
 *   false         if c[n+m-1:n] != 0
1714
 *   x = c[n-1:0]  otherwise.
1715
 */
1716
template <>
1717
inline bool RewriteRule<ZeroExtendEqConst>::applies(TNode node) {
1718
  return node.getKind() == kind::EQUAL &&
1719
         ((node[0].getKind() == kind::BITVECTOR_ZERO_EXTEND &&
1720
           node[1].isConst()) ||
1721
          (node[1].getKind() == kind::BITVECTOR_ZERO_EXTEND &&
1722
           node[0].isConst()));
1723
}
1724
1725
template <>
1726
inline Node RewriteRule<ZeroExtendEqConst>::apply(TNode node) {
1727
  TNode t, c;
1728
  if (node[0].getKind() == kind::BITVECTOR_ZERO_EXTEND) {
1729
    t = node[0][0];
1730
    c = node[1];
1731
  } else {
1732
    t = node[1][0];
1733
    c = node[0];
1734
  }
1735
  BitVector c_hi =
1736
      c.getConst<BitVector>().extract(utils::getSize(c) - 1, utils::getSize(t));
1737
  BitVector c_lo = c.getConst<BitVector>().extract(utils::getSize(t) - 1, 0);
1738
  BitVector zero = BitVector(c_hi.getSize(), Integer(0));
1739
1740
  if (c_hi == zero) {
1741
    return NodeManager::currentNM()->mkNode(kind::EQUAL, t,
1742
                                            utils::mkConst(c_lo));
1743
  }
1744
  return utils::mkFalse();
1745
}
1746
1747
/* -------------------------------------------------------------------------- */
1748
1749
/**
1750
 * SignExtendEqConst
1751
 *
1752
 * Rewrite sign_extend(x^n, m) = c^n+m to
1753
 *
1754
 *   x = c[n-1:0]   if (c[n-1:n-1] == 0 && c[n+m-1:n] == 0) ||
1755
 *                     (c[n-1:n-1] == 1 && c[n+m-1:n] == ~0)
1756
 *   false          otherwise.
1757
 */
1758
template <>
1759
inline bool RewriteRule<SignExtendEqConst>::applies(TNode node) {
1760
  return node.getKind() == kind::EQUAL &&
1761
         ((node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND &&
1762
           node[1].isConst()) ||
1763
          (node[1].getKind() == kind::BITVECTOR_SIGN_EXTEND &&
1764
           node[0].isConst()));
1765
}
1766
1767
template <>
1768
inline Node RewriteRule<SignExtendEqConst>::apply(TNode node) {
1769
  TNode t, c;
1770
  if (node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND) {
1771
    t = node[0][0];
1772
    c = node[1];
1773
  } else {
1774
    t = node[1][0];
1775
    c = node[0];
1776
  }
1777
  unsigned pos_msb_t = utils::getSize(t) - 1;
1778
  BitVector c_hi =
1779
      c.getConst<BitVector>().extract(utils::getSize(c) - 1, pos_msb_t);
1780
  BitVector c_lo = c.getConst<BitVector>().extract(pos_msb_t, 0);
1781
  BitVector zero = BitVector(c_hi.getSize(), Integer(0));
1782
1783
  if (c_hi == zero || c_hi == ~zero) {
1784
    return NodeManager::currentNM()->mkNode(kind::EQUAL, t,
1785
                                            utils::mkConst(c_lo));
1786
  }
1787
  return utils::mkFalse();
1788
}
1789
1790
/* -------------------------------------------------------------------------- */
1791
1792
/**
1793
 * ZeroExtendUltConst
1794
 *
1795
 * Rewrite zero_extend(x^n,m) < c^n+m to
1796
 *
1797
 *   x < c[n-1:0]   if c[n+m-1:n] == 0.
1798
 *
1799
 * Rewrite c^n+m < Rewrite zero_extend(x^n,m) to
1800
 *
1801
 *   c[n-1:0] < x   if c[n+m-1:n] == 0.
1802
 */
1803
template <>
1804
95672
inline bool RewriteRule<ZeroExtendUltConst>::applies(TNode node) {
1805
378627
  if (node.getKind() == kind::BITVECTOR_ULT &&
1806
286684
      ((node[0].getKind() == kind::BITVECTOR_ZERO_EXTEND &&
1807
286520
        node[1].isConst()) ||
1808
286262
       (node[1].getKind() == kind::BITVECTOR_ZERO_EXTEND &&
1809
99312
        node[0].isConst()))) {
1810
338
    TNode t, c;
1811
169
    bool is_lhs = node[0].getKind() == kind::BITVECTOR_ZERO_EXTEND;
1812
169
    if (is_lhs) {
1813
82
      t = node[0][0];
1814
82
      c = node[1];
1815
    } else {
1816
87
      t = node[1][0];
1817
87
      c = node[0];
1818
    }
1819
1820
169
    if (utils::getSize(t) == utils::getSize(c))
1821
    {
1822
8
      return false;
1823
    }
1824
1825
322
    BitVector bv_c = c.getConst<BitVector>();
1826
483
    BitVector c_hi = c.getConst<BitVector>().extract(utils::getSize(c) - 1,
1827
644
                                                     utils::getSize(t));
1828
322
    BitVector zero = BitVector(c_hi.getSize(), Integer(0));
1829
1830
161
    return c_hi == zero;
1831
  }
1832
95503
  return false;
1833
}
1834
1835
template <>
1836
28
inline Node RewriteRule<ZeroExtendUltConst>::apply(TNode node) {
1837
56
  TNode t, c;
1838
28
  bool is_lhs = node[0].getKind() == kind::BITVECTOR_ZERO_EXTEND;
1839
28
  if (is_lhs) {
1840
12
    t = node[0][0];
1841
12
    c = node[1];
1842
  } else {
1843
16
    t = node[1][0];
1844
16
    c = node[0];
1845
  }
1846
  Node c_lo =
1847
56
      utils::mkConst(c.getConst<BitVector>().extract(utils::getSize(t) - 1, 0));
1848
1849
28
  if (is_lhs) {
1850
12
    return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, t, c_lo);
1851
  }
1852
16
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_ULT, c_lo, t);
1853
}
1854
1855
/* -------------------------------------------------------------------------- */
1856
1857
/**
1858
 * SignExtendUltConst
1859
 *
1860
 * Rewrite sign_extend(x^n,m) < c^n+m to
1861
 *
1862
 *   x < c[n-1:0]   if (c <= (1 << (n - 1))) || (c >= (~0 << (n - 1)))
1863
 *   x[n-1:n-1] = 0 if (1 << (n - 1)) < c <= (~0 << (n - 1)).
1864
 *
1865
 * Rewrite c^n+m < sign_extend(x^n,m) to
1866
 *
1867
 *   c[n-1:0] < x   if (c < (1 << (n - 1))) || (c >= ~(1 << (n-1)))
1868
 *   x[n-1:n-1] = 1 if ~(~0 << (n-1)) <= c <= ~(1 << (n-1))
1869
 *
1870
 * where ~(~0 << (n - 1)) == (1 << (n - 1)) - 1
1871
 *
1872
 */
1873
template <>
1874
96107
inline bool RewriteRule<SignExtendUltConst>::applies(TNode node)
1875
{
1876
192214
  if (node.getKind() == kind::BITVECTOR_ULT
1877
289247
      && ((node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND
1878
109169
           && node[1].isConst())
1879
190086
          || (node[1].getKind() == kind::BITVECTOR_SIGN_EXTEND
1880
109359
              && node[0].isConst())))
1881
  {
1882
1852
    TNode x, c;
1883
926
    bool is_lhs = node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND;
1884
926
    if (is_lhs)
1885
    {
1886
354
      x = node[0][0];
1887
354
      c = node[1];
1888
    }
1889
    else
1890
    {
1891
572
      x = node[1][0];
1892
572
      c = node[0];
1893
    }
1894
1852
    BitVector bv_c = c.getConst<BitVector>();
1895
926
    unsigned size_c = utils::getSize(c);
1896
926
    unsigned msb_x_pos = utils::getSize(x) - 1;
1897
    // (1 << (n - 1)))
1898
1852
    BitVector bv_msb_x(size_c);
1899
926
    bv_msb_x.setBit(msb_x_pos, true);
1900
    // (~0 << (n - 1))
1901
    BitVector bv_upper_bits =
1902
1852
        (~BitVector(size_c)).leftShift(BitVector(size_c, msb_x_pos));
1903
1904
    return (is_lhs
1905
354
            && (bv_c <= bv_msb_x || bv_c >= bv_upper_bits
1906
222
                || (bv_msb_x < bv_c && bv_c <= bv_upper_bits)))
1907
2424
           || (!is_lhs
1908
1498
               && (bv_c < bv_msb_x || bv_c >= ~bv_msb_x
1909
1184
                   || (~bv_upper_bits <= bv_c && bv_c <= ~bv_msb_x)));
1910
  }
1911
95181
  return false;
1912
}
1913
1914
template <>
1915
463
inline Node RewriteRule<SignExtendUltConst>::apply(TNode node)
1916
{
1917
926
  TNode x, c;
1918
463
  bool is_lhs = node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND;
1919
463
  if (is_lhs)
1920
  {
1921
177
    x = node[0][0];
1922
177
    c = node[1];
1923
  }
1924
  else
1925
  {
1926
286
    x = node[1][0];
1927
286
    c = node[0];
1928
  }
1929
926
  BitVector bv_c = c.getConst<BitVector>();
1930
1931
463
  unsigned size_c = utils::getSize(c);
1932
463
  unsigned msb_x_pos = utils::getSize(x) - 1;
1933
926
  Node c_lo = utils::mkConst(bv_c.extract(msb_x_pos, 0));
1934
  // (1 << (n - 1)))
1935
926
  BitVector bv_msb_x(size_c);
1936
463
  bv_msb_x.setBit(msb_x_pos, true);
1937
  // (~0 << (n - 1))
1938
  BitVector bv_upper_bits =
1939
926
      (~BitVector(size_c)).leftShift(BitVector(size_c, msb_x_pos));
1940
1941
463
  NodeManager* nm = NodeManager::currentNM();
1942
463
  if (is_lhs)
1943
  {
1944
    // x[n-1:n-1] = 0
1945
177
    if (bv_msb_x < bv_c && bv_c <= bv_upper_bits)
1946
    {
1947
262
      Node msb_x = utils::mkExtract(x, msb_x_pos, msb_x_pos);
1948
131
      return nm->mkNode(kind::EQUAL, msb_x, utils::mkZero(1));
1949
    }
1950
    // x < c[n-1:0]
1951
46
    Assert(bv_c <= bv_msb_x || bv_c >= bv_upper_bits);
1952
46
    return nm->mkNode(kind::BITVECTOR_ULT, x, c_lo);
1953
  }
1954
1955
  // x[n-1:n-1] = 1
1956
286
  if (~bv_upper_bits <= bv_c && bv_c <= ~bv_msb_x)
1957
  {
1958
420
    Node msb_x = utils::mkExtract(x, msb_x_pos, msb_x_pos);
1959
210
    return nm->mkNode(kind::EQUAL, msb_x, utils::mkOne(1));
1960
  }
1961
  // c[n-1:0] < x
1962
76
  Assert(bv_c < bv_msb_x || bv_c >= ~bv_msb_x);
1963
76
  return nm->mkNode(kind::BITVECTOR_ULT, c_lo, x);
1964
}
1965
1966
/* -------------------------------------------------------------------------- */
1967
1968
template<> inline
1969
4
bool RewriteRule<MultSlice>::applies(TNode node) {
1970
4
  if (node.getKind() != kind::BITVECTOR_MULT || node.getNumChildren() != 2) {
1971
2
    return false;
1972
  }
1973
2
  return utils::getSize(node[0]) % 2 == 0;
1974
}
1975
1976
/**
1977
 * Expressses the multiplication in terms of the top and bottom
1978
 * slices of the terms. Note increases circuit size, but could
1979
 * lead to simplifications (use wisely!).
1980
 *
1981
 * @param node
1982
 *
1983
 * @return
1984
 */
1985
template <>
1986
2
inline Node RewriteRule<MultSlice>::apply(TNode node)
1987
{
1988
2
  Debug("bv-rewrite") << "RewriteRule<MultSlice>(" << node << ")" << std::endl;
1989
2
  NodeManager *nm = NodeManager::currentNM();
1990
2
  unsigned bitwidth = utils::getSize(node[0]);
1991
4
  Node zeros = utils::mkConst(bitwidth / 2, 0);
1992
4
  TNode a = node[0];
1993
4
  Node bottom_a = utils::mkExtract(a, bitwidth / 2 - 1, 0);
1994
4
  Node top_a = utils::mkExtract(a, bitwidth - 1, bitwidth / 2);
1995
4
  TNode b = node[1];
1996
4
  Node bottom_b = utils::mkExtract(b, bitwidth / 2 - 1, 0);
1997
4
  Node top_b = utils::mkExtract(b, bitwidth - 1, bitwidth / 2);
1998
1999
  Node term1 = nm->mkNode(kind::BITVECTOR_MULT,
2000
4
                          nm->mkNode(kind::BITVECTOR_CONCAT, zeros, bottom_a),
2001
8
                          nm->mkNode(kind::BITVECTOR_CONCAT, zeros, bottom_b));
2002
2003
  Node term2 = nm->mkNode(kind::BITVECTOR_CONCAT,
2004
4
                          nm->mkNode(kind::BITVECTOR_MULT, top_b, bottom_a),
2005
8
                          zeros);
2006
  Node term3 = nm->mkNode(kind::BITVECTOR_CONCAT,
2007
4
                          nm->mkNode(kind::BITVECTOR_MULT, top_a, bottom_b),
2008
8
                          zeros);
2009
4
  return nm->mkNode(kind::BITVECTOR_ADD, term1, term2, term3);
2010
}
2011
2012
/* -------------------------------------------------------------------------- */
2013
2014
/**
2015
 * x < y + 1 <=> (not y < x) and y != 1...1
2016
 *
2017
 * @param node
2018
 *
2019
 * @return
2020
 */
2021
template <>
2022
inline bool RewriteRule<UltAddOne>::applies(TNode node)
2023
{
2024
  if (node.getKind() != kind::BITVECTOR_ULT) return false;
2025
  TNode x = node[0];
2026
  TNode y1 = node[1];
2027
  if (y1.getKind() != kind::BITVECTOR_ADD) return false;
2028
  if (y1[0].getKind() != kind::CONST_BITVECTOR &&
2029
      y1[1].getKind() != kind::CONST_BITVECTOR)
2030
    return false;
2031
2032
  if (y1[0].getKind() == kind::CONST_BITVECTOR &&
2033
      y1[1].getKind() == kind::CONST_BITVECTOR)
2034
    return false;
2035
2036
  if (y1.getNumChildren() != 2)
2037
    return false;
2038
2039
  TNode one = y1[0].getKind() == kind::CONST_BITVECTOR ? y1[0] : y1[1];
2040
  if (one != utils::mkConst(utils::getSize(one), 1)) return false;
2041
  return true;
2042
}
2043
2044
template <>
2045
inline Node RewriteRule<UltAddOne>::apply(TNode node)
2046
{
2047
  Debug("bv-rewrite") << "RewriteRule<UltAddOne>(" << node << ")" << std::endl;
2048
  NodeManager *nm = NodeManager::currentNM();
2049
  TNode x = node[0];
2050
  TNode y1 = node[1];
2051
  TNode y = y1[0].getKind() != kind::CONST_BITVECTOR ? y1[0] : y1[1];
2052
  unsigned size = utils::getSize(x);
2053
  Node not_y_eq_1 =
2054
      nm->mkNode(kind::NOT, nm->mkNode(kind::EQUAL, y, utils::mkOnes(size)));
2055
  Node not_y_lt_x =
2056
      nm->mkNode(kind::NOT, nm->mkNode(kind::BITVECTOR_ULT, y, x));
2057
  return nm->mkNode(kind::AND, not_y_eq_1, not_y_lt_x);
2058
}
2059
2060
/* -------------------------------------------------------------------------- */
2061
2062
/**
2063
 * x ^(x-1) = 0 => 1 << sk
2064
 * WARNING: this is an **EQUISATISFIABLE** transformation!
2065
 * Only to be called on top level assertions.
2066
 *
2067
 * @param node
2068
 *
2069
 * @return
2070
 */
2071
template<> inline
2072
14
bool RewriteRule<IsPowerOfTwo>::applies(TNode node) {
2073
14
  if (node.getKind()!= kind::EQUAL) return false;
2074
32
  if (node[0].getKind() != kind::BITVECTOR_AND &&
2075
18
      node[1].getKind() != kind::BITVECTOR_AND)
2076
2
    return false;
2077
48
  if (!utils::isZero(node[0]) &&
2078
36
      !utils::isZero(node[1]))
2079
    return false;
2080
2081
24
  TNode t = !utils::isZero(node[0])? node[0]: node[1];
2082
12
  if (t.getNumChildren() != 2) return false;
2083
24
  TNode a = t[0];
2084
24
  TNode b = t[1];
2085
12
  unsigned size = utils::getSize(t);
2086
12
  if(size < 2) return false;
2087
  Node diff = Rewriter::rewrite(
2088
24
      NodeManager::currentNM()->mkNode(kind::BITVECTOR_SUB, a, b));
2089
12
  return (diff.isConst() && (diff == utils::mkConst(size, 1u) || diff == utils::mkOnes(size)));
2090
}
2091
2092
template <>
2093
6
inline Node RewriteRule<IsPowerOfTwo>::apply(TNode node)
2094
{
2095
12
  Debug("bv-rewrite") << "RewriteRule<IsPowerOfTwo>(" << node << ")"
2096
6
                      << std::endl;
2097
6
  NodeManager *nm = NodeManager::currentNM();
2098
12
  TNode term = utils::isZero(node[0]) ? node[1] : node[0];
2099
12
  TNode a = term[0];
2100
12
  TNode b = term[1];
2101
6
  unsigned size = utils::getSize(term);
2102
12
  Node diff = Rewriter::rewrite(nm->mkNode(kind::BITVECTOR_SUB, a, b));
2103
6
  Assert(diff.isConst());
2104
12
  TNode x = diff == utils::mkConst(size, 1u) ? a : b;
2105
12
  Node one = utils::mkConst(size, 1u);
2106
12
  Node sk = utils::mkVar(size);
2107
12
  Node sh = nm->mkNode(kind::BITVECTOR_SHL, one, sk);
2108
6
  Node x_eq_sh = nm->mkNode(kind::EQUAL, x, sh);
2109
12
  return x_eq_sh;
2110
}
2111
2112
/* -------------------------------------------------------------------------- */
2113
2114
/**
2115
 * Rewrite
2116
 *   sign_extend(x+t,n) * sign_extend(a,m) < sign_extend(x,n) * sign_extend(a,m)
2117
 * to
2118
 *   (and
2119
 *    (not (= t zero))
2120
 *    (not (= a zero))
2121
 *    (= (bvslt (bvadd x t) x) (bvsgt a zero))
2122
 *   )
2123
 *
2124
 * Rewrite
2125
 *   zero_extend(x+t,n) * sign_extend(a,m) < zero_extend(x,n) * sign_extend(a,m)
2126
 * to
2127
 *   (and
2128
 *    (not (= t zero))
2129
 *    (not (= a zero))
2130
 *    (= (bvult (bvadd x t) x) (bvsgt a zero))
2131
 *   )
2132
 * where n and m are sufficiently big to not produce an overflow for
2133
 * the multiplications.
2134
 *
2135
 * These patterns occur in the quantified BV benchmark family 'ranking',
2136
 * where the BV engine struggles due to the high bit widths of the
2137
 * multiplication's operands.
2138
 */
2139
static std::tuple<Node, Node, bool>
2140
37
extract_ext_tuple(TNode node)
2141
{
2142
74
  TNode a = node[0];
2143
74
  TNode b = node[1];
2144
111
  for (unsigned i = 0; i < 2; ++i)
2145
  {
2146
148
    if (a.getKind() == kind::BITVECTOR_CONCAT
2147
29
        && b.getKind() == kind::BITVECTOR_SIGN_EXTEND
2148
74
        && a[0] == utils::mkZero(utils::getSize(a[0]))
2149
74
        && utils::getSize(a[1]) <= utils::getSize(a[0])
2150
148
        && utils::getSize(b[0]) <= utils::getSignExtendAmount(b))
2151
    {
2152
      return std::make_tuple(a[1], b[0], false);
2153
    }
2154
74
    else if (i == 0
2155
37
             && a.getKind() == kind::BITVECTOR_SIGN_EXTEND
2156
             && b.getKind() == kind::BITVECTOR_SIGN_EXTEND
2157
74
             && utils::getSize(a[0]) <= utils::getSignExtendAmount(a)
2158
74
             && utils::getSize(b[0]) <= utils::getSignExtendAmount(b))
2159
    {
2160
      return std::make_tuple(a[0], b[0], true);
2161
    }
2162
74
    std::swap(a, b);
2163
  }
2164
37
  return std::make_tuple(Node::null(), Node::null(), false);
2165
}
2166
2167
/* -------------------------------------------------------------------------- */
2168
2169
template<> inline
2170
103218
bool RewriteRule<MultSltMult>::applies(TNode node)
2171
{
2172
206436
  if (node.getKind() != kind::BITVECTOR_SLT
2173
205179
      || node[0].getKind() != kind::BITVECTOR_MULT
2174
208813
      || node[1].getKind() != kind::BITVECTOR_MULT)
2175
103171
    return false;
2176
2177
47
  if (node[0].getNumChildren() > 2 || node[1].getNumChildren() > 2)
2178
10
    return false;
2179
2180
  bool is_sext_l, is_sext_r;
2181
74
  TNode ml[2], mr[2];
2182
2183
37
  std::tie(ml[0], ml[1], is_sext_l) = extract_ext_tuple(node[0]);
2184
37
  if (ml[0].isNull())
2185
37
    return false;
2186
2187
  std::tie(mr[0], mr[1], is_sext_r) = extract_ext_tuple(node[1]);
2188
  if (mr[0].isNull())
2189
    return false;
2190
2191
  if (is_sext_l != is_sext_r)
2192
    return false;
2193
2194
  TNode addxt, x, a;
2195
  if (ml[0].getKind() == kind::BITVECTOR_ADD)
2196
  {
2197
    addxt = ml[0];
2198
    a = ml[1];
2199
  }
2200
  else if (ml[1].getKind() == kind::BITVECTOR_ADD)
2201
  {
2202
    addxt = ml[1];
2203
    a = ml[0];
2204
  }
2205
  else
2206
    return false;
2207
2208
  if (addxt.getNumChildren() > 2)
2209
    return false;
2210
2211
  if (mr[0] == a)
2212
  {
2213
    x = mr[1];
2214
  }
2215
  else if (mr[1] == a)
2216
  {
2217
    x = mr[0];
2218
  }
2219
  else
2220
    return false;
2221
2222
  return (addxt[0] == x || addxt[1] == x);
2223
}
2224
2225
template<> inline
2226
Node RewriteRule<MultSltMult>::apply(TNode node)
2227
{
2228
  bool is_sext;
2229
  TNode ml[2], mr[2];
2230
2231
  std::tie(ml[0], ml[1], is_sext) = extract_ext_tuple(node[0]);
2232
  std::tie(mr[0], mr[1], std::ignore) = extract_ext_tuple(node[1]);
2233
2234
  TNode addxt, x, t, a;
2235
  if (ml[0].getKind() == kind::BITVECTOR_ADD)
2236
  {
2237
    addxt = ml[0];
2238
    a = ml[1];
2239
  }
2240
  else
2241
  {
2242
    Assert(ml[1].getKind() == kind::BITVECTOR_ADD);
2243
    addxt = ml[1];
2244
    a = ml[0];
2245
  }
2246
2247
  x = (mr[0] == a) ? mr[1] : mr[0];
2248
  t = (addxt[0] == x) ? addxt[1] : addxt[0];
2249
2250
  NodeManager *nm = NodeManager::currentNM();
2251
  Node zero_t = utils::mkZero(utils::getSize(t));
2252
  Node zero_a = utils::mkZero(utils::getSize(a));
2253
2254
  NodeBuilder nb(kind::AND);
2255
  Kind k = is_sext ? kind::BITVECTOR_SLT : kind::BITVECTOR_ULT;
2256
  nb << t.eqNode(zero_t).notNode();
2257
  nb << a.eqNode(zero_a).notNode();
2258
  nb << nm->mkNode(k, addxt, x)
2259
            .eqNode(nm->mkNode(kind::BITVECTOR_SGT, a, zero_a));
2260
  return nb.constructNode();
2261
}
2262
2263
}  // namespace bv
2264
}  // namespace theory
2265
}  // namespace cvc5