GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv_rewrite_rules_normalization.h Lines: 587 726 80.9 %
Date: 2021-09-29 Branches: 1194 2919 40.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Aina Niemetz, Clark Barrett
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 <unordered_map>
24
#include <unordered_set>
25
26
#include "expr/node_algorithm.h"
27
#include "theory/bv/theory_bv_rewrite_rules.h"
28
#include "theory/bv/theory_bv_utils.h"
29
#include "theory/rewriter.h"
30
#include "util/bitvector.h"
31
32
namespace cvc5 {
33
namespace theory {
34
namespace bv {
35
36
/**
37
 * ExtractBitwise
38
 *   (x bvop y) [i:j] ==> x[i:j] bvop y[i:j]
39
 *  where bvop is bvand,bvor, bvxor
40
 */
41
template<> inline
42
bool RewriteRule<ExtractBitwise>::applies(TNode node) {
43
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
44
          (node[0].getKind() == kind::BITVECTOR_AND ||
45
           node[0].getKind() == kind::BITVECTOR_OR ||
46
           node[0].getKind() == kind::BITVECTOR_XOR ));
47
}
48
49
template<> inline
50
Node RewriteRule<ExtractBitwise>::apply(TNode node) {
51
  Debug("bv-rewrite") << "RewriteRule<ExtractBitwise>(" << node << ")" << std::endl;
52
  unsigned high = utils::getExtractHigh(node);
53
  unsigned low = utils::getExtractLow(node);
54
  std::vector<Node> children;
55
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i) {
56
    children.push_back(utils::mkExtract(node[0][i], high, low));
57
  }
58
  Kind kind = node[0].getKind();
59
  return utils::mkSortedNode(kind, children);
60
}
61
62
/**
63
 * ExtractNot
64
 *
65
 *  (~ a) [i:j] ==> ~ (a[i:j])
66
 */
67
template<> inline
68
81955
bool RewriteRule<ExtractNot>::applies(TNode node) {
69
245865
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
70
245865
          node[0].getKind() == kind::BITVECTOR_NOT);
71
}
72
73
template <>
74
1263
inline Node RewriteRule<ExtractNot>::apply(TNode node)
75
{
76
1263
  Debug("bv-rewrite") << "RewriteRule<ExtractNot>(" << node << ")" << std::endl;
77
1263
  unsigned low = utils::getExtractLow(node);
78
1263
  unsigned high = utils::getExtractHigh(node);
79
2526
  Node a = utils::mkExtract(node[0][0], high, low);
80
2526
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, a);
81
}
82
83
/**
84
 * ExtractSignExtend
85
 *
86
 * (sign_extend k x) [i:j] => pushes extract in
87
 *
88
 * @return
89
 */
90
91
template<> inline
92
81252
bool RewriteRule<ExtractSignExtend>::applies(TNode node) {
93
325008
  if (node.getKind() == kind::BITVECTOR_EXTRACT &&
94
243756
      node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND) {
95
560
    return true;
96
  }
97
80692
  return false;
98
}
99
100
template <>
101
280
inline Node RewriteRule<ExtractSignExtend>::apply(TNode node)
102
{
103
560
  Debug("bv-rewrite") << "RewriteRule<ExtractSignExtend>(" << node << ")"
104
280
                      << std::endl;
105
560
  TNode extendee = node[0][0];
106
280
  unsigned extendee_size = utils::getSize(extendee);
107
108
280
  unsigned high = utils::getExtractHigh(node);
109
280
  unsigned low = utils::getExtractLow(node);
110
111
280
  Node resultNode;
112
  // extract falls on extendee
113
280
  if (high < extendee_size)
114
  {
115
121
    resultNode = utils::mkExtract(extendee, high, low);
116
  }
117
159
  else if (low < extendee_size && high >= extendee_size)
118
  {
119
    // if extract overlaps sign extend and extendee
120
44
    Node low_extract = utils::mkExtract(extendee, extendee_size - 1, low);
121
22
    unsigned new_amount = high - extendee_size + 1;
122
44
    resultNode = utils::mkSignExtend(low_extract, new_amount);
123
  }
124
  else
125
  {
126
    // extract only over sign extend
127
137
    Assert(low >= extendee_size);
128
137
    unsigned top = utils::getSize(extendee) - 1;
129
274
    Node most_significant_bit = utils::mkExtract(extendee, top, top);
130
274
    std::vector<Node> bits;
131
382
    for (unsigned i = 0; i < high - low + 1; ++i)
132
    {
133
245
      bits.push_back(most_significant_bit);
134
    }
135
137
    resultNode = utils::mkConcat(bits);
136
  }
137
560
  Debug("bv-rewrite") << "                           =>" << resultNode
138
280
                      << std::endl;
139
560
  return resultNode;
140
}
141
142
/**
143
 * ExtractArith
144
 *
145
 * (a bvop b) [k:0] ==> (a[k:0] bvop b[k:0])
146
 */
147
148
template<> inline
149
bool RewriteRule<ExtractArith>::applies(TNode node) {
150
  return (node.getKind() == kind::BITVECTOR_EXTRACT
151
          && utils::getExtractLow(node) == 0
152
          && (node[0].getKind() == kind::BITVECTOR_ADD
153
              || node[0].getKind() == kind::BITVECTOR_MULT));
154
}
155
156
template <>
157
inline Node RewriteRule<ExtractArith>::apply(TNode node)
158
{
159
  Debug("bv-rewrite") << "RewriteRule<ExtractArith>(" << node << ")"
160
                      << std::endl;
161
  unsigned low = utils::getExtractLow(node);
162
  Assert(low == 0);
163
  unsigned high = utils::getExtractHigh(node);
164
  std::vector<Node> children;
165
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
166
  {
167
    children.push_back(utils::mkExtract(node[0][i], high, low));
168
  }
169
  Kind kind = node[0].getKind();
170
  return utils::mkNaryNode(kind, children);
171
}
172
173
/**
174
 * ExtractArith2
175
 *
176
 * (a bvop b) [i:j] ==> (a[i:0] bvop b[i:0]) [i:j]
177
 */
178
179
// careful not to apply in a loop
180
template<> inline
181
bool RewriteRule<ExtractArith2>::applies(TNode node) {
182
  return (node.getKind() == kind::BITVECTOR_EXTRACT
183
          && (node[0].getKind() == kind::BITVECTOR_ADD
184
              || node[0].getKind() == kind::BITVECTOR_MULT));
185
}
186
187
template <>
188
inline Node RewriteRule<ExtractArith2>::apply(TNode node)
189
{
190
  Debug("bv-rewrite") << "RewriteRule<ExtractArith2>(" << node << ")"
191
                      << std::endl;
192
  unsigned low = utils::getExtractLow(node);
193
  unsigned high = utils::getExtractHigh(node);
194
  std::vector<Node> children;
195
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
196
  {
197
    children.push_back(utils::mkExtract(node[0][i], high, 0));
198
  }
199
  Kind kind = node[0].getKind();
200
  Node op_children = utils::mkNaryNode(kind, children);
201
202
  return utils::mkExtract(op_children, high, low);
203
}
204
205
template<> inline
206
378191
bool RewriteRule<FlattenAssocCommut>::applies(TNode node) {
207
378191
  Kind kind = node.getKind();
208
378191
  if (kind != kind::BITVECTOR_ADD && kind != kind::BITVECTOR_MULT
209
4603
      && kind != kind::BITVECTOR_OR && kind != kind::BITVECTOR_XOR
210
      && kind != kind::BITVECTOR_AND)
211
    return false;
212
378191
  TNode::iterator child_it = node.begin();
213
2614227
  for(; child_it != node.end(); ++child_it) {
214
1169730
    if ((*child_it).getKind() == kind) {
215
51712
      return true;
216
    }
217
  }
218
326479
  return false;
219
}
220
221
template <>
222
25860
inline Node RewriteRule<FlattenAssocCommut>::apply(TNode node)
223
{
224
51720
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")"
225
25860
                      << std::endl;
226
51720
  std::vector<Node> processingStack;
227
25860
  processingStack.push_back(node);
228
51720
  std::vector<Node> children;
229
25860
  Kind kind = node.getKind();
230
231
447928
  while (!processingStack.empty())
232
  {
233
422068
    TNode current = processingStack.back();
234
211034
    processingStack.pop_back();
235
236
    // flatten expression
237
211034
    if (current.getKind() == kind)
238
    {
239
245723
      for (unsigned i = 0; i < current.getNumChildren(); ++i)
240
      {
241
185174
        processingStack.push_back(current[i]);
242
      }
243
    }
244
    else
245
    {
246
150485
      children.push_back(current);
247
    }
248
  }
249
51720
  if (node.getKind() == kind::BITVECTOR_ADD
250
25860
      || node.getKind() == kind::BITVECTOR_MULT)
251
  {
252
25817
    return utils::mkNaryNode(kind, children);
253
  }
254
  else
255
  {
256
43
    return utils::mkSortedNode(kind, children);
257
  }
258
}
259
260
512014
static inline void addToCoefMap(std::map<Node, BitVector>& map,
261
                                TNode term, const BitVector& coef) {
262
512014
  if (map.find(term) != map.end()) {
263
398
    map[term] = map[term] + coef;
264
  } else {
265
511616
    map[term] = coef;
266
  }
267
512014
}
268
269
270
652078
static inline void updateCoefMap(TNode current, unsigned size,
271
                                 std::map<Node, BitVector>& factorToCoefficient,
272
                                 BitVector& constSum) {
273
652078
  switch (current.getKind()) {
274
244726
    case kind::BITVECTOR_MULT: {
275
      // look for c * term, where c is a constant
276
489452
      BitVector coeff;
277
489452
      Node term;
278
244726
      if (current.getNumChildren() == 2) {
279
        // Mult should be normalized with only one constant at end
280
56391
        Assert(!current[0].isConst());
281
56391
        if (current[1].isConst()) {
282
44320
          coeff = current[1].getConst<BitVector>();
283
44320
          term = current[0];
284
        }
285
      }
286
188335
      else if (current[current.getNumChildren()-1].isConst()) {
287
359738
        NodeBuilder nb(kind::BITVECTOR_MULT);
288
179869
        TNode::iterator child_it = current.begin();
289
1192785
        for(; (child_it+1) != current.end(); ++child_it) {
290
506458
          Assert(!(*child_it).isConst());
291
506458
          nb << (*child_it);
292
        }
293
179869
        term = nb;
294
179869
        coeff = (*child_it).getConst<BitVector>();
295
      }
296
244726
      if (term.isNull()) {
297
20537
        coeff = BitVector(size, (unsigned)1);
298
20537
        term = current;
299
      }
300
244726
      if(term.getKind() == kind::BITVECTOR_SUB) {
301
        TNode a = term[0];
302
        TNode b = term[1];
303
        addToCoefMap(factorToCoefficient, a, coeff);
304
        addToCoefMap(factorToCoefficient, b, -coeff);
305
      }
306
244726
      else if(term.getKind() == kind::BITVECTOR_NEG) {
307
        addToCoefMap(factorToCoefficient, term[0], -BitVector(size, coeff));
308
      }
309
      else {
310
244726
        addToCoefMap(factorToCoefficient, term, coeff);
311
      }
312
244726
      break;
313
    }
314
    case kind::BITVECTOR_SUB:
315
      // turn into a + (-1)*b
316
      Assert(current.getNumChildren() == 2);
317
      addToCoefMap(factorToCoefficient, current[0], BitVector(size, (unsigned)1));
318
      addToCoefMap(factorToCoefficient, current[1], -BitVector(size, (unsigned)1));
319
      break;
320
70074
    case kind::BITVECTOR_NEG:
321
70074
      addToCoefMap(factorToCoefficient, current[0], -BitVector(size, (unsigned)1));
322
70074
      break;
323
140064
    case kind::CONST_BITVECTOR: {
324
280128
      BitVector constValue = current.getConst<BitVector>();
325
140064
      constSum = constSum + constValue;
326
140064
      break;
327
    }
328
197214
    default:
329
      // store as 1 * current
330
197214
      addToCoefMap(factorToCoefficient, current, BitVector(size, (unsigned)1));
331
197214
      break;
332
  }
333
652078
}
334
335
510432
static inline void addToChildren(TNode term,
336
                                 unsigned size,
337
                                 BitVector coeff,
338
                                 std::vector<Node> &children)
339
{
340
510432
  NodeManager *nm = NodeManager::currentNM();
341
510432
  if (coeff == BitVector(size, (unsigned)0))
342
  {
343
65
    return;
344
  }
345
510367
  else if (coeff == BitVector(size, (unsigned)1))
346
  {
347
216350
    children.push_back(term);
348
  }
349
294017
  else if (coeff == -BitVector(size, (unsigned)1))
350
  {
351
    // avoid introducing an extra multiplication
352
69581
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, term));
353
  }
354
224436
  else if (term.getKind() == kind::BITVECTOR_MULT)
355
  {
356
359712
    NodeBuilder nb(kind::BITVECTOR_MULT);
357
179856
    TNode::iterator child_it = term.begin();
358
1192700
    for (; child_it != term.end(); ++child_it)
359
    {
360
506422
      nb << *child_it;
361
    }
362
179856
    nb << utils::mkConst(coeff);
363
179856
    children.push_back(Node(nb));
364
  }
365
  else
366
  {
367
89160
    Node coeffNode = utils::mkConst(coeff);
368
89160
    Node product = nm->mkNode(kind::BITVECTOR_MULT, term, coeffNode);
369
44580
    children.push_back(product);
370
  }
371
}
372
373
template <>
374
131718
inline bool RewriteRule<AddCombineLikeTerms>::applies(TNode node)
375
{
376
131718
  return (node.getKind() == kind::BITVECTOR_ADD);
377
}
378
379
template <>
380
65859
inline Node RewriteRule<AddCombineLikeTerms>::apply(TNode node)
381
{
382
131718
  Debug("bv-rewrite") << "RewriteRule<AddCombineLikeTerms>(" << node << ")"
383
65859
                      << std::endl;
384
65859
  unsigned size = utils::getSize(node);
385
131718
  BitVector constSum(size, (unsigned)0);
386
131718
  std::map<Node, BitVector> factorToCoefficient;
387
388
  // combine like-terms
389
455905
  for (size_t i = 0, n = node.getNumChildren(); i < n; ++i)
390
  {
391
780092
    TNode current = node[i];
392
390046
    updateCoefMap(current, size, factorToCoefficient, constSum);
393
  }
394
395
131718
  std::vector<Node> children;
396
397
  // construct result
398
65859
  std::map<Node, BitVector>::const_iterator it = factorToCoefficient.begin();
399
400
686873
  for (; it != factorToCoefficient.end(); ++it)
401
  {
402
310507
    addToChildren(it->first, size, it->second, children);
403
  }
404
405
65859
  if (constSum != BitVector(size, (unsigned)0))
406
  {
407
41839
    children.push_back(utils::mkConst(constSum));
408
  }
409
410
65859
  size_t csize = children.size();
411
65859
  if (csize == node.getNumChildren())
412
  {
413
    // If we couldn't combine any terms, we don't perform the rewrite. This is
414
    // important because we are otherwise reordering terms in the addition
415
    // based on the node ids of the terms that are multiplied with the
416
    // coefficients. Due to garbage collection we may see different id orders
417
    // for those nodes even when we perform one rewrite directly after the
418
    // other, so the rewrite wouldn't be idempotent.
419
30256
    return node;
420
  }
421
422
  return csize == 0 ? utils::mkZero(size)
423
35603
                    : utils::mkNaryNode(kind::BITVECTOR_ADD, children);
424
}
425
426
template<> inline
427
460218
bool RewriteRule<MultSimplify>::applies(TNode node) {
428
460218
  return node.getKind() == kind::BITVECTOR_MULT;
429
}
430
431
template <>
432
230109
inline Node RewriteRule<MultSimplify>::apply(TNode node)
433
{
434
460218
  Debug("bv-rewrite") << "RewriteRule<MultSimplify>(" << node << ")"
435
230109
                      << std::endl;
436
230109
  NodeManager *nm = NodeManager::currentNM();
437
230109
  unsigned size = utils::getSize(node);
438
460218
  BitVector constant(size, Integer(1));
439
440
230109
  bool isNeg = false;
441
460218
  std::vector<Node> children;
442
865959
  for (const TNode &current : node)
443
  {
444
1281092
    Node c = current;
445
645242
    if (c.getKind() == kind::BITVECTOR_NEG)
446
    {
447
1313
      isNeg = !isNeg;
448
1313
      c = c[0];
449
    }
450
451
645242
    if (c.getKind() == kind::CONST_BITVECTOR)
452
    {
453
456710
      BitVector value = c.getConst<BitVector>();
454
233051
      constant = constant * value;
455
233051
      if (constant == BitVector(size, (unsigned)0))
456
      {
457
9392
        return utils::mkConst(size, 0);
458
      }
459
    }
460
    else
461
    {
462
412191
      children.push_back(c);
463
    }
464
  }
465
441434
  BitVector oValue = BitVector(size, static_cast<unsigned>(1));
466
441434
  BitVector noValue = BitVector::mkOnes(size);
467
468
220717
  if (children.empty())
469
  {
470
19948
    return utils::mkConst(isNeg ? -constant : constant);
471
  }
472
473
200769
  std::sort(children.begin(), children.end());
474
475
200769
  if (constant == noValue)
476
  {
477
1054
    isNeg = !isNeg;
478
  }
479
199715
  else if (constant != oValue)
480
  {
481
174207
    if (isNeg)
482
    {
483
1159
      isNeg = !isNeg;
484
1159
      constant = -constant;
485
    }
486
174207
    children.push_back(utils::mkConst(constant));
487
  }
488
489
401538
  Node ret = utils::mkNaryNode(kind::BITVECTOR_MULT, children);
490
491
  // if negative, negate entire node
492
200769
  if (isNeg && size > 1)
493
  {
494
861
    ret = nm->mkNode(kind::BITVECTOR_NEG, ret);
495
  }
496
200769
  return ret;
497
}
498
499
template<> inline
500
88344
bool RewriteRule<MultDistribConst>::applies(TNode node) {
501
155635
  if (node.getKind() != kind::BITVECTOR_MULT ||
502
67291
      node.getNumChildren() != 2) {
503
63849
    return false;
504
  }
505
24495
  Assert(!node[0].isConst());
506
24495
  if (!node[1].isConst()) {
507
9990
    return false;
508
  }
509
29010
  TNode factor = node[0];
510
14505
  return (factor.getKind() == kind::BITVECTOR_ADD
511
12347
          || factor.getKind() == kind::BITVECTOR_SUB
512
26852
          || factor.getKind() == kind::BITVECTOR_NEG);
513
}
514
515
template <>
516
1079
inline Node RewriteRule<MultDistribConst>::apply(TNode node)
517
{
518
2158
  Debug("bv-rewrite") << "RewriteRule<MultDistribConst>(" << node << ")"
519
1079
                      << std::endl;
520
521
1079
  NodeManager *nm = NodeManager::currentNM();
522
2158
  TNode constant = node[1];
523
2158
  TNode factor = node[0];
524
1079
  Assert(constant.getKind() == kind::CONST_BITVECTOR);
525
526
1079
  if (factor.getKind() == kind::BITVECTOR_NEG)
527
  {
528
    // push negation on the constant part
529
    BitVector const_bv = constant.getConst<BitVector>();
530
    return nm->mkNode(
531
        kind::BITVECTOR_MULT, factor[0], utils::mkConst(-const_bv));
532
  }
533
534
2158
  std::vector<Node> children;
535
11323
  for (unsigned i = 0; i < factor.getNumChildren(); ++i)
536
  {
537
10244
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, factor[i], constant));
538
  }
539
540
1079
  return utils::mkNaryNode(factor.getKind(), children);
541
}
542
543
template<> inline
544
87603
bool RewriteRule<MultDistrib>::applies(TNode node) {
545
153074
  if (node.getKind() != kind::BITVECTOR_MULT ||
546
65471
      node.getNumChildren() != 2) {
547
64928
    return false;
548
  }
549
68025
  if (node[0].getKind() == kind::BITVECTOR_ADD
550
68025
      || node[0].getKind() == kind::BITVECTOR_SUB)
551
  {
552
102
    return node[1].getKind() != kind::BITVECTOR_ADD
553
102
           && node[1].getKind() != kind::BITVECTOR_SUB;
554
  }
555
67923
  return node[1].getKind() == kind::BITVECTOR_ADD
556
67923
         || node[1].getKind() == kind::BITVECTOR_SUB;
557
}
558
559
template <>
560
338
inline Node RewriteRule<MultDistrib>::apply(TNode node)
561
{
562
676
  Debug("bv-rewrite") << "RewriteRule<MultDistrib>(" << node << ")"
563
338
                      << std::endl;
564
565
338
  NodeManager *nm = NodeManager::currentNM();
566
1014
  bool is_rhs_factor = node[0].getKind() == kind::BITVECTOR_ADD
567
1014
                       || node[0].getKind() == kind::BITVECTOR_SUB;
568
676
  TNode factor = !is_rhs_factor ? node[0] : node[1];
569
676
  TNode sum = is_rhs_factor ? node[0] : node[1];
570
338
  Assert(factor.getKind() != kind::BITVECTOR_ADD
571
         && factor.getKind() != kind::BITVECTOR_SUB
572
         && (sum.getKind() == kind::BITVECTOR_ADD
573
             || sum.getKind() == kind::BITVECTOR_SUB));
574
575
676
  std::vector<Node> children;
576
20844
  for (unsigned i = 0; i < sum.getNumChildren(); ++i)
577
  {
578
20506
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, sum[i], factor));
579
  }
580
581
676
  return utils::mkNaryNode(sum.getKind(), children);
582
}
583
584
template<> inline
585
4
bool RewriteRule<ConcatToMult>::applies(TNode node) {
586
4
  if (node.getKind() != kind::BITVECTOR_CONCAT) return false;
587
  if (node.getNumChildren() != 2) return false;
588
  if (node[0].getKind()!= kind::BITVECTOR_EXTRACT) return false;
589
  if (!node[1].isConst()) return false;
590
  TNode extract = node[0];
591
  TNode c = node[1];
592
  unsigned amount = utils::getSize(c);
593
594
  if (utils::getSize(node) != utils::getSize(extract[0])) return false;
595
  if (c != utils::mkZero(amount)) return false;
596
597
  unsigned low = utils::getExtractLow(extract);
598
  if (low != 0) return false;
599
  unsigned high = utils::getExtractHigh(extract);
600
  if (high + amount + 1 != utils::getSize(node)) return false;
601
  return true;
602
}
603
604
template <>
605
inline Node RewriteRule<ConcatToMult>::apply(TNode node)
606
{
607
  Debug("bv-rewrite") << "RewriteRule<ConcatToMult>(" << node << ")"
608
                      << std::endl;
609
  unsigned size = utils::getSize(node);
610
  Node factor = node[0][0];
611
  Assert(utils::getSize(factor) == utils::getSize(node));
612
  BitVector amount = BitVector(size, utils::getSize(node[1]));
613
  Node coef = utils::mkConst(BitVector(size, 1u).leftShift(amount));
614
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_MULT, factor, coef);
615
}
616
617
template <>
618
271545
inline bool RewriteRule<SolveEq>::applies(TNode node)
619
{
620
543090
  if (node.getKind() != kind::EQUAL
621
520665
      || (node[0].isVar() && !expr::hasSubterm(node[1], node[0]))
622
767192
      || (node[1].isVar() && !expr::hasSubterm(node[0], node[1])))
623
  {
624
64985
    return false;
625
  }
626
206560
  return true;
627
}
628
629
// Doesn't do full solving (yet), instead, if a term appears both on lhs and
630
// rhs, it subtracts from both sides so that one side's coeff is zero
631
template <>
632
103280
inline Node RewriteRule<SolveEq>::apply(TNode node)
633
{
634
103280
  Debug("bv-rewrite") << "RewriteRule<SolveEq>(" << node << ")" << std::endl;
635
636
206560
  TNode left = node[0];
637
206560
  TNode right = node[1];
638
639
103280
  unsigned size = utils::getSize(left);
640
206560
  BitVector zero(size, (unsigned)0);
641
206560
  BitVector leftConst(size, (unsigned)0);
642
206560
  BitVector rightConst(size, (unsigned)0);
643
206560
  std::map<Node, BitVector> leftMap, rightMap;
644
645
  // Collect terms and coefficients plus constant for left
646
103280
  if (left.getKind() == kind::BITVECTOR_ADD)
647
  {
648
59798
    for (unsigned i = 0; i < left.getNumChildren(); ++i)
649
    {
650
54939
      updateCoefMap(left[i], size, leftMap, leftConst);
651
    }
652
  }
653
98421
  else if (left.getKind() == kind::BITVECTOR_NOT && left[0] == right)
654
  {
655
17
    return utils::mkFalse();
656
  }
657
  else
658
  {
659
98404
    updateCoefMap(left, size, leftMap, leftConst);
660
  }
661
662
  // Collect terms and coefficients plus constant for right
663
103263
  if (right.getKind() == kind::BITVECTOR_ADD)
664
  {
665
15510
    for (unsigned i = 0; i < right.getNumChildren(); ++i)
666
    {
667
10468
      updateCoefMap(right[i], size, rightMap, rightConst);
668
    }
669
  }
670
98221
  else if (right.getKind() == kind::BITVECTOR_NOT && right[0] == left)
671
  {
672
    return utils::mkFalse();
673
  }
674
  else
675
  {
676
98221
    updateCoefMap(right, size, rightMap, rightConst);
677
  }
678
679
206526
  std::vector<Node> childrenLeft, childrenRight;
680
681
103263
  std::map<Node, BitVector>::const_iterator iLeft = leftMap.begin(),
682
103263
                                            iLeftEnd = leftMap.end();
683
103263
  std::map<Node, BitVector>::const_iterator iRight = rightMap.begin(),
684
103263
                                            iRightEnd = rightMap.end();
685
686
206526
  BitVector coeffLeft;
687
206526
  TNode termLeft;
688
103263
  if (iLeft != iLeftEnd)
689
  {
690
101065
    coeffLeft = iLeft->second;
691
101065
    termLeft = iLeft->first;
692
  }
693
694
206526
  BitVector coeffRight;
695
206526
  TNode termRight;
696
103263
  if (iRight != iRightEnd)
697
  {
698
52598
    coeffRight = iRight->second;
699
52598
    termRight = iRight->first;
700
  }
701
702
  // Changed tracks whether there have been any changes to the coefficients or
703
  // constants of the left- or right-hand side. We perform a rewrite only if
704
  // that is the case. This is important because we are otherwise reordering
705
  // terms in the addition based on the node ids of the terms that are
706
  // multiplied with the coefficients. Due to garbage collection we may see
707
  // different id orders for those nodes even when we perform one rewrite
708
  // directly after the other, so the rewrite wouldn't be idempotent.
709
103263
  bool changed = false;
710
  bool incLeft, incRight;
711
712
504247
  while (iLeft != iLeftEnd || iRight != iRightEnd)
713
  {
714
200492
    incLeft = incRight = false;
715
200492
    if (iLeft != iLeftEnd && (iRight == iRightEnd || termLeft < termRight))
716
    {
717
146617
      addToChildren(termLeft, size, coeffLeft, childrenLeft);
718
146617
      incLeft = true;
719
    }
720
53875
    else if (iLeft == iLeftEnd || termRight < termLeft)
721
    {
722
53258
      Assert(iRight != iRightEnd);
723
53258
      addToChildren(termRight, size, coeffRight, childrenRight);
724
53258
      incRight = true;
725
    }
726
    else
727
    {
728
617
      if (coeffLeft > coeffRight)
729
      {
730
50
        addToChildren(termLeft, size, coeffLeft - coeffRight, childrenLeft);
731
      }
732
567
      else if (coeffRight > coeffLeft)
733
      {
734
        addToChildren(termRight, size, coeffRight - coeffLeft, childrenRight);
735
      }
736
617
      incLeft = incRight = true;
737
617
      changed = true;
738
    }
739
200492
    if (incLeft)
740
    {
741
147234
      ++iLeft;
742
147234
      if (iLeft != iLeftEnd)
743
      {
744
46169
        Assert(termLeft < iLeft->first);
745
46169
        coeffLeft = iLeft->second;
746
46169
        termLeft = iLeft->first;
747
      }
748
    }
749
200492
    if (incRight)
750
    {
751
53875
      ++iRight;
752
53875
      if (iRight != iRightEnd)
753
      {
754
1277
        Assert(termRight < iRight->first);
755
1277
        coeffRight = iRight->second;
756
1277
        termRight = iRight->first;
757
      }
758
    }
759
  }
760
761
  // construct result
762
763
  // If both constants are nonzero, combine on right, otherwise leave them where
764
  // they are
765
103263
  if (rightConst != zero)
766
  {
767
40921
    changed |= (leftConst != zero);
768
40921
    rightConst = rightConst - leftConst;
769
40921
    leftConst = zero;
770
40921
    if (rightConst != zero)
771
    {
772
40438
      childrenRight.push_back(utils::mkConst(rightConst));
773
    }
774
  }
775
62342
  else if (leftConst != zero)
776
  {
777
3895
    childrenLeft.push_back(utils::mkConst(leftConst));
778
  }
779
780
206526
  Node newLeft, newRight;
781
782
103263
  if (childrenRight.size() == 0 && leftConst != zero)
783
  {
784
279
    Assert(childrenLeft.back().isConst()
785
           && childrenLeft.back().getConst<BitVector>() == leftConst);
786
279
    if (childrenLeft.size() == 1)
787
    {
788
      // c = 0 ==> false
789
84
      return utils::mkFalse();
790
    }
791
    // special case - if right is empty and left has a constant, move the
792
    // constant
793
195
    childrenRight.push_back(utils::mkConst(-leftConst));
794
195
    childrenLeft.pop_back();
795
195
    changed = true;
796
  }
797
798
103179
  if (childrenLeft.size() == 0)
799
  {
800
1074
    if (rightConst != zero)
801
    {
802
764
      Assert(childrenRight.back().isConst()
803
             && childrenRight.back().getConst<BitVector>() == rightConst);
804
764
      if (childrenRight.size() == 1)
805
      {
806
        // 0 = c ==> false
807
467
        return utils::mkFalse();
808
      }
809
      // special case - if left is empty and right has a constant, move the
810
      // constant
811
297
      newLeft = utils::mkConst(-rightConst);
812
297
      childrenRight.pop_back();
813
297
      changed = true;
814
    }
815
    else
816
    {
817
310
      newLeft = utils::mkConst(size, (unsigned)0);
818
    }
819
  }
820
  else
821
  {
822
102105
    newLeft = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenLeft);
823
  }
824
825
102712
  if (childrenRight.size() == 0)
826
  {
827
13860
    newRight = utils::mkConst(size, (unsigned)0);
828
  }
829
  else
830
  {
831
88852
    newRight = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenRight);
832
  }
833
834
102712
  if (!changed)
835
  {
836
101016
    return node;
837
  }
838
839
1696
  if (newLeft == newRight)
840
  {
841
3
    Assert(newLeft == utils::mkConst(size, (unsigned)0));
842
3
    return utils::mkTrue();
843
  }
844
845
1693
  if (newLeft < newRight)
846
  {
847
595
    Assert((newRight == left && newLeft == right)
848
           || Rewriter::rewrite(newRight) != left
849
           || Rewriter::rewrite(newLeft) != right);
850
595
    return newRight.eqNode(newLeft);
851
  }
852
853
1098
  Assert((newLeft == left && newRight == right)
854
         || Rewriter::rewrite(newLeft) != left
855
         || Rewriter::rewrite(newRight) != right);
856
1098
  return newLeft.eqNode(newRight);
857
}
858
859
template<> inline
860
23
bool RewriteRule<BitwiseEq>::applies(TNode node) {
861
66
  if (node.getKind() != kind::EQUAL ||
862
43
      utils::getSize(node[0]) != 1) {
863
23
    return false;
864
  }
865
  TNode term;
866
  BitVector c;
867
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
868
    c = node[0].getConst<BitVector>();
869
    term = node[1];
870
  }
871
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
872
    c = node[1].getConst<BitVector>();
873
    term = node[0];
874
  }
875
  else {
876
    return false;
877
  }
878
  switch (term.getKind()) {
879
    case kind::BITVECTOR_AND:
880
    case kind::BITVECTOR_OR:
881
      //operator BITVECTOR_XOR 2: "bitwise xor"
882
    case kind::BITVECTOR_NOT:
883
    case kind::BITVECTOR_NAND:
884
    case kind::BITVECTOR_NOR:
885
      //operator BITVECTOR_XNOR 2 "bitwise xnor"
886
    case kind::BITVECTOR_COMP:
887
    case kind::BITVECTOR_NEG:
888
      return true;
889
      break;
890
    default:
891
      break;
892
  }
893
  return false;
894
}
895
896
897
static inline Node mkNodeKind(Kind k, TNode node, TNode c) {
898
  unsigned i = 0;
899
  unsigned nc = node.getNumChildren();
900
  NodeBuilder nb(k);
901
  for(; i < nc; ++i) {
902
    nb << node[i].eqNode(c);
903
  }
904
  return nb;
905
}
906
907
908
template<> inline
909
Node RewriteRule<BitwiseEq>::apply(TNode node) {
910
  Debug("bv-rewrite") << "RewriteRule<BitwiseEq>(" << node << ")" << std::endl;
911
912
  TNode term;
913
  BitVector c;
914
915
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
916
    c = node[0].getConst<BitVector>();
917
    term = node[1];
918
  }
919
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
920
    c = node[1].getConst<BitVector>();
921
    term = node[0];
922
  }
923
924
  bool eqOne = (c == BitVector(1,(unsigned)1));
925
926
  switch (term.getKind()) {
927
    case kind::BITVECTOR_AND:
928
      if (eqOne) {
929
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
930
      }
931
      else {
932
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
933
      }
934
      break;
935
    case kind::BITVECTOR_NAND:
936
      if (eqOne) {
937
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
938
      }
939
      else {
940
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
941
      }
942
      break;
943
    case kind::BITVECTOR_OR:
944
      if (eqOne) {
945
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
946
      }
947
      else {
948
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
949
      }
950
      break;
951
    case kind::BITVECTOR_NOR:
952
      if (eqOne) {
953
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
954
      }
955
      else {
956
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
957
      }
958
      break;
959
    case kind::BITVECTOR_NOT:
960
      return term[0].eqNode(utils::mkConst(~c));
961
    case kind::BITVECTOR_COMP:
962
      Assert(term.getNumChildren() == 2);
963
      if (eqOne) {
964
        return term[0].eqNode(term[1]);
965
      }
966
      else {
967
        return term[0].eqNode(term[1]).notNode();
968
      }
969
    case kind::BITVECTOR_NEG:
970
      return term[0].eqNode(utils::mkConst(c));
971
    default:
972
      break;
973
  }
974
  Unreachable();
975
}
976
977
978
/**
979
 * -(c * expr) ==> (-c * expr)
980
 * where c is a constant
981
 */
982
template<> inline
983
13609
bool RewriteRule<NegMult>::applies(TNode node) {
984
54436
  if(node.getKind()!= kind::BITVECTOR_NEG ||
985
40827
     node[0].getKind() != kind::BITVECTOR_MULT) {
986
12711
    return false;
987
  }
988
898
  return node[node.getNumChildren()-1].isConst();
989
}
990
991
template<> inline
992
Node RewriteRule<NegMult>::apply(TNode node) {
993
  Debug("bv-rewrite") << "RewriteRule<NegMult>(" << node << ")" << std::endl;
994
  TNode mult = node[0];
995
  NodeBuilder nb(kind::BITVECTOR_MULT);
996
  BitVector bv(utils::getSize(node), (unsigned)1);
997
  TNode::iterator child_it = mult.begin();
998
  for(; (child_it+1) != mult.end(); ++child_it) {
999
    nb << (*child_it);
1000
  }
1001
  Assert((*child_it).isConst());
1002
  bv = (*child_it).getConst<BitVector>();
1003
  nb << utils::mkConst(-bv);
1004
  return Node(nb);
1005
}
1006
1007
template<> inline
1008
26907
bool RewriteRule<NegSub>::applies(TNode node) {
1009
66659
  return (node.getKind() == kind::BITVECTOR_NEG &&
1010
66659
          node[0].getKind() == kind::BITVECTOR_SUB);
1011
}
1012
1013
template <>
1014
103
inline Node RewriteRule<NegSub>::apply(TNode node)
1015
{
1016
103
  Debug("bv-rewrite") << "RewriteRule<NegSub>(" << node << ")" << std::endl;
1017
  return NodeManager::currentNM()->mkNode(
1018
103
      kind::BITVECTOR_SUB, node[0][1], node[0][0]);
1019
}
1020
1021
template <>
1022
28028
inline bool RewriteRule<NegAdd>::applies(TNode node)
1023
{
1024
28028
  return (node.getKind() == kind::BITVECTOR_NEG
1025
56056
          && node[0].getKind() == kind::BITVECTOR_ADD);
1026
}
1027
1028
template <>
1029
1224
inline Node RewriteRule<NegAdd>::apply(TNode node)
1030
{
1031
1224
  Debug("bv-rewrite") << "RewriteRule<NegAdd>(" << node << ")" << std::endl;
1032
1224
  NodeManager *nm = NodeManager::currentNM();
1033
2448
  std::vector<Node> children;
1034
3677
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
1035
  {
1036
2453
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, node[0][i]));
1037
  }
1038
2448
  return utils::mkNaryNode(kind::BITVECTOR_ADD, children);
1039
}
1040
1041
struct Count {
1042
  unsigned pos;
1043
  unsigned neg;
1044
577880
  Count() : pos(0), neg(0) {}
1045
577880
  Count(unsigned p, unsigned n):
1046
    pos(p),
1047
577880
    neg(n)
1048
577880
  {}
1049
};
1050
1051
578463
inline static void insert(std::unordered_map<TNode, Count>& map,
1052
                          TNode node,
1053
                          bool neg)
1054
{
1055
578463
  if(map.find(node) == map.end()) {
1056
577880
    Count c = neg? Count(0,1) : Count(1, 0);
1057
577880
    map[node] = c;
1058
  } else {
1059
583
    if (neg) {
1060
230
      ++(map[node].neg);
1061
    } else {
1062
353
      ++(map[node].pos);
1063
    }
1064
  }
1065
578463
}
1066
1067
template<> inline
1068
217418
bool RewriteRule<AndSimplify>::applies(TNode node) {
1069
217418
  return (node.getKind() == kind::BITVECTOR_AND);
1070
}
1071
1072
template <>
1073
108709
inline Node RewriteRule<AndSimplify>::apply(TNode node)
1074
{
1075
217418
  Debug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")"
1076
108709
                      << std::endl;
1077
1078
108709
  NodeManager *nm = NodeManager::currentNM();
1079
  // this will remove duplicates
1080
217418
  std::unordered_map<TNode, Count> subterms;
1081
108709
  unsigned size = utils::getSize(node);
1082
217418
  BitVector constant = BitVector::mkOnes(size);
1083
364287
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1084
  {
1085
511156
    TNode current = node[i];
1086
    // simplify constants
1087
255578
    if (current.getKind() == kind::CONST_BITVECTOR)
1088
    {
1089
183148
      BitVector bv = current.getConst<BitVector>();
1090
91574
      constant = constant & bv;
1091
    }
1092
    else
1093
    {
1094
164004
      if (current.getKind() == kind::BITVECTOR_NOT)
1095
      {
1096
57754
        insert(subterms, current[0], true);
1097
      }
1098
      else
1099
      {
1100
106250
        insert(subterms, current, false);
1101
      }
1102
    }
1103
  }
1104
1105
217418
  std::vector<Node> children;
1106
1107
108709
  if (constant == BitVector(size, (unsigned)0))
1108
  {
1109
27305
    return utils::mkZero(size);
1110
  }
1111
1112
81404
  if (constant != BitVector::mkOnes(size))
1113
  {
1114
30689
    children.push_back(utils::mkConst(constant));
1115
  }
1116
1117
81404
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1118
1119
388296
  for (; it != subterms.end(); ++it)
1120
  {
1121
153514
    if (it->second.pos > 0 && it->second.neg > 0)
1122
    {
1123
      // if we have a and ~a
1124
68
      return utils::mkZero(size);
1125
    }
1126
    else
1127
    {
1128
      // idempotence
1129
153446
      if (it->second.neg > 0)
1130
      {
1131
        // if it only occured negated
1132
53326
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1133
      }
1134
      else
1135
      {
1136
        // if it only occured positive
1137
100120
        children.push_back(it->first);
1138
      }
1139
    }
1140
  }
1141
81336
  if (children.size() == 0)
1142
  {
1143
207
    return utils::mkOnes(size);
1144
  }
1145
1146
81129
  return utils::mkSortedNode(kind::BITVECTOR_AND, children);
1147
}
1148
1149
template<> inline
1150
257116
bool RewriteRule<FlattenAssocCommutNoDuplicates>::applies(TNode node) {
1151
257116
  Kind kind = node.getKind();
1152
257116
  if (kind != kind::BITVECTOR_OR &&
1153
      kind != kind::BITVECTOR_AND)
1154
    return false;
1155
257116
  TNode::iterator child_it = node.begin();
1156
1674922
  for(; child_it != node.end(); ++child_it) {
1157
739141
    if ((*child_it).getKind() == kind) {
1158
30238
      return true;
1159
    }
1160
  }
1161
226878
  return false;
1162
}
1163
1164
template<> inline
1165
15119
Node RewriteRule<FlattenAssocCommutNoDuplicates>::apply(TNode node) {
1166
15119
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")" << std::endl;
1167
30238
  std::vector<Node> processingStack;
1168
15119
  processingStack.push_back(node);
1169
30238
  std::unordered_set<TNode> processed;
1170
30238
  std::vector<Node> children;
1171
15119
  Kind kind = node.getKind();
1172
1173
301787
  while (! processingStack.empty()) {
1174
285688
    TNode current = processingStack.back();
1175
143334
    processingStack.pop_back();
1176
143334
    if (processed.count(current))
1177
980
      continue;
1178
1179
142354
    processed.insert(current);
1180
1181
    // flatten expression
1182
142354
    if (current.getKind() == kind) {
1183
161986
      for (unsigned i = 0; i < current.getNumChildren(); ++i) {
1184
128215
        processingStack.push_back(current[i]);
1185
      }
1186
    } else {
1187
108583
      children.push_back(current);
1188
    }
1189
  }
1190
30238
  return utils::mkSortedNode(kind, children);
1191
}
1192
1193
1194
template<> inline
1195
266571
bool RewriteRule<OrSimplify>::applies(TNode node) {
1196
266571
  return (node.getKind() == kind::BITVECTOR_OR);
1197
}
1198
1199
template <>
1200
133283
inline Node RewriteRule<OrSimplify>::apply(TNode node)
1201
{
1202
133283
  Debug("bv-rewrite") << "RewriteRule<OrSimplify>(" << node << ")" << std::endl;
1203
1204
133283
  NodeManager *nm = NodeManager::currentNM();
1205
  // this will remove duplicates
1206
266566
  std::unordered_map<TNode, Count> subterms;
1207
133283
  unsigned size = utils::getSize(node);
1208
266566
  BitVector constant(size, (unsigned)0);
1209
1210
680644
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1211
  {
1212
1094722
    TNode current = node[i];
1213
    // simplify constants
1214
547361
    if (current.getKind() == kind::CONST_BITVECTOR)
1215
    {
1216
280822
      BitVector bv = current.getConst<BitVector>();
1217
140411
      constant = constant | bv;
1218
    }
1219
    else
1220
    {
1221
406950
      if (current.getKind() == kind::BITVECTOR_NOT)
1222
      {
1223
21582
        insert(subterms, current[0], true);
1224
      }
1225
      else
1226
      {
1227
385368
        insert(subterms, current, false);
1228
      }
1229
    }
1230
  }
1231
1232
266566
  std::vector<Node> children;
1233
1234
133283
  if (constant == BitVector::mkOnes(size))
1235
  {
1236
7662
    return utils::mkOnes(size);
1237
  }
1238
1239
125621
  if (constant != BitVector(size, (unsigned)0))
1240
  {
1241
59784
    children.push_back(utils::mkConst(constant));
1242
  }
1243
1244
125621
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1245
1246
932535
  for (; it != subterms.end(); ++it)
1247
  {
1248
403588
    if (it->second.pos > 0 && it->second.neg > 0)
1249
    {
1250
      // if we have a or ~a
1251
131
      return utils::mkOnes(size);
1252
    }
1253
    else
1254
    {
1255
      // idempotence
1256
403457
      if (it->second.neg > 0)
1257
      {
1258
        // if it only occured negated
1259
21235
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1260
      }
1261
      else
1262
      {
1263
        // if it only occured positive
1264
382222
        children.push_back(it->first);
1265
      }
1266
    }
1267
  }
1268
1269
125490
  if (children.size() == 0)
1270
  {
1271
1045
    return utils::mkZero(size);
1272
  }
1273
124445
  return utils::mkSortedNode(kind::BITVECTOR_OR, children);
1274
}
1275
1276
template<> inline
1277
9120
bool RewriteRule<XorSimplify>::applies(TNode node) {
1278
9120
  return (node.getKind() == kind::BITVECTOR_XOR);
1279
}
1280
1281
template <>
1282
4560
inline Node RewriteRule<XorSimplify>::apply(TNode node)
1283
{
1284
9120
  Debug("bv-rewrite") << "RewriteRule<XorSimplify>(" << node << ")"
1285
4560
                      << std::endl;
1286
1287
4560
  NodeManager *nm = NodeManager::currentNM();
1288
9120
  std::unordered_map<TNode, Count> subterms;
1289
4560
  unsigned size = utils::getSize(node);
1290
9120
  BitVector constant;
1291
4560
  bool const_set = false;
1292
1293
13788
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1294
  {
1295
18456
    TNode current = node[i];
1296
    // simplify constants
1297
9228
    if (current.getKind() == kind::CONST_BITVECTOR)
1298
    {
1299
3438
      BitVector bv = current.getConst<BitVector>();
1300
1719
      if (const_set)
1301
      {
1302
393
        constant = constant ^ bv;
1303
      }
1304
      else
1305
      {
1306
1326
        const_set = true;
1307
1326
        constant = bv;
1308
      }
1309
    }
1310
    else
1311
    {
1312
      // collect number of occurances of each term and its negation
1313
7509
      if (current.getKind() == kind::BITVECTOR_NOT)
1314
      {
1315
374
        insert(subterms, current[0], true);
1316
      }
1317
      else
1318
      {
1319
7135
        insert(subterms, current, false);
1320
      }
1321
    }
1322
  }
1323
1324
9120
  std::vector<Node> children;
1325
1326
4560
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1327
4560
  unsigned true_count = 0;
1328
4560
  bool seen_false = false;
1329
19498
  for (; it != subterms.end(); ++it)
1330
  {
1331
7469
    unsigned pos = it->second.pos;  // number of positive occurances
1332
7469
    unsigned neg = it->second.neg;  // number of negated occurances
1333
1334
    // remove duplicates using the following rules
1335
    // a xor a ==> false
1336
    // false xor false ==> false
1337
7469
    seen_false = seen_false ? seen_false : (pos > 1 || neg > 1);
1338
    // check what did not reduce
1339
7469
    if (pos % 2 && neg % 2)
1340
    {
1341
      // we have a xor ~a ==> true
1342
3
      ++true_count;
1343
    }
1344
7466
    else if (pos % 2)
1345
    {
1346
      // we had a positive occurence left
1347
7058
      children.push_back(it->first);
1348
    }
1349
408
    else if (neg % 2)
1350
    {
1351
      // we had a negative occurence left
1352
371
      children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1353
    }
1354
    // otherwise both reduced to false
1355
  }
1356
1357
9120
  std::vector<BitVector> xorConst;
1358
9120
  BitVector true_bv = BitVector::mkOnes(size);
1359
9120
  BitVector false_bv(size, (unsigned)0);
1360
1361
4560
  if (true_count)
1362
  {
1363
    // true xor ... xor true ==> true (odd)
1364
    //                       ==> false (even)
1365
3
    xorConst.push_back(true_count % 2 ? true_bv : false_bv);
1366
  }
1367
4560
  if (seen_false)
1368
  {
1369
37
    xorConst.push_back(false_bv);
1370
  }
1371
4560
  if (const_set)
1372
  {
1373
1326
    xorConst.push_back(constant);
1374
  }
1375
1376
4560
  if (xorConst.size() > 0)
1377
  {
1378
2728
    BitVector result = xorConst[0];
1379
1366
    for (unsigned i = 1; i < xorConst.size(); ++i)
1380
    {
1381
2
      result = result ^ xorConst[i];
1382
    }
1383
1364
    children.push_back(utils::mkConst(result));
1384
  }
1385
1386
4560
  Assert(children.size());
1387
1388
9120
  return utils::mkSortedNode(kind::BITVECTOR_XOR, children);
1389
}
1390
1391
/**
1392
 * BitwiseSlicing
1393
 *
1394
 * (a bvand c) ==> (concat (bvand a[i0:j0] c0) ... (bvand a[in:jn] cn))
1395
 *  where c0,..., cn are maximally continuous substrings of 0 or 1 in the constant c
1396
 *
1397
 * Note: this rule assumes AndSimplify has already been called on the node
1398
 */
1399
template<> inline
1400
126408
bool RewriteRule<BitwiseSlicing>::applies(TNode node) {
1401
351749
  if ((node.getKind() != kind::BITVECTOR_AND &&
1402
162243
      node.getKind() != kind::BITVECTOR_OR &&
1403
452746
      node.getKind() != kind::BITVECTOR_XOR) ||
1404
263028
      utils::getSize(node) == 1)
1405
95212
    return false;
1406
  // find the first constant and return true if it's not only 1..1 or only 0..0
1407
  // (there could be more than one constant)
1408
95370
  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
1409
66418
    if (node[i].getKind() == kind::CONST_BITVECTOR) {
1410
4488
      BitVector constant = node[i].getConst<BitVector>();
1411
      // we do not apply the rule if the constant is all 0s or all 1s
1412
2244
      if (constant == BitVector(utils::getSize(node), 0u)) return false;
1413
1414
4515
      for (unsigned j = 0, csize = constant.getSize(); j < csize; ++j)
1415
      {
1416
4451
        if (!constant.isBitSet(j)) return true;
1417
      }
1418
64
      return false;
1419
    }
1420
  }
1421
28952
  return false;
1422
}
1423
1424
template <>
1425
1090
inline Node RewriteRule<BitwiseSlicing>::apply(TNode node)
1426
{
1427
2180
  Debug("bv-rewrite") << "RewriteRule<BitwiseSlicing>(" << node << ")"
1428
1090
                      << std::endl;
1429
1090
  NodeManager *nm = NodeManager::currentNM();
1430
  // get the constant
1431
1090
  bool found_constant = false;
1432
2180
  TNode constant;
1433
2180
  std::vector<Node> other_children;
1434
3318
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1435
  {
1436
2228
    if (node[i].getKind() == kind::CONST_BITVECTOR && !found_constant)
1437
    {
1438
1090
      constant = node[i];
1439
1090
      found_constant = true;
1440
    }
1441
    else
1442
    {
1443
1138
      other_children.push_back(node[i]);
1444
    }
1445
  }
1446
1090
  Assert(found_constant && other_children.size() == node.getNumChildren() - 1);
1447
1448
2180
  Node other = utils::mkNaryNode(node.getKind(), other_children);
1449
1450
2180
  BitVector bv_constant = constant.getConst<BitVector>();
1451
2180
  std::vector<Node> concat_children;
1452
1090
  int start = bv_constant.getSize() - 1;
1453
1090
  int end = start;
1454
22634
  for (int i = end - 1; i >= 0; --i)
1455
  {
1456
21544
    if (bv_constant.isBitSet(i + 1) != bv_constant.isBitSet(i))
1457
    {
1458
3846
      Node other_extract = utils::mkExtract(other, end, start);
1459
3846
      Node const_extract = utils::mkExtract(constant, end, start);
1460
      Node bitwise_op =
1461
3846
          nm->mkNode(node.getKind(), const_extract, other_extract);
1462
1923
      concat_children.push_back(bitwise_op);
1463
1923
      start = end = i;
1464
    }
1465
    else
1466
    {
1467
19621
      start--;
1468
    }
1469
21544
    if (i == 0)
1470
    {
1471
2180
      Node other_extract = utils::mkExtract(other, end, 0);
1472
2180
      Node const_extract = utils::mkExtract(constant, end, 0);
1473
      Node bitwise_op =
1474
2180
          nm->mkNode(node.getKind(), const_extract, other_extract);
1475
1090
      concat_children.push_back(bitwise_op);
1476
    }
1477
  }
1478
1090
  Node result = utils::mkConcat(concat_children);
1479
1090
  Debug("bv-rewrite") << "    =>" << result << std::endl;
1480
2180
  return result;
1481
}
1482
1483
template <>
1484
27
inline bool RewriteRule<NormalizeEqAddNeg>::applies(TNode node)
1485
{
1486
27
  return node.getKind() == kind::EQUAL
1487
89
         && (node[0].getKind() == kind::BITVECTOR_ADD
1488
60
             || node[1].getKind() == kind::BITVECTOR_ADD);
1489
}
1490
1491
template <>
1492
4
inline Node RewriteRule<NormalizeEqAddNeg>::apply(TNode node)
1493
{
1494
8
  Debug("bv-rewrite") << "RewriteRule<NormalizeEqAddNeg>(" << node << ")"
1495
4
                      << std::endl;
1496
1497
8
  NodeBuilder nb_lhs(kind::BITVECTOR_ADD);
1498
8
  NodeBuilder nb_rhs(kind::BITVECTOR_ADD);
1499
4
  NodeManager *nm = NodeManager::currentNM();
1500
1501
4
  if (node[0].getKind() == kind::BITVECTOR_ADD)
1502
  {
1503
12
    for (const TNode &n : node[0])
1504
    {
1505
8
      if (n.getKind() == kind::BITVECTOR_NEG)
1506
        nb_rhs << n[0];
1507
      else
1508
8
        nb_lhs << n;
1509
    }
1510
  }
1511
  else
1512
  {
1513
    nb_lhs << node[0];
1514
  }
1515
1516
4
  if (node[1].getKind() == kind::BITVECTOR_ADD)
1517
  {
1518
    for (const TNode &n : node[1])
1519
    {
1520
      if (n.getKind() == kind::BITVECTOR_NEG)
1521
        nb_lhs << n[0];
1522
      else
1523
        nb_rhs << n;
1524
    }
1525
  }
1526
  else
1527
  {
1528
4
    nb_rhs << node[1];
1529
  }
1530
1531
8
  Node zero = utils::mkZero(utils::getSize(node[0]));
1532
1533
8
  Node lhs, rhs;
1534
4
  if (nb_lhs.getNumChildren() == 0)
1535
  {
1536
    lhs = zero;
1537
  }
1538
4
  else if (nb_lhs.getNumChildren() == 1)
1539
  {
1540
    lhs = nb_lhs[0];
1541
  }
1542
  else
1543
  {
1544
4
    lhs = nb_lhs.constructNode();
1545
  }
1546
4
  if (nb_rhs.getNumChildren() == 0)
1547
  {
1548
    rhs = zero;
1549
  }
1550
4
  else if (nb_rhs.getNumChildren() == 1)
1551
  {
1552
4
    rhs = nb_rhs[0];
1553
  }
1554
  else
1555
  {
1556
    rhs = nb_rhs.constructNode();
1557
  }
1558
8
  return nm->mkNode(node.getKind(), lhs, rhs);
1559
}
1560
1561
// template<> inline
1562
// bool RewriteRule<>::applies(TNode node) {
1563
//   return (node.getKind() == kind::BITVECTOR_CONCAT);
1564
// }
1565
1566
// template<> inline
1567
// Node RewriteRule<>::apply(TNode node) {
1568
//   Debug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
1569
//   return resultNode;
1570
// }
1571
1572
1573
1574
}
1575
}
1576
}  // namespace cvc5