GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv_rewrite_rules_simplification.h Lines: 669 747 89.6 %
Date: 2021-05-22 Branches: 1968 4290 45.9 %

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