GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv_rewrite_rules_normalization.h Lines: 670 726 92.3 %
Date: 2021-05-22 Branches: 1392 2919 47.7 %

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
31
namespace cvc5 {
32
namespace theory {
33
namespace bv {
34
35
/**
36
 * ExtractBitwise
37
 *   (x bvop y) [i:j] ==> x[i:j] bvop y[i:j]
38
 *  where bvop is bvand,bvor, bvxor
39
 */
40
template<> inline
41
bool RewriteRule<ExtractBitwise>::applies(TNode node) {
42
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
43
          (node[0].getKind() == kind::BITVECTOR_AND ||
44
           node[0].getKind() == kind::BITVECTOR_OR ||
45
           node[0].getKind() == kind::BITVECTOR_XOR ));
46
}
47
48
template<> inline
49
Node RewriteRule<ExtractBitwise>::apply(TNode node) {
50
  Debug("bv-rewrite") << "RewriteRule<ExtractBitwise>(" << node << ")" << std::endl;
51
  unsigned high = utils::getExtractHigh(node);
52
  unsigned low = utils::getExtractLow(node);
53
  std::vector<Node> children;
54
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i) {
55
    children.push_back(utils::mkExtract(node[0][i], high, low));
56
  }
57
  Kind kind = node[0].getKind();
58
  return utils::mkSortedNode(kind, children);
59
}
60
61
/**
62
 * ExtractNot
63
 *
64
 *  (~ a) [i:j] ==> ~ (a[i:j])
65
 */
66
template<> inline
67
143267
bool RewriteRule<ExtractNot>::applies(TNode node) {
68
429801
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
69
429801
          node[0].getKind() == kind::BITVECTOR_NOT);
70
}
71
72
template <>
73
1766
inline Node RewriteRule<ExtractNot>::apply(TNode node)
74
{
75
1766
  Debug("bv-rewrite") << "RewriteRule<ExtractNot>(" << node << ")" << std::endl;
76
1766
  unsigned low = utils::getExtractLow(node);
77
1766
  unsigned high = utils::getExtractHigh(node);
78
3532
  Node a = utils::mkExtract(node[0][0], high, low);
79
3532
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_NOT, a);
80
}
81
82
/**
83
 * ExtractSignExtend
84
 *
85
 * (sign_extend k x) [i:j] => pushes extract in
86
 *
87
 * @return
88
 */
89
90
template<> inline
91
142825
bool RewriteRule<ExtractSignExtend>::applies(TNode node) {
92
571300
  if (node.getKind() == kind::BITVECTOR_EXTRACT &&
93
428475
      node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND) {
94
1324
    return true;
95
  }
96
141501
  return false;
97
}
98
99
template <>
100
662
inline Node RewriteRule<ExtractSignExtend>::apply(TNode node)
101
{
102
1324
  Debug("bv-rewrite") << "RewriteRule<ExtractSignExtend>(" << node << ")"
103
662
                      << std::endl;
104
1324
  TNode extendee = node[0][0];
105
662
  unsigned extendee_size = utils::getSize(extendee);
106
107
662
  unsigned high = utils::getExtractHigh(node);
108
662
  unsigned low = utils::getExtractLow(node);
109
110
662
  Node resultNode;
111
  // extract falls on extendee
112
662
  if (high < extendee_size)
113
  {
114
241
    resultNode = utils::mkExtract(extendee, high, low);
115
  }
116
421
  else if (low < extendee_size && high >= extendee_size)
117
  {
118
    // if extract overlaps sign extend and extendee
119
156
    Node low_extract = utils::mkExtract(extendee, extendee_size - 1, low);
120
78
    unsigned new_amount = high - extendee_size + 1;
121
156
    resultNode = utils::mkSignExtend(low_extract, new_amount);
122
  }
123
  else
124
  {
125
    // extract only over sign extend
126
343
    Assert(low >= extendee_size);
127
343
    unsigned top = utils::getSize(extendee) - 1;
128
686
    Node most_significant_bit = utils::mkExtract(extendee, top, top);
129
686
    std::vector<Node> bits;
130
930
    for (unsigned i = 0; i < high - low + 1; ++i)
131
    {
132
587
      bits.push_back(most_significant_bit);
133
    }
134
343
    resultNode = utils::mkConcat(bits);
135
  }
136
1324
  Debug("bv-rewrite") << "                           =>" << resultNode
137
662
                      << std::endl;
138
1324
  return resultNode;
139
}
140
141
/**
142
 * ExtractArith
143
 *
144
 * (a bvop b) [k:0] ==> (a[k:0] bvop b[k:0])
145
 */
146
147
template<> inline
148
bool RewriteRule<ExtractArith>::applies(TNode node) {
149
  return (node.getKind() == kind::BITVECTOR_EXTRACT
150
          && utils::getExtractLow(node) == 0
151
          && (node[0].getKind() == kind::BITVECTOR_ADD
152
              || node[0].getKind() == kind::BITVECTOR_MULT));
153
}
154
155
template <>
156
inline Node RewriteRule<ExtractArith>::apply(TNode node)
157
{
158
  Debug("bv-rewrite") << "RewriteRule<ExtractArith>(" << node << ")"
159
                      << std::endl;
160
  unsigned low = utils::getExtractLow(node);
161
  Assert(low == 0);
162
  unsigned high = utils::getExtractHigh(node);
163
  std::vector<Node> children;
164
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
165
  {
166
    children.push_back(utils::mkExtract(node[0][i], high, low));
167
  }
168
  Kind kind = node[0].getKind();
169
  return utils::mkNaryNode(kind, children);
170
}
171
172
/**
173
 * ExtractArith2
174
 *
175
 * (a bvop b) [i:j] ==> (a[i:0] bvop b[i:0]) [i:j]
176
 */
177
178
// careful not to apply in a loop
179
template<> inline
180
bool RewriteRule<ExtractArith2>::applies(TNode node) {
181
  return (node.getKind() == kind::BITVECTOR_EXTRACT
182
          && (node[0].getKind() == kind::BITVECTOR_ADD
183
              || node[0].getKind() == kind::BITVECTOR_MULT));
184
}
185
186
template <>
187
inline Node RewriteRule<ExtractArith2>::apply(TNode node)
188
{
189
  Debug("bv-rewrite") << "RewriteRule<ExtractArith2>(" << node << ")"
190
                      << std::endl;
191
  unsigned low = utils::getExtractLow(node);
192
  unsigned high = utils::getExtractHigh(node);
193
  std::vector<Node> children;
194
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
195
  {
196
    children.push_back(utils::mkExtract(node[0][i], high, 0));
197
  }
198
  Kind kind = node[0].getKind();
199
  Node op_children = utils::mkNaryNode(kind, children);
200
201
  return utils::mkExtract(op_children, high, low);
202
}
203
204
template<> inline
205
417475
bool RewriteRule<FlattenAssocCommut>::applies(TNode node) {
206
417475
  Kind kind = node.getKind();
207
417475
  if (kind != kind::BITVECTOR_ADD && kind != kind::BITVECTOR_MULT
208
11262
      && kind != kind::BITVECTOR_OR && kind != kind::BITVECTOR_XOR
209
      && kind != kind::BITVECTOR_AND)
210
    return false;
211
417475
  TNode::iterator child_it = node.begin();
212
2876755
  for(; child_it != node.end(); ++child_it) {
213
1282468
    if ((*child_it).getKind() == kind) {
214
52828
      return true;
215
    }
216
  }
217
364647
  return false;
218
}
219
220
template <>
221
26418
inline Node RewriteRule<FlattenAssocCommut>::apply(TNode node)
222
{
223
52836
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")"
224
26418
                      << std::endl;
225
52836
  std::vector<Node> processingStack;
226
26418
  processingStack.push_back(node);
227
52836
  std::vector<Node> children;
228
26418
  Kind kind = node.getKind();
229
230
454098
  while (!processingStack.empty())
231
  {
232
427680
    TNode current = processingStack.back();
233
213840
    processingStack.pop_back();
234
235
    // flatten expression
236
213840
    if (current.getKind() == kind)
237
    {
238
249102
      for (unsigned i = 0; i < current.getNumChildren(); ++i)
239
      {
240
187422
        processingStack.push_back(current[i]);
241
      }
242
    }
243
    else
244
    {
245
152160
      children.push_back(current);
246
    }
247
  }
248
52836
  if (node.getKind() == kind::BITVECTOR_ADD
249
26418
      || node.getKind() == kind::BITVECTOR_MULT)
250
  {
251
26337
    return utils::mkNaryNode(kind, children);
252
  }
253
  else
254
  {
255
81
    return utils::mkSortedNode(kind, children);
256
  }
257
}
258
259
662184
static inline void addToCoefMap(std::map<Node, BitVector>& map,
260
                                TNode term, const BitVector& coef) {
261
662184
  if (map.find(term) != map.end()) {
262
436
    map[term] = map[term] + coef;
263
  } else {
264
661748
    map[term] = coef;
265
  }
266
662184
}
267
268
269
833703
static inline void updateCoefMap(TNode current, unsigned size,
270
                                 std::map<Node, BitVector>& factorToCoefficient,
271
                                 BitVector& constSum) {
272
833703
  switch (current.getKind()) {
273
292752
    case kind::BITVECTOR_MULT: {
274
      // look for c * term, where c is a constant
275
585504
      BitVector coeff;
276
585504
      Node term;
277
292752
      if (current.getNumChildren() == 2) {
278
        // Mult should be normalized with only one constant at end
279
59529
        Assert(!current[0].isConst());
280
59529
        if (current[1].isConst()) {
281
44786
          coeff = current[1].getConst<BitVector>();
282
44786
          term = current[0];
283
        }
284
      }
285
233223
      else if (current[current.getNumChildren()-1].isConst()) {
286
446328
        NodeBuilder nb(kind::BITVECTOR_MULT);
287
223164
        TNode::iterator child_it = current.begin();
288
1491372
        for(; (child_it+1) != current.end(); ++child_it) {
289
634104
          Assert(!(*child_it).isConst());
290
634104
          nb << (*child_it);
291
        }
292
223164
        term = nb;
293
223164
        coeff = (*child_it).getConst<BitVector>();
294
      }
295
292752
      if (term.isNull()) {
296
24802
        coeff = BitVector(size, (unsigned)1);
297
24802
        term = current;
298
      }
299
292752
      if(term.getKind() == kind::BITVECTOR_SUB) {
300
        TNode a = term[0];
301
        TNode b = term[1];
302
        addToCoefMap(factorToCoefficient, a, coeff);
303
        addToCoefMap(factorToCoefficient, b, -coeff);
304
      }
305
292752
      else if(term.getKind() == kind::BITVECTOR_NEG) {
306
        addToCoefMap(factorToCoefficient, term[0], -BitVector(size, coeff));
307
      }
308
      else {
309
292752
        addToCoefMap(factorToCoefficient, term, coeff);
310
      }
311
292752
      break;
312
    }
313
    case kind::BITVECTOR_SUB:
314
      // turn into a + (-1)*b
315
      Assert(current.getNumChildren() == 2);
316
      addToCoefMap(factorToCoefficient, current[0], BitVector(size, (unsigned)1));
317
      addToCoefMap(factorToCoefficient, current[1], -BitVector(size, (unsigned)1));
318
      break;
319
73890
    case kind::BITVECTOR_NEG:
320
73890
      addToCoefMap(factorToCoefficient, current[0], -BitVector(size, (unsigned)1));
321
73890
      break;
322
171519
    case kind::CONST_BITVECTOR: {
323
343038
      BitVector constValue = current.getConst<BitVector>();
324
171519
      constSum = constSum + constValue;
325
171519
      break;
326
    }
327
295542
    default:
328
      // store as 1 * current
329
295542
      addToCoefMap(factorToCoefficient, current, BitVector(size, (unsigned)1));
330
295542
      break;
331
  }
332
833703
}
333
334
658544
static inline void addToChildren(TNode term,
335
                                 unsigned size,
336
                                 BitVector coeff,
337
                                 std::vector<Node> &children)
338
{
339
658544
  NodeManager *nm = NodeManager::currentNM();
340
658544
  if (coeff == BitVector(size, (unsigned)0))
341
  {
342
83
    return;
343
  }
344
658461
  else if (coeff == BitVector(size, (unsigned)1))
345
  {
346
317877
    children.push_back(term);
347
  }
348
340584
  else if (coeff == -BitVector(size, (unsigned)1))
349
  {
350
    // avoid introducing an extra multiplication
351
72359
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, term));
352
  }
353
268225
  else if (term.getKind() == kind::BITVECTOR_MULT)
354
  {
355
446320
    NodeBuilder nb(kind::BITVECTOR_MULT);
356
223160
    TNode::iterator child_it = term.begin();
357
1491332
    for (; child_it != term.end(); ++child_it)
358
    {
359
634086
      nb << *child_it;
360
    }
361
223160
    nb << utils::mkConst(coeff);
362
223160
    children.push_back(Node(nb));
363
  }
364
  else
365
  {
366
90130
    Node coeffNode = utils::mkConst(coeff);
367
90130
    Node product = nm->mkNode(kind::BITVECTOR_MULT, term, coeffNode);
368
45065
    children.push_back(product);
369
  }
370
}
371
372
template <>
373
166716
inline bool RewriteRule<AddCombineLikeTerms>::applies(TNode node)
374
{
375
166716
  return (node.getKind() == kind::BITVECTOR_ADD);
376
}
377
378
template <>
379
83358
inline Node RewriteRule<AddCombineLikeTerms>::apply(TNode node)
380
{
381
166716
  Debug("bv-rewrite") << "RewriteRule<AddCombineLikeTerms>(" << node << ")"
382
83358
                      << std::endl;
383
83358
  unsigned size = utils::getSize(node);
384
166716
  BitVector constSum(size, (unsigned)0);
385
166716
  std::map<Node, BitVector> factorToCoefficient;
386
387
  // combine like-terms
388
531772
  for (size_t i = 0, n = node.getNumChildren(); i < n; ++i)
389
  {
390
896828
    TNode current = node[i];
391
448414
    updateCoefMap(current, size, factorToCoefficient, constSum);
392
  }
393
394
166716
  std::vector<Node> children;
395
396
  // construct result
397
83358
  std::map<Node, BitVector>::const_iterator it = factorToCoefficient.begin();
398
399
797688
  for (; it != factorToCoefficient.end(); ++it)
400
  {
401
357165
    addToChildren(it->first, size, it->second, children);
402
  }
403
404
83358
  if (constSum != BitVector(size, (unsigned)0))
405
  {
406
53594
    children.push_back(utils::mkConst(constSum));
407
  }
408
409
83358
  size_t csize = children.size();
410
83358
  if (csize == node.getNumChildren())
411
  {
412
    // If we couldn't combine any terms, we don't perform the rewrite. This is
413
    // important because we are otherwise reordering terms in the addition
414
    // based on the node ids of the terms that are multiplied with the
415
    // coefficients. Due to garbage collection we may see different id orders
416
    // for those nodes even when we perform one rewrite directly after the
417
    // other, so the rewrite wouldn't be idempotent.
418
47717
    return node;
419
  }
420
421
  return csize == 0 ? utils::mkZero(size)
422
35641
                    : utils::mkNaryNode(kind::BITVECTOR_ADD, children);
423
}
424
425
template<> inline
426
470792
bool RewriteRule<MultSimplify>::applies(TNode node) {
427
470792
  return node.getKind() == kind::BITVECTOR_MULT;
428
}
429
430
template <>
431
235396
inline Node RewriteRule<MultSimplify>::apply(TNode node)
432
{
433
470792
  Debug("bv-rewrite") << "RewriteRule<MultSimplify>(" << node << ")"
434
235396
                      << std::endl;
435
235396
  NodeManager *nm = NodeManager::currentNM();
436
235396
  unsigned size = utils::getSize(node);
437
470792
  BitVector constant(size, Integer(1));
438
439
235396
  bool isNeg = false;
440
470792
  std::vector<Node> children;
441
881992
  for (const TNode &current : node)
442
  {
443
1302708
    Node c = current;
444
656112
    if (c.getKind() == kind::BITVECTOR_NEG)
445
    {
446
1370
      isNeg = !isNeg;
447
1370
      c = c[0];
448
    }
449
450
656112
    if (c.getKind() == kind::CONST_BITVECTOR)
451
    {
452
460032
      BitVector value = c.getConst<BitVector>();
453
234774
      constant = constant * value;
454
234774
      if (constant == BitVector(size, (unsigned)0))
455
      {
456
9516
        return utils::mkConst(size, 0);
457
      }
458
    }
459
    else
460
    {
461
421338
      children.push_back(c);
462
    }
463
  }
464
451760
  BitVector oValue = BitVector(size, static_cast<unsigned>(1));
465
451760
  BitVector noValue = BitVector::mkOnes(size);
466
467
225880
  if (children.empty())
468
  {
469
20615
    return utils::mkConst(isNeg ? -constant : constant);
470
  }
471
472
205265
  std::sort(children.begin(), children.end());
473
474
205265
  if (constant == noValue)
475
  {
476
1874
    isNeg = !isNeg;
477
  }
478
203391
  else if (constant != oValue)
479
  {
480
174447
    if (isNeg)
481
    {
482
1172
      isNeg = !isNeg;
483
1172
      constant = -constant;
484
    }
485
174447
    children.push_back(utils::mkConst(constant));
486
  }
487
488
410530
  Node ret = utils::mkNaryNode(kind::BITVECTOR_MULT, children);
489
490
  // if negative, negate entire node
491
205265
  if (isNeg && size > 1)
492
  {
493
832
    ret = nm->mkNode(kind::BITVECTOR_NEG, ret);
494
  }
495
205265
  return ret;
496
}
497
498
template<> inline
499
90726
bool RewriteRule<MultDistribConst>::applies(TNode node) {
500
160434
  if (node.getKind() != kind::BITVECTOR_MULT ||
501
69708
      node.getNumChildren() != 2) {
502
63945
    return false;
503
  }
504
26781
  Assert(!node[0].isConst());
505
26781
  if (!node[1].isConst()) {
506
12061
    return false;
507
  }
508
29440
  TNode factor = node[0];
509
14720
  return (factor.getKind() == kind::BITVECTOR_ADD
510
12556
          || factor.getKind() == kind::BITVECTOR_SUB
511
27276
          || factor.getKind() == kind::BITVECTOR_NEG);
512
}
513
514
template <>
515
1082
inline Node RewriteRule<MultDistribConst>::apply(TNode node)
516
{
517
2164
  Debug("bv-rewrite") << "RewriteRule<MultDistribConst>(" << node << ")"
518
1082
                      << std::endl;
519
520
1082
  NodeManager *nm = NodeManager::currentNM();
521
2164
  TNode constant = node[1];
522
2164
  TNode factor = node[0];
523
1082
  Assert(constant.getKind() == kind::CONST_BITVECTOR);
524
525
1082
  if (factor.getKind() == kind::BITVECTOR_NEG)
526
  {
527
    // push negation on the constant part
528
    BitVector const_bv = constant.getConst<BitVector>();
529
    return nm->mkNode(
530
        kind::BITVECTOR_MULT, factor[0], utils::mkConst(-const_bv));
531
  }
532
533
2164
  std::vector<Node> children;
534
11332
  for (unsigned i = 0; i < factor.getNumChildren(); ++i)
535
  {
536
10250
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, factor[i], constant));
537
  }
538
539
1082
  return utils::mkNaryNode(factor.getKind(), children);
540
}
541
542
template<> inline
543
90039
bool RewriteRule<MultDistrib>::applies(TNode node) {
544
157978
  if (node.getKind() != kind::BITVECTOR_MULT ||
545
67939
      node.getNumChildren() != 2) {
546
65027
    return false;
547
  }
548
75036
  if (node[0].getKind() == kind::BITVECTOR_ADD
549
75036
      || node[0].getKind() == kind::BITVECTOR_SUB)
550
  {
551
222
    return node[1].getKind() != kind::BITVECTOR_ADD
552
222
           && node[1].getKind() != kind::BITVECTOR_SUB;
553
  }
554
74814
  return node[1].getKind() == kind::BITVECTOR_ADD
555
74814
         || node[1].getKind() == kind::BITVECTOR_SUB;
556
}
557
558
template <>
559
395
inline Node RewriteRule<MultDistrib>::apply(TNode node)
560
{
561
790
  Debug("bv-rewrite") << "RewriteRule<MultDistrib>(" << node << ")"
562
395
                      << std::endl;
563
564
395
  NodeManager *nm = NodeManager::currentNM();
565
1185
  bool is_rhs_factor = node[0].getKind() == kind::BITVECTOR_ADD
566
1185
                       || node[0].getKind() == kind::BITVECTOR_SUB;
567
790
  TNode factor = !is_rhs_factor ? node[0] : node[1];
568
790
  TNode sum = is_rhs_factor ? node[0] : node[1];
569
395
  Assert(factor.getKind() != kind::BITVECTOR_ADD
570
         && factor.getKind() != kind::BITVECTOR_SUB
571
         && (sum.getKind() == kind::BITVECTOR_ADD
572
             || sum.getKind() == kind::BITVECTOR_SUB));
573
574
790
  std::vector<Node> children;
575
21021
  for (unsigned i = 0; i < sum.getNumChildren(); ++i)
576
  {
577
20626
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, sum[i], factor));
578
  }
579
580
790
  return utils::mkNaryNode(sum.getKind(), children);
581
}
582
583
template<> inline
584
1238
bool RewriteRule<ConcatToMult>::applies(TNode node) {
585
1238
  if (node.getKind() != kind::BITVECTOR_CONCAT) return false;
586
326
  if (node.getNumChildren() != 2) return false;
587
238
  if (node[0].getKind()!= kind::BITVECTOR_EXTRACT) return false;
588
28
  if (!node[1].isConst()) return false;
589
32
  TNode extract = node[0];
590
32
  TNode c = node[1];
591
16
  unsigned amount = utils::getSize(c);
592
593
16
  if (utils::getSize(node) != utils::getSize(extract[0])) return false;
594
16
  if (c != utils::mkZero(amount)) return false;
595
596
16
  unsigned low = utils::getExtractLow(extract);
597
16
  if (low != 0) return false;
598
16
  unsigned high = utils::getExtractHigh(extract);
599
16
  if (high + amount + 1 != utils::getSize(node)) return false;
600
16
  return true;
601
}
602
603
template <>
604
4
inline Node RewriteRule<ConcatToMult>::apply(TNode node)
605
{
606
8
  Debug("bv-rewrite") << "RewriteRule<ConcatToMult>(" << node << ")"
607
4
                      << std::endl;
608
4
  unsigned size = utils::getSize(node);
609
8
  Node factor = node[0][0];
610
4
  Assert(utils::getSize(factor) == utils::getSize(node));
611
8
  BitVector amount = BitVector(size, utils::getSize(node[1]));
612
8
  Node coef = utils::mkConst(BitVector(size, 1u).leftShift(amount));
613
8
  return NodeManager::currentNM()->mkNode(kind::BITVECTOR_MULT, factor, coef);
614
}
615
616
template <>
617
422981
inline bool RewriteRule<SolveEq>::applies(TNode node)
618
{
619
845962
  if (node.getKind() != kind::EQUAL
620
803827
      || (node[0].isVar() && !expr::hasSubterm(node[1], node[0]))
621
1169060
      || (node[1].isVar() && !expr::hasSubterm(node[0], node[1])))
622
  {
623
126985
    return false;
624
  }
625
295996
  return true;
626
}
627
628
// Doesn't do full solving (yet), instead, if a term appears both on lhs and
629
// rhs, it subtracts from both sides so that one side's coeff is zero
630
template <>
631
148000
inline Node RewriteRule<SolveEq>::apply(TNode node)
632
{
633
148000
  Debug("bv-rewrite") << "RewriteRule<SolveEq>(" << node << ")" << std::endl;
634
635
296000
  TNode left = node[0];
636
296000
  TNode right = node[1];
637
638
148000
  unsigned size = utils::getSize(left);
639
296000
  BitVector zero(size, (unsigned)0);
640
296000
  BitVector leftConst(size, (unsigned)0);
641
296000
  BitVector rightConst(size, (unsigned)0);
642
296000
  std::map<Node, BitVector> leftMap, rightMap;
643
644
  // Collect terms and coefficients plus constant for left
645
148000
  if (left.getKind() == kind::BITVECTOR_ADD)
646
  {
647
82618
    for (unsigned i = 0; i < left.getNumChildren(); ++i)
648
    {
649
70227
      updateCoefMap(left[i], size, leftMap, leftConst);
650
    }
651
  }
652
135609
  else if (left.getKind() == kind::BITVECTOR_NOT && left[0] == right)
653
  {
654
41
    return utils::mkFalse();
655
  }
656
  else
657
  {
658
135568
    updateCoefMap(left, size, leftMap, leftConst);
659
  }
660
661
  // Collect terms and coefficients plus constant for right
662
147959
  if (right.getKind() == kind::BITVECTOR_ADD)
663
  {
664
49099
    for (unsigned i = 0; i < right.getNumChildren(); ++i)
665
    {
666
40317
      updateCoefMap(right[i], size, rightMap, rightConst);
667
    }
668
  }
669
139177
  else if (right.getKind() == kind::BITVECTOR_NOT && right[0] == left)
670
  {
671
    return utils::mkFalse();
672
  }
673
  else
674
  {
675
139177
    updateCoefMap(right, size, rightMap, rightConst);
676
  }
677
678
295918
  std::vector<Node> childrenLeft, childrenRight;
679
680
147959
  std::map<Node, BitVector>::const_iterator iLeft = leftMap.begin(),
681
147959
                                            iLeftEnd = leftMap.end();
682
147959
  std::map<Node, BitVector>::const_iterator iRight = rightMap.begin(),
683
147959
                                            iRightEnd = rightMap.end();
684
685
295918
  BitVector coeffLeft;
686
295918
  TNode termLeft;
687
147959
  if (iLeft != iLeftEnd)
688
  {
689
144496
    coeffLeft = iLeft->second;
690
144496
    termLeft = iLeft->first;
691
  }
692
693
295918
  BitVector coeffRight;
694
295918
  TNode termRight;
695
147959
  if (iRight != iRightEnd)
696
  {
697
87525
    coeffRight = iRight->second;
698
87525
    termRight = iRight->first;
699
  }
700
701
  // Changed tracks whether there have been any changes to the coefficients or
702
  // constants of the left- or right-hand side. We perform a rewrite only if
703
  // that is the case. This is important because we are otherwise reordering
704
  // terms in the addition based on the node ids of the terms that are
705
  // multiplied with the coefficients. Due to garbage collection we may see
706
  // different id orders for those nodes even when we perform one rewrite
707
  // directly after the other, so the rewrite wouldn't be idempotent.
708
147959
  bool changed = false;
709
  bool incLeft, incRight;
710
711
753849
  while (iLeft != iLeftEnd || iRight != iRightEnd)
712
  {
713
302945
    incLeft = incRight = false;
714
302945
    if (iLeft != iLeftEnd && (iRight == iRightEnd || termLeft < termRight))
715
    {
716
190861
      addToChildren(termLeft, size, coeffLeft, childrenLeft);
717
190861
      incLeft = true;
718
    }
719
112084
    else if (iLeft == iLeftEnd || termRight < termLeft)
720
    {
721
110446
      Assert(iRight != iRightEnd);
722
110446
      addToChildren(termRight, size, coeffRight, childrenRight);
723
110446
      incRight = true;
724
    }
725
    else
726
    {
727
1638
      if (coeffLeft > coeffRight)
728
      {
729
68
        addToChildren(termLeft, size, coeffLeft - coeffRight, childrenLeft);
730
      }
731
1570
      else if (coeffRight > coeffLeft)
732
      {
733
4
        addToChildren(termRight, size, coeffRight - coeffLeft, childrenRight);
734
      }
735
1638
      incLeft = incRight = true;
736
1638
      changed = true;
737
    }
738
302945
    if (incLeft)
739
    {
740
192499
      ++iLeft;
741
192499
      if (iLeft != iLeftEnd)
742
      {
743
48003
        Assert(termLeft < iLeft->first);
744
48003
        coeffLeft = iLeft->second;
745
48003
        termLeft = iLeft->first;
746
      }
747
    }
748
302945
    if (incRight)
749
    {
750
112084
      ++iRight;
751
112084
      if (iRight != iRightEnd)
752
      {
753
24559
        Assert(termRight < iRight->first);
754
24559
        coeffRight = iRight->second;
755
24559
        termRight = iRight->first;
756
      }
757
    }
758
  }
759
760
  // construct result
761
762
  // If both constants are nonzero, combine on right, otherwise leave them where
763
  // they are
764
147959
  if (rightConst != zero)
765
  {
766
48645
    changed |= (leftConst != zero);
767
48645
    rightConst = rightConst - leftConst;
768
48645
    leftConst = zero;
769
48645
    if (rightConst != zero)
770
    {
771
47574
      childrenRight.push_back(utils::mkConst(rightConst));
772
    }
773
  }
774
99314
  else if (leftConst != zero)
775
  {
776
8759
    childrenLeft.push_back(utils::mkConst(leftConst));
777
  }
778
779
295918
  Node newLeft, newRight;
780
781
147959
  if (childrenRight.size() == 0 && leftConst != zero)
782
  {
783
461
    Assert(childrenLeft.back().isConst()
784
           && childrenLeft.back().getConst<BitVector>() == leftConst);
785
461
    if (childrenLeft.size() == 1)
786
    {
787
      // c = 0 ==> false
788
241
      return utils::mkFalse();
789
    }
790
    // special case - if right is empty and left has a constant, move the
791
    // constant
792
220
    childrenRight.push_back(utils::mkConst(-leftConst));
793
220
    childrenLeft.pop_back();
794
220
    changed = true;
795
  }
796
797
147718
  if (childrenLeft.size() == 0)
798
  {
799
2300
    if (rightConst != zero)
800
    {
801
1776
      Assert(childrenRight.back().isConst()
802
             && childrenRight.back().getConst<BitVector>() == rightConst);
803
1776
      if (childrenRight.size() == 1)
804
      {
805
        // 0 = c ==> false
806
1283
        return utils::mkFalse();
807
      }
808
      // special case - if left is empty and right has a constant, move the
809
      // constant
810
493
      newLeft = utils::mkConst(-rightConst);
811
493
      childrenRight.pop_back();
812
493
      changed = true;
813
    }
814
    else
815
    {
816
524
      newLeft = utils::mkConst(size, (unsigned)0);
817
    }
818
  }
819
  else
820
  {
821
145418
    newLeft = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenLeft);
822
  }
823
824
146435
  if (childrenRight.size() == 0)
825
  {
826
18770
    newRight = utils::mkConst(size, (unsigned)0);
827
  }
828
  else
829
  {
830
127665
    newRight = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenRight);
831
  }
832
833
146435
  if (!changed)
834
  {
835
143379
    return node;
836
  }
837
838
3056
  if (newLeft == newRight)
839
  {
840
4
    Assert(newLeft == utils::mkConst(size, (unsigned)0));
841
4
    return utils::mkTrue();
842
  }
843
844
3052
  if (newLeft < newRight)
845
  {
846
890
    Assert((newRight == left && newLeft == right)
847
           || Rewriter::rewrite(newRight) != left
848
           || Rewriter::rewrite(newLeft) != right);
849
890
    return newRight.eqNode(newLeft);
850
  }
851
852
2162
  Assert((newLeft == left && newRight == right)
853
         || Rewriter::rewrite(newLeft) != left
854
         || Rewriter::rewrite(newRight) != right);
855
2162
  return newLeft.eqNode(newRight);
856
}
857
858
template<> inline
859
316104
bool RewriteRule<BitwiseEq>::applies(TNode node) {
860
668844
  if (node.getKind() != kind::EQUAL ||
861
352740
      utils::getSize(node[0]) != 1) {
862
312178
    return false;
863
  }
864
7852
  TNode term;
865
7852
  BitVector c;
866
3926
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
867
172
    c = node[0].getConst<BitVector>();
868
172
    term = node[1];
869
  }
870
3754
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
871
2316
    c = node[1].getConst<BitVector>();
872
2316
    term = node[0];
873
  }
874
  else {
875
1438
    return false;
876
  }
877
2488
  switch (term.getKind()) {
878
840
    case kind::BITVECTOR_AND:
879
    case kind::BITVECTOR_OR:
880
      //operator BITVECTOR_XOR 2: "bitwise xor"
881
    case kind::BITVECTOR_NOT:
882
    case kind::BITVECTOR_NAND:
883
    case kind::BITVECTOR_NOR:
884
      //operator BITVECTOR_XNOR 2 "bitwise xnor"
885
    case kind::BITVECTOR_COMP:
886
    case kind::BITVECTOR_NEG:
887
840
      return true;
888
      break;
889
1648
    default:
890
1648
      break;
891
  }
892
1648
  return false;
893
}
894
895
896
115
static inline Node mkNodeKind(Kind k, TNode node, TNode c) {
897
115
  unsigned i = 0;
898
115
  unsigned nc = node.getNumChildren();
899
230
  NodeBuilder nb(k);
900
1183
  for(; i < nc; ++i) {
901
534
    nb << node[i].eqNode(c);
902
  }
903
230
  return nb;
904
}
905
906
907
template<> inline
908
420
Node RewriteRule<BitwiseEq>::apply(TNode node) {
909
420
  Debug("bv-rewrite") << "RewriteRule<BitwiseEq>(" << node << ")" << std::endl;
910
911
840
  TNode term;
912
840
  BitVector c;
913
914
420
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
915
4
    c = node[0].getConst<BitVector>();
916
4
    term = node[1];
917
  }
918
416
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
919
416
    c = node[1].getConst<BitVector>();
920
416
    term = node[0];
921
  }
922
923
420
  bool eqOne = (c == BitVector(1,(unsigned)1));
924
925
420
  switch (term.getKind()) {
926
47
    case kind::BITVECTOR_AND:
927
47
      if (eqOne) {
928
17
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
929
      }
930
      else {
931
30
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
932
      }
933
      break;
934
    case kind::BITVECTOR_NAND:
935
      if (eqOne) {
936
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
937
      }
938
      else {
939
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
940
      }
941
      break;
942
68
    case kind::BITVECTOR_OR:
943
68
      if (eqOne) {
944
60
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
945
      }
946
      else {
947
8
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
948
      }
949
      break;
950
    case kind::BITVECTOR_NOR:
951
      if (eqOne) {
952
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
953
      }
954
      else {
955
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
956
      }
957
      break;
958
141
    case kind::BITVECTOR_NOT:
959
141
      return term[0].eqNode(utils::mkConst(~c));
960
144
    case kind::BITVECTOR_COMP:
961
144
      Assert(term.getNumChildren() == 2);
962
144
      if (eqOne) {
963
132
        return term[0].eqNode(term[1]);
964
      }
965
      else {
966
12
        return term[0].eqNode(term[1]).notNode();
967
      }
968
20
    case kind::BITVECTOR_NEG:
969
20
      return term[0].eqNode(utils::mkConst(c));
970
    default:
971
      break;
972
  }
973
  Unreachable();
974
}
975
976
977
/**
978
 * -(c * expr) ==> (-c * expr)
979
 * where c is a constant
980
 */
981
template<> inline
982
15927
bool RewriteRule<NegMult>::applies(TNode node) {
983
63708
  if(node.getKind()!= kind::BITVECTOR_NEG ||
984
47781
     node[0].getKind() != kind::BITVECTOR_MULT) {
985
14947
    return false;
986
  }
987
980
  return node[node.getNumChildren()-1].isConst();
988
}
989
990
template<> inline
991
Node RewriteRule<NegMult>::apply(TNode node) {
992
  Debug("bv-rewrite") << "RewriteRule<NegMult>(" << node << ")" << std::endl;
993
  TNode mult = node[0];
994
  NodeBuilder nb(kind::BITVECTOR_MULT);
995
  BitVector bv(utils::getSize(node), (unsigned)1);
996
  TNode::iterator child_it = mult.begin();
997
  for(; (child_it+1) != mult.end(); ++child_it) {
998
    nb << (*child_it);
999
  }
1000
  Assert((*child_it).isConst());
1001
  bv = (*child_it).getConst<BitVector>();
1002
  nb << utils::mkConst(-bv);
1003
  return Node(nb);
1004
}
1005
1006
template<> inline
1007
30513
bool RewriteRule<NegSub>::applies(TNode node) {
1008
78097
  return (node.getKind() == kind::BITVECTOR_NEG &&
1009
78097
          node[0].getKind() == kind::BITVECTOR_SUB);
1010
}
1011
1012
template <>
1013
191
inline Node RewriteRule<NegSub>::apply(TNode node)
1014
{
1015
191
  Debug("bv-rewrite") << "RewriteRule<NegSub>(" << node << ")" << std::endl;
1016
  return NodeManager::currentNM()->mkNode(
1017
191
      kind::BITVECTOR_SUB, node[0][1], node[0][0]);
1018
}
1019
1020
template <>
1021
31565
inline bool RewriteRule<NegAdd>::applies(TNode node)
1022
{
1023
31565
  return (node.getKind() == kind::BITVECTOR_NEG
1024
63130
          && node[0].getKind() == kind::BITVECTOR_ADD);
1025
}
1026
1027
template <>
1028
1243
inline Node RewriteRule<NegAdd>::apply(TNode node)
1029
{
1030
1243
  Debug("bv-rewrite") << "RewriteRule<NegAdd>(" << node << ")" << std::endl;
1031
1243
  NodeManager *nm = NodeManager::currentNM();
1032
2486
  std::vector<Node> children;
1033
3743
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
1034
  {
1035
2500
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, node[0][i]));
1036
  }
1037
2486
  return utils::mkNaryNode(kind::BITVECTOR_ADD, children);
1038
}
1039
1040
struct Count {
1041
  unsigned pos;
1042
  unsigned neg;
1043
749542
  Count() : pos(0), neg(0) {}
1044
749542
  Count(unsigned p, unsigned n):
1045
    pos(p),
1046
749542
    neg(n)
1047
749542
  {}
1048
};
1049
1050
750280
inline static void insert(std::unordered_map<TNode, Count>& map,
1051
                          TNode node,
1052
                          bool neg)
1053
{
1054
750280
  if(map.find(node) == map.end()) {
1055
749542
    Count c = neg? Count(0,1) : Count(1, 0);
1056
749542
    map[node] = c;
1057
  } else {
1058
738
    if (neg) {
1059
259
      ++(map[node].neg);
1060
    } else {
1061
479
      ++(map[node].pos);
1062
    }
1063
  }
1064
750280
}
1065
1066
template<> inline
1067
235876
bool RewriteRule<AndSimplify>::applies(TNode node) {
1068
235876
  return (node.getKind() == kind::BITVECTOR_AND);
1069
}
1070
1071
template <>
1072
117938
inline Node RewriteRule<AndSimplify>::apply(TNode node)
1073
{
1074
235876
  Debug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")"
1075
117938
                      << std::endl;
1076
1077
117938
  NodeManager *nm = NodeManager::currentNM();
1078
  // this will remove duplicates
1079
235876
  std::unordered_map<TNode, Count> subterms;
1080
117938
  unsigned size = utils::getSize(node);
1081
235876
  BitVector constant = BitVector::mkOnes(size);
1082
379324
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1083
  {
1084
522772
    TNode current = node[i];
1085
    // simplify constants
1086
261386
    if (current.getKind() == kind::CONST_BITVECTOR)
1087
    {
1088
186528
      BitVector bv = current.getConst<BitVector>();
1089
93264
      constant = constant & bv;
1090
    }
1091
    else
1092
    {
1093
168122
      if (current.getKind() == kind::BITVECTOR_NOT)
1094
      {
1095
54126
        insert(subterms, current[0], true);
1096
      }
1097
      else
1098
      {
1099
113996
        insert(subterms, current, false);
1100
      }
1101
    }
1102
  }
1103
1104
235876
  std::vector<Node> children;
1105
1106
117938
  if (constant == BitVector(size, (unsigned)0))
1107
  {
1108
28469
    return utils::mkZero(size);
1109
  }
1110
1111
89469
  if (constant != BitVector::mkOnes(size))
1112
  {
1113
30757
    children.push_back(utils::mkConst(constant));
1114
  }
1115
1116
89469
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1117
1118
402927
  for (; it != subterms.end(); ++it)
1119
  {
1120
156819
    if (it->second.pos > 0 && it->second.neg > 0)
1121
    {
1122
      // if we have a and ~a
1123
90
      return utils::mkZero(size);
1124
    }
1125
    else
1126
    {
1127
      // idempotence
1128
156729
      if (it->second.neg > 0)
1129
      {
1130
        // if it only occured negated
1131
49487
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1132
      }
1133
      else
1134
      {
1135
        // if it only occured positive
1136
107242
        children.push_back(it->first);
1137
      }
1138
    }
1139
  }
1140
89379
  if (children.size() == 0)
1141
  {
1142
192
    return utils::mkOnes(size);
1143
  }
1144
1145
89187
  return utils::mkSortedNode(kind::BITVECTOR_AND, children);
1146
}
1147
1148
template<> inline
1149
283769
bool RewriteRule<FlattenAssocCommutNoDuplicates>::applies(TNode node) {
1150
283769
  Kind kind = node.getKind();
1151
283769
  if (kind != kind::BITVECTOR_OR &&
1152
      kind != kind::BITVECTOR_AND)
1153
    return false;
1154
283769
  TNode::iterator child_it = node.begin();
1155
1958753
  for(; child_it != node.end(); ++child_it) {
1156
871974
    if ((*child_it).getKind() == kind) {
1157
34482
      return true;
1158
    }
1159
  }
1160
249287
  return false;
1161
}
1162
1163
template<> inline
1164
17241
Node RewriteRule<FlattenAssocCommutNoDuplicates>::apply(TNode node) {
1165
17241
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")" << std::endl;
1166
34482
  std::vector<Node> processingStack;
1167
17241
  processingStack.push_back(node);
1168
34482
  std::unordered_set<TNode> processed;
1169
34482
  std::vector<Node> children;
1170
17241
  Kind kind = node.getKind();
1171
1172
400751
  while (! processingStack.empty()) {
1173
382293
    TNode current = processingStack.back();
1174
191755
    processingStack.pop_back();
1175
191755
    if (processed.count(current))
1176
1217
      continue;
1177
1178
190538
    processed.insert(current);
1179
1180
    // flatten expression
1181
190538
    if (current.getKind() == kind) {
1182
213102
      for (unsigned i = 0; i < current.getNumChildren(); ++i) {
1183
174514
        processingStack.push_back(current[i]);
1184
      }
1185
    } else {
1186
151950
      children.push_back(current);
1187
    }
1188
  }
1189
34482
  return utils::mkSortedNode(kind, children);
1190
}
1191
1192
1193
template<> inline
1194
297170
bool RewriteRule<OrSimplify>::applies(TNode node) {
1195
297170
  return (node.getKind() == kind::BITVECTOR_OR);
1196
}
1197
1198
template <>
1199
148580
inline Node RewriteRule<OrSimplify>::apply(TNode node)
1200
{
1201
148580
  Debug("bv-rewrite") << "RewriteRule<OrSimplify>(" << node << ")" << std::endl;
1202
1203
148580
  NodeManager *nm = NodeManager::currentNM();
1204
  // this will remove duplicates
1205
297160
  std::unordered_map<TNode, Count> subterms;
1206
148580
  unsigned size = utils::getSize(node);
1207
297160
  BitVector constant(size, (unsigned)0);
1208
1209
859984
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1210
  {
1211
1422808
    TNode current = node[i];
1212
    // simplify constants
1213
711404
    if (current.getKind() == kind::CONST_BITVECTOR)
1214
    {
1215
298246
      BitVector bv = current.getConst<BitVector>();
1216
149123
      constant = constant | bv;
1217
    }
1218
    else
1219
    {
1220
562281
      if (current.getKind() == kind::BITVECTOR_NOT)
1221
      {
1222
22472
        insert(subterms, current[0], true);
1223
      }
1224
      else
1225
      {
1226
539809
        insert(subterms, current, false);
1227
      }
1228
    }
1229
  }
1230
1231
297160
  std::vector<Node> children;
1232
1233
148580
  if (constant == BitVector::mkOnes(size))
1234
  {
1235
7669
    return utils::mkOnes(size);
1236
  }
1237
1238
140911
  if (constant != BitVector(size, (unsigned)0))
1239
  {
1240
63841
    children.push_back(utils::mkConst(constant));
1241
  }
1242
1243
140911
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1244
1245
1258765
  for (; it != subterms.end(); ++it)
1246
  {
1247
559066
    if (it->second.pos > 0 && it->second.neg > 0)
1248
    {
1249
      // if we have a or ~a
1250
139
      return utils::mkOnes(size);
1251
    }
1252
    else
1253
    {
1254
      // idempotence
1255
558927
      if (it->second.neg > 0)
1256
      {
1257
        // if it only occured negated
1258
22142
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1259
      }
1260
      else
1261
      {
1262
        // if it only occured positive
1263
536785
        children.push_back(it->first);
1264
      }
1265
    }
1266
  }
1267
1268
140772
  if (children.size() == 0)
1269
  {
1270
1090
    return utils::mkZero(size);
1271
  }
1272
139682
  return utils::mkSortedNode(kind::BITVECTOR_OR, children);
1273
}
1274
1275
template<> inline
1276
22362
bool RewriteRule<XorSimplify>::applies(TNode node) {
1277
22362
  return (node.getKind() == kind::BITVECTOR_XOR);
1278
}
1279
1280
template <>
1281
11181
inline Node RewriteRule<XorSimplify>::apply(TNode node)
1282
{
1283
22362
  Debug("bv-rewrite") << "RewriteRule<XorSimplify>(" << node << ")"
1284
11181
                      << std::endl;
1285
1286
11181
  NodeManager *nm = NodeManager::currentNM();
1287
22362
  std::unordered_map<TNode, Count> subterms;
1288
11181
  unsigned size = utils::getSize(node);
1289
22362
  BitVector constant;
1290
11181
  bool const_set = false;
1291
1292
33755
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1293
  {
1294
45148
    TNode current = node[i];
1295
    // simplify constants
1296
22574
    if (current.getKind() == kind::CONST_BITVECTOR)
1297
    {
1298
5394
      BitVector bv = current.getConst<BitVector>();
1299
2697
      if (const_set)
1300
      {
1301
481
        constant = constant ^ bv;
1302
      }
1303
      else
1304
      {
1305
2216
        const_set = true;
1306
2216
        constant = bv;
1307
      }
1308
    }
1309
    else
1310
    {
1311
      // collect number of occurances of each term and its negation
1312
19877
      if (current.getKind() == kind::BITVECTOR_NOT)
1313
      {
1314
1208
        insert(subterms, current[0], true);
1315
      }
1316
      else
1317
      {
1318
18669
        insert(subterms, current, false);
1319
      }
1320
    }
1321
  }
1322
1323
22362
  std::vector<Node> children;
1324
1325
11181
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1326
11181
  unsigned true_count = 0;
1327
11181
  bool seen_false = false;
1328
50773
  for (; it != subterms.end(); ++it)
1329
  {
1330
19796
    unsigned pos = it->second.pos;  // number of positive occurances
1331
19796
    unsigned neg = it->second.neg;  // number of negated occurances
1332
1333
    // remove duplicates using the following rules
1334
    // a xor a ==> false
1335
    // false xor false ==> false
1336
19796
    seen_false = seen_false ? seen_false : (pos > 1 || neg > 1);
1337
    // check what did not reduce
1338
19796
    if (pos % 2 && neg % 2)
1339
    {
1340
      // we have a xor ~a ==> true
1341
5
      ++true_count;
1342
    }
1343
19791
    else if (pos % 2)
1344
    {
1345
      // we had a positive occurence left
1346
18512
      children.push_back(it->first);
1347
    }
1348
1279
    else if (neg % 2)
1349
    {
1350
      // we had a negative occurence left
1351
1203
      children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1352
    }
1353
    // otherwise both reduced to false
1354
  }
1355
1356
22362
  std::vector<BitVector> xorConst;
1357
22362
  BitVector true_bv = BitVector::mkOnes(size);
1358
22362
  BitVector false_bv(size, (unsigned)0);
1359
1360
11181
  if (true_count)
1361
  {
1362
    // true xor ... xor true ==> true (odd)
1363
    //                       ==> false (even)
1364
5
    xorConst.push_back(true_count % 2 ? true_bv : false_bv);
1365
  }
1366
11181
  if (seen_false)
1367
  {
1368
76
    xorConst.push_back(false_bv);
1369
  }
1370
11181
  if (const_set)
1371
  {
1372
2216
    xorConst.push_back(constant);
1373
  }
1374
1375
11181
  if (xorConst.size() > 0)
1376
  {
1377
4590
    BitVector result = xorConst[0];
1378
2297
    for (unsigned i = 1; i < xorConst.size(); ++i)
1379
    {
1380
2
      result = result ^ xorConst[i];
1381
    }
1382
2295
    children.push_back(utils::mkConst(result));
1383
  }
1384
1385
11181
  Assert(children.size());
1386
1387
22362
  return utils::mkSortedNode(kind::BITVECTOR_XOR, children);
1388
}
1389
1390
/**
1391
 * BitwiseSlicing
1392
 *
1393
 * (a bvand c) ==> (concat (bvand a[i0:j0] c0) ... (bvand a[in:jn] cn))
1394
 *  where c0,..., cn are maximally continuous substrings of 0 or 1 in the constant c
1395
 *
1396
 * Note: this rule assumes AndSimplify has already been called on the node
1397
 */
1398
template<> inline
1399
150421
bool RewriteRule<BitwiseSlicing>::applies(TNode node) {
1400
419599
  if ((node.getKind() != kind::BITVECTOR_AND &&
1401
194792
      node.getKind() != kind::BITVECTOR_OR &&
1402
554081
      node.getKind() != kind::BITVECTOR_XOR) ||
1403
327625
      utils::getSize(node) == 1)
1404
109164
    return false;
1405
  // find the first constant and return true if it's not only 1..1 or only 0..0
1406
  // (there could be more than one constant)
1407
125491
  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
1408
87023
    if (node[i].getKind() == kind::CONST_BITVECTOR) {
1409
5578
      BitVector constant = node[i].getConst<BitVector>();
1410
      // we do not apply the rule if the constant is all 0s or all 1s
1411
2789
      if (constant == BitVector(utils::getSize(node), 0u)) return false;
1412
1413
5328
      for (unsigned j = 0, csize = constant.getSize(); j < csize; ++j)
1414
      {
1415
5221
        if (!constant.isBitSet(j)) return true;
1416
      }
1417
107
      return false;
1418
    }
1419
  }
1420
38468
  return false;
1421
}
1422
1423
template <>
1424
1341
inline Node RewriteRule<BitwiseSlicing>::apply(TNode node)
1425
{
1426
2682
  Debug("bv-rewrite") << "RewriteRule<BitwiseSlicing>(" << node << ")"
1427
1341
                      << std::endl;
1428
1341
  NodeManager *nm = NodeManager::currentNM();
1429
  // get the constant
1430
1341
  bool found_constant = false;
1431
2682
  TNode constant;
1432
2682
  std::vector<Node> other_children;
1433
4078
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1434
  {
1435
2737
    if (node[i].getKind() == kind::CONST_BITVECTOR && !found_constant)
1436
    {
1437
1341
      constant = node[i];
1438
1341
      found_constant = true;
1439
    }
1440
    else
1441
    {
1442
1396
      other_children.push_back(node[i]);
1443
    }
1444
  }
1445
1341
  Assert(found_constant && other_children.size() == node.getNumChildren() - 1);
1446
1447
2682
  Node other = utils::mkNaryNode(node.getKind(), other_children);
1448
1449
2682
  BitVector bv_constant = constant.getConst<BitVector>();
1450
2682
  std::vector<Node> concat_children;
1451
1341
  int start = bv_constant.getSize() - 1;
1452
1341
  int end = start;
1453
24730
  for (int i = end - 1; i >= 0; --i)
1454
  {
1455
23389
    if (bv_constant.isBitSet(i + 1) != bv_constant.isBitSet(i))
1456
    {
1457
4852
      Node other_extract = utils::mkExtract(other, end, start);
1458
4852
      Node const_extract = utils::mkExtract(constant, end, start);
1459
      Node bitwise_op =
1460
4852
          nm->mkNode(node.getKind(), const_extract, other_extract);
1461
2426
      concat_children.push_back(bitwise_op);
1462
2426
      start = end = i;
1463
    }
1464
    else
1465
    {
1466
20963
      start--;
1467
    }
1468
23389
    if (i == 0)
1469
    {
1470
2682
      Node other_extract = utils::mkExtract(other, end, 0);
1471
2682
      Node const_extract = utils::mkExtract(constant, end, 0);
1472
      Node bitwise_op =
1473
2682
          nm->mkNode(node.getKind(), const_extract, other_extract);
1474
1341
      concat_children.push_back(bitwise_op);
1475
    }
1476
  }
1477
1341
  Node result = utils::mkConcat(concat_children);
1478
1341
  Debug("bv-rewrite") << "    =>" << result << std::endl;
1479
2682
  return result;
1480
}
1481
1482
template <>
1483
316076
inline bool RewriteRule<NormalizeEqAddNeg>::applies(TNode node)
1484
{
1485
316076
  return node.getKind() == kind::EQUAL
1486
950660
         && (node[0].getKind() == kind::BITVECTOR_ADD
1487
648896
             || node[1].getKind() == kind::BITVECTOR_ADD);
1488
}
1489
1490
template <>
1491
1216
inline Node RewriteRule<NormalizeEqAddNeg>::apply(TNode node)
1492
{
1493
2432
  Debug("bv-rewrite") << "RewriteRule<NormalizeEqAddNeg>(" << node << ")"
1494
1216
                      << std::endl;
1495
1496
2432
  NodeBuilder nb_lhs(kind::BITVECTOR_ADD);
1497
2432
  NodeBuilder nb_rhs(kind::BITVECTOR_ADD);
1498
1216
  NodeManager *nm = NodeManager::currentNM();
1499
1500
1216
  if (node[0].getKind() == kind::BITVECTOR_ADD)
1501
  {
1502
13720
    for (const TNode &n : node[0])
1503
    {
1504
12920
      if (n.getKind() == kind::BITVECTOR_NEG)
1505
216
        nb_rhs << n[0];
1506
      else
1507
12704
        nb_lhs << n;
1508
    }
1509
  }
1510
  else
1511
  {
1512
416
    nb_lhs << node[0];
1513
  }
1514
1515
1216
  if (node[1].getKind() == kind::BITVECTOR_ADD)
1516
  {
1517
1317
    for (const TNode &n : node[1])
1518
    {
1519
895
      if (n.getKind() == kind::BITVECTOR_NEG)
1520
146
        nb_lhs << n[0];
1521
      else
1522
749
        nb_rhs << n;
1523
    }
1524
  }
1525
  else
1526
  {
1527
794
    nb_rhs << node[1];
1528
  }
1529
1530
2432
  Node zero = utils::mkZero(utils::getSize(node[0]));
1531
1532
2432
  Node lhs, rhs;
1533
1216
  if (nb_lhs.getNumChildren() == 0)
1534
  {
1535
12
    lhs = zero;
1536
  }
1537
1204
  else if (nb_lhs.getNumChildren() == 1)
1538
  {
1539
428
    lhs = nb_lhs[0];
1540
  }
1541
  else
1542
  {
1543
776
    lhs = nb_lhs.constructNode();
1544
  }
1545
1216
  if (nb_rhs.getNumChildren() == 0)
1546
  {
1547
    rhs = zero;
1548
  }
1549
1216
  else if (nb_rhs.getNumChildren() == 1)
1550
  {
1551
752
    rhs = nb_rhs[0];
1552
  }
1553
  else
1554
  {
1555
464
    rhs = nb_rhs.constructNode();
1556
  }
1557
2432
  return nm->mkNode(node.getKind(), lhs, rhs);
1558
}
1559
1560
// template<> inline
1561
// bool RewriteRule<>::applies(TNode node) {
1562
//   return (node.getKind() == kind::BITVECTOR_CONCAT);
1563
// }
1564
1565
// template<> inline
1566
// Node RewriteRule<>::apply(TNode node) {
1567
//   Debug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
1568
//   return resultNode;
1569
// }
1570
1571
1572
1573
}
1574
}
1575
}  // namespace cvc5