GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv_rewrite_rules_normalization.h Lines: 609 665 91.6 %
Date: 2021-11-07 Branches: 1214 2525 48.1 %

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
133749
bool RewriteRule<ExtractNot>::applies(TNode node) {
69
401247
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
70
401247
          node[0].getKind() == kind::BITVECTOR_NOT);
71
}
72
73
template <>
74
2418
inline Node RewriteRule<ExtractNot>::apply(TNode node)
75
{
76
2418
  Debug("bv-rewrite") << "RewriteRule<ExtractNot>(" << node << ")" << std::endl;
77
2418
  unsigned low = utils::getExtractLow(node);
78
2418
  unsigned high = utils::getExtractHigh(node);
79
4836
  Node a = utils::mkExtract(node[0][0], high, low);
80
4836
  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
132415
bool RewriteRule<ExtractSignExtend>::applies(TNode node) {
93
529660
  if (node.getKind() == kind::BITVECTOR_EXTRACT &&
94
397245
      node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND) {
95
1084
    return true;
96
  }
97
131331
  return false;
98
}
99
100
template <>
101
542
inline Node RewriteRule<ExtractSignExtend>::apply(TNode node)
102
{
103
1084
  Debug("bv-rewrite") << "RewriteRule<ExtractSignExtend>(" << node << ")"
104
542
                      << std::endl;
105
1084
  TNode extendee = node[0][0];
106
542
  unsigned extendee_size = utils::getSize(extendee);
107
108
542
  unsigned high = utils::getExtractHigh(node);
109
542
  unsigned low = utils::getExtractLow(node);
110
111
542
  Node resultNode;
112
  // extract falls on extendee
113
542
  if (high < extendee_size)
114
  {
115
190
    resultNode = utils::mkExtract(extendee, high, low);
116
  }
117
352
  else if (low < extendee_size && high >= extendee_size)
118
  {
119
    // if extract overlaps sign extend and extendee
120
128
    Node low_extract = utils::mkExtract(extendee, extendee_size - 1, low);
121
64
    unsigned new_amount = high - extendee_size + 1;
122
128
    resultNode = utils::mkSignExtend(low_extract, new_amount);
123
  }
124
  else
125
  {
126
    // extract only over sign extend
127
288
    Assert(low >= extendee_size);
128
288
    unsigned top = utils::getSize(extendee) - 1;
129
576
    Node most_significant_bit = utils::mkExtract(extendee, top, top);
130
576
    std::vector<Node> bits;
131
765
    for (unsigned i = 0; i < high - low + 1; ++i)
132
    {
133
477
      bits.push_back(most_significant_bit);
134
    }
135
288
    resultNode = utils::mkConcat(bits);
136
  }
137
1084
  Debug("bv-rewrite") << "                           =>" << resultNode
138
542
                      << std::endl;
139
1084
  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
503055
bool RewriteRule<FlattenAssocCommut>::applies(TNode node) {
207
503055
  Kind kind = node.getKind();
208
503055
  if (kind != kind::BITVECTOR_ADD && kind != kind::BITVECTOR_MULT
209
12595
      && kind != kind::BITVECTOR_OR && kind != kind::BITVECTOR_XOR
210
      && kind != kind::BITVECTOR_AND)
211
    return false;
212
503055
  TNode::iterator child_it = node.begin();
213
3250757
  for(; child_it != node.end(); ++child_it) {
214
1428005
    if ((*child_it).getKind() == kind) {
215
54154
      return true;
216
    }
217
  }
218
448901
  return false;
219
}
220
221
template <>
222
27081
inline Node RewriteRule<FlattenAssocCommut>::apply(TNode node)
223
{
224
54162
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")"
225
27081
                      << std::endl;
226
54162
  std::vector<Node> processingStack;
227
27081
  processingStack.push_back(node);
228
54162
  std::vector<Node> children;
229
27081
  Kind kind = node.getKind();
230
231
461947
  while (!processingStack.empty())
232
  {
233
434866
    TNode current = processingStack.back();
234
217433
    processingStack.pop_back();
235
236
    // flatten expression
237
217433
    if (current.getKind() == kind)
238
    {
239
253470
      for (unsigned i = 0; i < current.getNumChildren(); ++i)
240
      {
241
190352
        processingStack.push_back(current[i]);
242
      }
243
    }
244
    else
245
    {
246
154315
      children.push_back(current);
247
    }
248
  }
249
54162
  if (node.getKind() == kind::BITVECTOR_ADD
250
27081
      || node.getKind() == kind::BITVECTOR_MULT)
251
  {
252
26999
    return utils::mkNaryNode(kind, children);
253
  }
254
  else
255
  {
256
82
    return utils::mkSortedNode(kind, children);
257
  }
258
}
259
260
629043
static inline void addToCoefMap(std::map<Node, BitVector>& map,
261
                                TNode term, const BitVector& coef) {
262
629043
  if (map.find(term) != map.end()) {
263
558
    map[term] = map[term] + coef;
264
  } else {
265
628485
    map[term] = coef;
266
  }
267
629043
}
268
269
270
822327
static inline void updateCoefMap(TNode current, unsigned size,
271
                                 std::map<Node, BitVector>& factorToCoefficient,
272
                                 BitVector& constSum) {
273
822327
  switch (current.getKind()) {
274
251478
    case kind::BITVECTOR_MULT: {
275
      // look for c * term, where c is a constant
276
502956
      BitVector coeff;
277
502956
      Node term;
278
251478
      if (current.getNumChildren() == 2) {
279
        // Mult should be normalized with only one constant at end
280
61447
        Assert(!current[0].isConst());
281
61447
        if (current[1].isConst()) {
282
44479
          coeff = current[1].getConst<BitVector>();
283
44479
          term = current[0];
284
        }
285
      }
286
190031
      else if (current[current.getNumChildren()-1].isConst()) {
287
360072
        NodeBuilder nb(kind::BITVECTOR_MULT);
288
180036
        TNode::iterator child_it = current.begin();
289
1193772
        for(; (child_it+1) != current.end(); ++child_it) {
290
506868
          Assert(!(*child_it).isConst());
291
506868
          nb << (*child_it);
292
        }
293
180036
        term = nb;
294
180036
        coeff = (*child_it).getConst<BitVector>();
295
      }
296
251478
      if (term.isNull()) {
297
26963
        coeff = BitVector(size, (unsigned)1);
298
26963
        term = current;
299
      }
300
251478
      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
251478
      else if(term.getKind() == kind::BITVECTOR_NEG) {
307
        addToCoefMap(factorToCoefficient, term[0], -BitVector(size, coeff));
308
      }
309
      else {
310
251478
        addToCoefMap(factorToCoefficient, term, coeff);
311
      }
312
251478
      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
75080
    case kind::BITVECTOR_NEG:
321
75080
      addToCoefMap(factorToCoefficient, current[0], -BitVector(size, (unsigned)1));
322
75080
      break;
323
193284
    case kind::CONST_BITVECTOR: {
324
386568
      BitVector constValue = current.getConst<BitVector>();
325
193284
      constSum = constSum + constValue;
326
193284
      break;
327
    }
328
302485
    default:
329
      // store as 1 * current
330
302485
      addToCoefMap(factorToCoefficient, current, BitVector(size, (unsigned)1));
331
302485
      break;
332
  }
333
822327
}
334
335
625767
static inline void addToChildren(TNode term,
336
                                 unsigned size,
337
                                 BitVector coeff,
338
                                 std::vector<Node> &children)
339
{
340
625767
  NodeManager *nm = NodeManager::currentNM();
341
625767
  if (coeff == BitVector(size, (unsigned)0))
342
  {
343
93
    return;
344
  }
345
625674
  else if (coeff == BitVector(size, (unsigned)1))
346
  {
347
327039
    children.push_back(term);
348
  }
349
298635
  else if (coeff == -BitVector(size, (unsigned)1))
350
  {
351
    // avoid introducing an extra multiplication
352
73732
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, term));
353
  }
354
224903
  else if (term.getKind() == kind::BITVECTOR_MULT)
355
  {
356
360064
    NodeBuilder nb(kind::BITVECTOR_MULT);
357
180032
    TNode::iterator child_it = term.begin();
358
1193732
    for (; child_it != term.end(); ++child_it)
359
    {
360
506850
      nb << *child_it;
361
    }
362
180032
    nb << utils::mkConst(coeff);
363
180032
    children.push_back(Node(nb));
364
  }
365
  else
366
  {
367
89742
    Node coeffNode = utils::mkConst(coeff);
368
89742
    Node product = nm->mkNode(kind::BITVECTOR_MULT, term, coeffNode);
369
44871
    children.push_back(product);
370
  }
371
}
372
373
template <>
374
179446
inline bool RewriteRule<AddCombineLikeTerms>::applies(TNode node)
375
{
376
179446
  return (node.getKind() == kind::BITVECTOR_ADD);
377
}
378
379
template <>
380
89723
inline Node RewriteRule<AddCombineLikeTerms>::apply(TNode node)
381
{
382
179446
  Debug("bv-rewrite") << "RewriteRule<AddCombineLikeTerms>(" << node << ")"
383
89723
                      << std::endl;
384
89723
  unsigned size = utils::getSize(node);
385
179446
  BitVector constSum(size, (unsigned)0);
386
179446
  std::map<Node, BitVector> factorToCoefficient;
387
388
  // combine like-terms
389
528454
  for (size_t i = 0, n = node.getNumChildren(); i < n; ++i)
390
  {
391
877462
    TNode current = node[i];
392
438731
    updateCoefMap(current, size, factorToCoefficient, constSum);
393
  }
394
395
179446
  std::vector<Node> children;
396
397
  // construct result
398
89723
  std::map<Node, BitVector>::const_iterator it = factorToCoefficient.begin();
399
400
762181
  for (; it != factorToCoefficient.end(); ++it)
401
  {
402
336229
    addToChildren(it->first, size, it->second, children);
403
  }
404
405
89723
  if (constSum != BitVector(size, (unsigned)0))
406
  {
407
55755
    children.push_back(utils::mkConst(constSum));
408
  }
409
410
89723
  size_t csize = children.size();
411
89723
  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
45420
    return node;
420
  }
421
422
  return csize == 0 ? utils::mkZero(size)
423
44303
                    : utils::mkNaryNode(kind::BITVECTOR_ADD, children);
424
}
425
426
template<> inline
427
610302
bool RewriteRule<MultSimplify>::applies(TNode node) {
428
610302
  return node.getKind() == kind::BITVECTOR_MULT;
429
}
430
431
template <>
432
305151
inline Node RewriteRule<MultSimplify>::apply(TNode node)
433
{
434
610302
  Debug("bv-rewrite") << "RewriteRule<MultSimplify>(" << node << ")"
435
305151
                      << std::endl;
436
305151
  NodeManager *nm = NodeManager::currentNM();
437
305151
  unsigned size = utils::getSize(node);
438
610302
  BitVector constant(size, Integer(1));
439
440
305151
  bool isNeg = false;
441
610302
  std::vector<Node> children;
442
1091111
  for (const TNode &current : node)
443
  {
444
1585854
    Node c = current;
445
799894
    if (c.getKind() == kind::BITVECTOR_NEG)
446
    {
447
1379
      isNeg = !isNeg;
448
1379
      c = c[0];
449
    }
450
451
799894
    if (c.getKind() == kind::CONST_BITVECTOR)
452
    {
453
615714
      BitVector value = c.getConst<BitVector>();
454
314824
      constant = constant * value;
455
314824
      if (constant == BitVector(size, (unsigned)0))
456
      {
457
13934
        return utils::mkConst(size, 0);
458
      }
459
    }
460
    else
461
    {
462
485070
      children.push_back(c);
463
    }
464
  }
465
582434
  BitVector oValue = BitVector(size, static_cast<unsigned>(1));
466
582434
  BitVector noValue = BitVector::mkOnes(size);
467
468
291217
  if (children.empty())
469
  {
470
35777
    return utils::mkConst(isNeg ? -constant : constant);
471
  }
472
473
255440
  std::sort(children.begin(), children.end());
474
475
255440
  if (constant == noValue)
476
  {
477
1949
    isNeg = !isNeg;
478
  }
479
253491
  else if (constant != oValue)
480
  {
481
214335
    if (isNeg)
482
    {
483
1174
      isNeg = !isNeg;
484
1174
      constant = -constant;
485
    }
486
214335
    children.push_back(utils::mkConst(constant));
487
  }
488
489
510880
  Node ret = utils::mkNaryNode(kind::BITVECTOR_MULT, children);
490
491
  // if negative, negate entire node
492
255440
  if (isNeg && size > 1)
493
  {
494
1096
    ret = nm->mkNode(kind::BITVECTOR_NEG, ret);
495
  }
496
255440
  return ret;
497
}
498
499
template<> inline
500
114506
bool RewriteRule<MultDistribConst>::applies(TNode node) {
501
190240
  if (node.getKind() != kind::BITVECTOR_MULT ||
502
75734
      node.getNumChildren() != 2) {
503
82977
    return false;
504
  }
505
31529
  Assert(!node[0].isConst());
506
31529
  if (!node[1].isConst()) {
507
16765
    return false;
508
  }
509
29528
  TNode factor = node[0];
510
14764
  return (factor.getKind() == kind::BITVECTOR_ADD
511
12600
          || factor.getKind() == kind::BITVECTOR_SUB
512
27364
          || factor.getKind() == kind::BITVECTOR_NEG);
513
}
514
515
template <>
516
1082
inline Node RewriteRule<MultDistribConst>::apply(TNode node)
517
{
518
2164
  Debug("bv-rewrite") << "RewriteRule<MultDistribConst>(" << node << ")"
519
1082
                      << std::endl;
520
521
1082
  NodeManager *nm = NodeManager::currentNM();
522
2164
  TNode constant = node[1];
523
2164
  TNode factor = node[0];
524
1082
  Assert(constant.getKind() == kind::CONST_BITVECTOR);
525
526
1082
  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
2164
  std::vector<Node> children;
535
11332
  for (unsigned i = 0; i < factor.getNumChildren(); ++i)
536
  {
537
10250
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, factor[i], constant));
538
  }
539
540
1082
  return utils::mkNaryNode(factor.getKind(), children);
541
}
542
543
template<> inline
544
113812
bool RewriteRule<MultDistrib>::applies(TNode node) {
545
187770
  if (node.getKind() != kind::BITVECTOR_MULT ||
546
73958
      node.getNumChildren() != 2) {
547
84059
    return false;
548
  }
549
89259
  if (node[0].getKind() == kind::BITVECTOR_ADD
550
89259
      || node[0].getKind() == kind::BITVECTOR_SUB)
551
  {
552
186
    return node[1].getKind() != kind::BITVECTOR_ADD
553
186
           && node[1].getKind() != kind::BITVECTOR_SUB;
554
  }
555
89073
  return node[1].getKind() == kind::BITVECTOR_ADD
556
89073
         || node[1].getKind() == kind::BITVECTOR_SUB;
557
}
558
559
template <>
560
388
inline Node RewriteRule<MultDistrib>::apply(TNode node)
561
{
562
776
  Debug("bv-rewrite") << "RewriteRule<MultDistrib>(" << node << ")"
563
388
                      << std::endl;
564
565
388
  NodeManager *nm = NodeManager::currentNM();
566
1164
  bool is_rhs_factor = node[0].getKind() == kind::BITVECTOR_ADD
567
1164
                       || node[0].getKind() == kind::BITVECTOR_SUB;
568
776
  TNode factor = !is_rhs_factor ? node[0] : node[1];
569
776
  TNode sum = is_rhs_factor ? node[0] : node[1];
570
388
  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
776
  std::vector<Node> children;
576
21000
  for (unsigned i = 0; i < sum.getNumChildren(); ++i)
577
  {
578
20612
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, sum[i], factor));
579
  }
580
581
776
  return utils::mkNaryNode(sum.getKind(), children);
582
}
583
584
template<> inline
585
bool RewriteRule<ConcatToMult>::applies(TNode node) {
586
  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
441943
inline bool RewriteRule<SolveEq>::applies(TNode node)
619
{
620
883886
  if (node.getKind() != kind::EQUAL
621
840773
      || (node[0].isVar() && !expr::hasSubterm(node[1], node[0]))
622
1230778
      || (node[1].isVar() && !expr::hasSubterm(node[0], node[1])))
623
  {
624
120771
    return false;
625
  }
626
321172
  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
160586
inline Node RewriteRule<SolveEq>::apply(TNode node)
633
{
634
160586
  Debug("bv-rewrite") << "RewriteRule<SolveEq>(" << node << ")" << std::endl;
635
636
321172
  TNode left = node[0];
637
321172
  TNode right = node[1];
638
639
160586
  unsigned size = utils::getSize(left);
640
321172
  BitVector zero(size, (unsigned)0);
641
321172
  BitVector leftConst(size, (unsigned)0);
642
321172
  BitVector rightConst(size, (unsigned)0);
643
321172
  std::map<Node, BitVector> leftMap, rightMap;
644
645
  // Collect terms and coefficients plus constant for left
646
160586
  if (left.getKind() == kind::BITVECTOR_ADD)
647
  {
648
70629
    for (unsigned i = 0; i < left.getNumChildren(); ++i)
649
    {
650
62207
      updateCoefMap(left[i], size, leftMap, leftConst);
651
    }
652
  }
653
152164
  else if (left.getKind() == kind::BITVECTOR_NOT && left[0] == right)
654
  {
655
32
    return utils::mkFalse();
656
  }
657
  else
658
  {
659
152132
    updateCoefMap(left, size, leftMap, leftConst);
660
  }
661
662
  // Collect terms and coefficients plus constant for right
663
160554
  if (right.getKind() == kind::BITVECTOR_ADD)
664
  {
665
24923
    for (unsigned i = 0; i < right.getNumChildren(); ++i)
666
    {
667
16813
      updateCoefMap(right[i], size, rightMap, rightConst);
668
    }
669
  }
670
152444
  else if (right.getKind() == kind::BITVECTOR_NOT && right[0] == left)
671
  {
672
    return utils::mkFalse();
673
  }
674
  else
675
  {
676
152444
    updateCoefMap(right, size, rightMap, rightConst);
677
  }
678
679
321108
  std::vector<Node> childrenLeft, childrenRight;
680
681
160554
  std::map<Node, BitVector>::const_iterator iLeft = leftMap.begin(),
682
160554
                                            iLeftEnd = leftMap.end();
683
160554
  std::map<Node, BitVector>::const_iterator iRight = rightMap.begin(),
684
160554
                                            iRightEnd = rightMap.end();
685
686
321108
  BitVector coeffLeft;
687
321108
  TNode termLeft;
688
160554
  if (iLeft != iLeftEnd)
689
  {
690
157218
    coeffLeft = iLeft->second;
691
157218
    termLeft = iLeft->first;
692
  }
693
694
321108
  BitVector coeffRight;
695
321108
  TNode termRight;
696
160554
  if (iRight != iRightEnd)
697
  {
698
85125
    coeffRight = iRight->second;
699
85125
    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
160554
  bool changed = false;
710
  bool incLeft, incRight;
711
712
742272
  while (iLeft != iLeftEnd || iRight != iRightEnd)
713
  {
714
290859
    incLeft = incRight = false;
715
290859
    if (iLeft != iLeftEnd && (iRight == iRightEnd || termLeft < termRight))
716
    {
717
203322
      addToChildren(termLeft, size, coeffLeft, childrenLeft);
718
203322
      incLeft = true;
719
    }
720
87537
    else if (iLeft == iLeftEnd || termRight < termLeft)
721
    {
722
86140
      Assert(iRight != iRightEnd);
723
86140
      addToChildren(termRight, size, coeffRight, childrenRight);
724
86140
      incRight = true;
725
    }
726
    else
727
    {
728
1397
      if (coeffLeft > coeffRight)
729
      {
730
76
        addToChildren(termLeft, size, coeffLeft - coeffRight, childrenLeft);
731
      }
732
1321
      else if (coeffRight > coeffLeft)
733
      {
734
        addToChildren(termRight, size, coeffRight - coeffLeft, childrenRight);
735
      }
736
1397
      incLeft = incRight = true;
737
1397
      changed = true;
738
    }
739
290859
    if (incLeft)
740
    {
741
204719
      ++iLeft;
742
204719
      if (iLeft != iLeftEnd)
743
      {
744
47501
        Assert(termLeft < iLeft->first);
745
47501
        coeffLeft = iLeft->second;
746
47501
        termLeft = iLeft->first;
747
      }
748
    }
749
290859
    if (incRight)
750
    {
751
87537
      ++iRight;
752
87537
      if (iRight != iRightEnd)
753
      {
754
2412
        Assert(termRight < iRight->first);
755
2412
        coeffRight = iRight->second;
756
2412
        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
160554
  if (rightConst != zero)
766
  {
767
59665
    changed |= (leftConst != zero);
768
59665
    rightConst = rightConst - leftConst;
769
59665
    leftConst = zero;
770
59665
    if (rightConst != zero)
771
    {
772
59136
      childrenRight.push_back(utils::mkConst(rightConst));
773
    }
774
  }
775
100889
  else if (leftConst != zero)
776
  {
777
6186
    childrenLeft.push_back(utils::mkConst(leftConst));
778
  }
779
780
321108
  Node newLeft, newRight;
781
782
160554
  if (childrenRight.size() == 0 && leftConst != zero)
783
  {
784
542
    Assert(childrenLeft.back().isConst()
785
           && childrenLeft.back().getConst<BitVector>() == leftConst);
786
542
    if (childrenLeft.size() == 1)
787
    {
788
      // c = 0 ==> false
789
141
      return utils::mkFalse();
790
    }
791
    // special case - if right is empty and left has a constant, move the
792
    // constant
793
401
    childrenRight.push_back(utils::mkConst(-leftConst));
794
401
    childrenLeft.pop_back();
795
401
    changed = true;
796
  }
797
798
160413
  if (childrenLeft.size() == 0)
799
  {
800
2063
    if (rightConst != zero)
801
    {
802
1564
      Assert(childrenRight.back().isConst()
803
             && childrenRight.back().getConst<BitVector>() == rightConst);
804
1564
      if (childrenRight.size() == 1)
805
      {
806
        // 0 = c ==> false
807
1130
        return utils::mkFalse();
808
      }
809
      // special case - if left is empty and right has a constant, move the
810
      // constant
811
434
      newLeft = utils::mkConst(-rightConst);
812
434
      childrenRight.pop_back();
813
434
      changed = true;
814
    }
815
    else
816
    {
817
499
      newLeft = utils::mkConst(size, (unsigned)0);
818
    }
819
  }
820
  else
821
  {
822
158350
    newLeft = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenLeft);
823
  }
824
825
159283
  if (childrenRight.size() == 0)
826
  {
827
21922
    newRight = utils::mkConst(size, (unsigned)0);
828
  }
829
  else
830
  {
831
137361
    newRight = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenRight);
832
  }
833
834
159283
  if (!changed)
835
  {
836
156959
    return node;
837
  }
838
839
2324
  if (newLeft == newRight)
840
  {
841
13
    Assert(newLeft == utils::mkConst(size, (unsigned)0));
842
13
    return utils::mkTrue();
843
  }
844
845
2311
  if (newLeft < newRight)
846
  {
847
773
    return newRight.eqNode(newLeft);
848
  }
849
850
1538
  return newLeft.eqNode(newRight);
851
}
852
853
template<> inline
854
252312
bool RewriteRule<BitwiseEq>::applies(TNode node) {
855
539334
  if (node.getKind() != kind::EQUAL ||
856
287022
      utils::getSize(node[0]) != 1) {
857
248535
    return false;
858
  }
859
7554
  TNode term;
860
7554
  BitVector c;
861
3777
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
862
151
    c = node[0].getConst<BitVector>();
863
151
    term = node[1];
864
  }
865
3626
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
866
2293
    c = node[1].getConst<BitVector>();
867
2293
    term = node[0];
868
  }
869
  else {
870
1333
    return false;
871
  }
872
2444
  switch (term.getKind()) {
873
862
    case kind::BITVECTOR_AND:
874
    case kind::BITVECTOR_OR:
875
      //operator BITVECTOR_XOR 2: "bitwise xor"
876
    case kind::BITVECTOR_NOT:
877
    case kind::BITVECTOR_NAND:
878
    case kind::BITVECTOR_NOR:
879
      //operator BITVECTOR_XNOR 2 "bitwise xnor"
880
    case kind::BITVECTOR_COMP:
881
    case kind::BITVECTOR_NEG:
882
862
      return true;
883
      break;
884
1582
    default:
885
1582
      break;
886
  }
887
1582
  return false;
888
}
889
890
891
109
static inline Node mkNodeKind(Kind k, TNode node, TNode c) {
892
109
  unsigned i = 0;
893
109
  unsigned nc = node.getNumChildren();
894
218
  NodeBuilder nb(k);
895
1045
  for(; i < nc; ++i) {
896
468
    nb << node[i].eqNode(c);
897
  }
898
218
  return nb;
899
}
900
901
902
template<> inline
903
431
Node RewriteRule<BitwiseEq>::apply(TNode node) {
904
431
  Debug("bv-rewrite") << "RewriteRule<BitwiseEq>(" << node << ")" << std::endl;
905
906
862
  TNode term;
907
862
  BitVector c;
908
909
431
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
910
4
    c = node[0].getConst<BitVector>();
911
4
    term = node[1];
912
  }
913
427
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
914
427
    c = node[1].getConst<BitVector>();
915
427
    term = node[0];
916
  }
917
918
431
  bool eqOne = (c == BitVector(1,(unsigned)1));
919
920
431
  switch (term.getKind()) {
921
41
    case kind::BITVECTOR_AND:
922
41
      if (eqOne) {
923
17
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
924
      }
925
      else {
926
24
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
927
      }
928
      break;
929
    case kind::BITVECTOR_NAND:
930
      if (eqOne) {
931
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
932
      }
933
      else {
934
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
935
      }
936
      break;
937
68
    case kind::BITVECTOR_OR:
938
68
      if (eqOne) {
939
60
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
940
      }
941
      else {
942
8
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
943
      }
944
      break;
945
    case kind::BITVECTOR_NOR:
946
      if (eqOne) {
947
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
948
      }
949
      else {
950
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
951
      }
952
      break;
953
136
    case kind::BITVECTOR_NOT:
954
136
      return term[0].eqNode(utils::mkConst(~c));
955
170
    case kind::BITVECTOR_COMP:
956
170
      Assert(term.getNumChildren() == 2);
957
170
      if (eqOne) {
958
158
        return term[0].eqNode(term[1]);
959
      }
960
      else {
961
12
        return term[0].eqNode(term[1]).notNode();
962
      }
963
16
    case kind::BITVECTOR_NEG:
964
16
      return term[0].eqNode(utils::mkConst(c));
965
    default:
966
      break;
967
  }
968
  Unreachable();
969
}
970
971
972
/**
973
 * -(c * expr) ==> (-c * expr)
974
 * where c is a constant
975
 */
976
template<> inline
977
21905
bool RewriteRule<NegMult>::applies(TNode node) {
978
87620
  if(node.getKind()!= kind::BITVECTOR_NEG ||
979
65715
     node[0].getKind() != kind::BITVECTOR_MULT) {
980
20825
    return false;
981
  }
982
1080
  return node[node.getNumChildren()-1].isConst();
983
}
984
985
template<> inline
986
Node RewriteRule<NegMult>::apply(TNode node) {
987
  Debug("bv-rewrite") << "RewriteRule<NegMult>(" << node << ")" << std::endl;
988
  TNode mult = node[0];
989
  NodeBuilder nb(kind::BITVECTOR_MULT);
990
  BitVector bv(utils::getSize(node), (unsigned)1);
991
  TNode::iterator child_it = mult.begin();
992
  for(; (child_it+1) != mult.end(); ++child_it) {
993
    nb << (*child_it);
994
  }
995
  Assert((*child_it).isConst());
996
  bv = (*child_it).getConst<BitVector>();
997
  nb << utils::mkConst(-bv);
998
  return Node(nb);
999
}
1000
1001
template<> inline
1002
41404
bool RewriteRule<NegSub>::applies(TNode node) {
1003
105314
  return (node.getKind() == kind::BITVECTOR_NEG &&
1004
105314
          node[0].getKind() == kind::BITVECTOR_SUB);
1005
}
1006
1007
template <>
1008
224
inline Node RewriteRule<NegSub>::apply(TNode node)
1009
{
1010
224
  Debug("bv-rewrite") << "RewriteRule<NegSub>(" << node << ")" << std::endl;
1011
  return NodeManager::currentNM()->mkNode(
1012
224
      kind::BITVECTOR_SUB, node[0][1], node[0][0]);
1013
}
1014
1015
template <>
1016
42466
inline bool RewriteRule<NegAdd>::applies(TNode node)
1017
{
1018
42466
  return (node.getKind() == kind::BITVECTOR_NEG
1019
84932
          && node[0].getKind() == kind::BITVECTOR_ADD);
1020
}
1021
1022
template <>
1023
1286
inline Node RewriteRule<NegAdd>::apply(TNode node)
1024
{
1025
1286
  Debug("bv-rewrite") << "RewriteRule<NegAdd>(" << node << ")" << std::endl;
1026
1286
  NodeManager *nm = NodeManager::currentNM();
1027
2572
  std::vector<Node> children;
1028
3866
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
1029
  {
1030
2580
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, node[0][i]));
1031
  }
1032
2572
  return utils::mkNaryNode(kind::BITVECTOR_ADD, children);
1033
}
1034
1035
struct Count {
1036
  unsigned pos;
1037
  unsigned neg;
1038
1105399
  Count() : pos(0), neg(0) {}
1039
1105399
  Count(unsigned p, unsigned n):
1040
    pos(p),
1041
1105399
    neg(n)
1042
1105399
  {}
1043
};
1044
1045
1106321
inline static void insert(std::unordered_map<TNode, Count>& map,
1046
                          TNode node,
1047
                          bool neg)
1048
{
1049
1106321
  if(map.find(node) == map.end()) {
1050
1105399
    Count c = neg? Count(0,1) : Count(1, 0);
1051
1105399
    map[node] = c;
1052
  } else {
1053
922
    if (neg) {
1054
363
      ++(map[node].neg);
1055
    } else {
1056
559
      ++(map[node].pos);
1057
    }
1058
  }
1059
1106321
}
1060
1061
template<> inline
1062
324002
bool RewriteRule<AndSimplify>::applies(TNode node) {
1063
324002
  return (node.getKind() == kind::BITVECTOR_AND);
1064
}
1065
1066
template <>
1067
162001
inline Node RewriteRule<AndSimplify>::apply(TNode node)
1068
{
1069
324002
  Debug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")"
1070
162001
                      << std::endl;
1071
1072
162001
  NodeManager *nm = NodeManager::currentNM();
1073
  // this will remove duplicates
1074
324002
  std::unordered_map<TNode, Count> subterms;
1075
162001
  unsigned size = utils::getSize(node);
1076
324002
  BitVector constant = BitVector::mkOnes(size);
1077
520834
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1078
  {
1079
717666
    TNode current = node[i];
1080
    // simplify constants
1081
358833
    if (current.getKind() == kind::CONST_BITVECTOR)
1082
    {
1083
262236
      BitVector bv = current.getConst<BitVector>();
1084
131118
      constant = constant & bv;
1085
    }
1086
    else
1087
    {
1088
227715
      if (current.getKind() == kind::BITVECTOR_NOT)
1089
      {
1090
75878
        insert(subterms, current[0], true);
1091
      }
1092
      else
1093
      {
1094
151837
        insert(subterms, current, false);
1095
      }
1096
    }
1097
  }
1098
1099
324002
  std::vector<Node> children;
1100
1101
162001
  if (constant == BitVector(size, (unsigned)0))
1102
  {
1103
38997
    return utils::mkZero(size);
1104
  }
1105
1106
123004
  if (constant != BitVector::mkOnes(size))
1107
  {
1108
44867
    children.push_back(utils::mkConst(constant));
1109
  }
1110
1111
123004
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1112
1113
546434
  for (; it != subterms.end(); ++it)
1114
  {
1115
211838
    if (it->second.pos > 0 && it->second.neg > 0)
1116
    {
1117
      // if we have a and ~a
1118
123
      return utils::mkZero(size);
1119
    }
1120
    else
1121
    {
1122
      // idempotence
1123
211715
      if (it->second.neg > 0)
1124
      {
1125
        // if it only occured negated
1126
69245
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1127
      }
1128
      else
1129
      {
1130
        // if it only occured positive
1131
142470
        children.push_back(it->first);
1132
      }
1133
    }
1134
  }
1135
122881
  if (children.size() == 0)
1136
  {
1137
264
    return utils::mkOnes(size);
1138
  }
1139
1140
122617
  return utils::mkSortedNode(kind::BITVECTOR_AND, children);
1141
}
1142
1143
template<> inline
1144
390113
bool RewriteRule<FlattenAssocCommutNoDuplicates>::applies(TNode node) {
1145
390113
  Kind kind = node.getKind();
1146
390113
  if (kind != kind::BITVECTOR_OR &&
1147
      kind != kind::BITVECTOR_AND)
1148
    return false;
1149
390113
  TNode::iterator child_it = node.begin();
1150
2821049
  for(; child_it != node.end(); ++child_it) {
1151
1265492
    if ((*child_it).getKind() == kind) {
1152
50024
      return true;
1153
    }
1154
  }
1155
340089
  return false;
1156
}
1157
1158
template<> inline
1159
25012
Node RewriteRule<FlattenAssocCommutNoDuplicates>::apply(TNode node) {
1160
25012
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")" << std::endl;
1161
50024
  std::vector<Node> processingStack;
1162
25012
  processingStack.push_back(node);
1163
50024
  std::unordered_set<TNode> processed;
1164
50024
  std::vector<Node> children;
1165
25012
  Kind kind = node.getKind();
1166
1167
608040
  while (! processingStack.empty()) {
1168
581478
    TNode current = processingStack.back();
1169
291514
    processingStack.pop_back();
1170
291514
    if (processed.count(current))
1171
1550
      continue;
1172
1173
289964
    processed.insert(current);
1174
1175
    // flatten expression
1176
289964
    if (current.getKind() == kind) {
1177
321877
      for (unsigned i = 0; i < current.getNumChildren(); ++i) {
1178
266502
        processingStack.push_back(current[i]);
1179
      }
1180
    } else {
1181
234589
      children.push_back(current);
1182
    }
1183
  }
1184
50024
  return utils::mkSortedNode(kind, children);
1185
}
1186
1187
1188
template<> inline
1189
406193
bool RewriteRule<OrSimplify>::applies(TNode node) {
1190
406193
  return (node.getKind() == kind::BITVECTOR_OR);
1191
}
1192
1193
template <>
1194
203093
inline Node RewriteRule<OrSimplify>::apply(TNode node)
1195
{
1196
203093
  Debug("bv-rewrite") << "RewriteRule<OrSimplify>(" << node << ")" << std::endl;
1197
1198
203093
  NodeManager *nm = NodeManager::currentNM();
1199
  // this will remove duplicates
1200
406186
  std::unordered_map<TNode, Count> subterms;
1201
203093
  unsigned size = utils::getSize(node);
1202
406186
  BitVector constant(size, (unsigned)0);
1203
1204
1270218
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1205
  {
1206
2134250
    TNode current = node[i];
1207
    // simplify constants
1208
1067125
    if (current.getKind() == kind::CONST_BITVECTOR)
1209
    {
1210
419564
      BitVector bv = current.getConst<BitVector>();
1211
209782
      constant = constant | bv;
1212
    }
1213
    else
1214
    {
1215
857343
      if (current.getKind() == kind::BITVECTOR_NOT)
1216
      {
1217
32902
        insert(subterms, current[0], true);
1218
      }
1219
      else
1220
      {
1221
824441
        insert(subterms, current, false);
1222
      }
1223
    }
1224
  }
1225
1226
406186
  std::vector<Node> children;
1227
1228
203093
  if (constant == BitVector::mkOnes(size))
1229
  {
1230
11087
    return utils::mkOnes(size);
1231
  }
1232
1233
192006
  if (constant != BitVector(size, (unsigned)0))
1234
  {
1235
83919
    children.push_back(utils::mkConst(constant));
1236
  }
1237
1238
192006
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1239
1240
1896018
  for (; it != subterms.end(); ++it)
1241
  {
1242
852209
    if (it->second.pos > 0 && it->second.neg > 0)
1243
    {
1244
      // if we have a or ~a
1245
203
      return utils::mkOnes(size);
1246
    }
1247
    else
1248
    {
1249
      // idempotence
1250
852006
      if (it->second.neg > 0)
1251
      {
1252
        // if it only occured negated
1253
32383
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1254
      }
1255
      else
1256
      {
1257
        // if it only occured positive
1258
819623
        children.push_back(it->first);
1259
      }
1260
    }
1261
  }
1262
1263
191803
  if (children.size() == 0)
1264
  {
1265
1594
    return utils::mkZero(size);
1266
  }
1267
190209
  return utils::mkSortedNode(kind::BITVECTOR_OR, children);
1268
}
1269
1270
template<> inline
1271
25026
bool RewriteRule<XorSimplify>::applies(TNode node) {
1272
25026
  return (node.getKind() == kind::BITVECTOR_XOR);
1273
}
1274
1275
template <>
1276
12513
inline Node RewriteRule<XorSimplify>::apply(TNode node)
1277
{
1278
25026
  Debug("bv-rewrite") << "RewriteRule<XorSimplify>(" << node << ")"
1279
12513
                      << std::endl;
1280
1281
12513
  NodeManager *nm = NodeManager::currentNM();
1282
25026
  std::unordered_map<TNode, Count> subterms;
1283
12513
  unsigned size = utils::getSize(node);
1284
25026
  BitVector constant;
1285
12513
  bool const_set = false;
1286
1287
37765
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1288
  {
1289
50504
    TNode current = node[i];
1290
    // simplify constants
1291
25252
    if (current.getKind() == kind::CONST_BITVECTOR)
1292
    {
1293
7978
      BitVector bv = current.getConst<BitVector>();
1294
3989
      if (const_set)
1295
      {
1296
611
        constant = constant ^ bv;
1297
      }
1298
      else
1299
      {
1300
3378
        const_set = true;
1301
3378
        constant = bv;
1302
      }
1303
    }
1304
    else
1305
    {
1306
      // collect number of occurances of each term and its negation
1307
21263
      if (current.getKind() == kind::BITVECTOR_NOT)
1308
      {
1309
1100
        insert(subterms, current[0], true);
1310
      }
1311
      else
1312
      {
1313
20163
        insert(subterms, current, false);
1314
      }
1315
    }
1316
  }
1317
1318
25026
  std::vector<Node> children;
1319
1320
12513
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1321
12513
  unsigned true_count = 0;
1322
12513
  bool seen_false = false;
1323
54867
  for (; it != subterms.end(); ++it)
1324
  {
1325
21177
    unsigned pos = it->second.pos;  // number of positive occurances
1326
21177
    unsigned neg = it->second.neg;  // number of negated occurances
1327
1328
    // remove duplicates using the following rules
1329
    // a xor a ==> false
1330
    // false xor false ==> false
1331
21177
    seen_false = seen_false ? seen_false : (pos > 1 || neg > 1);
1332
    // check what did not reduce
1333
21177
    if (pos % 2 && neg % 2)
1334
    {
1335
      // we have a xor ~a ==> true
1336
7
      ++true_count;
1337
    }
1338
21170
    else if (pos % 2)
1339
    {
1340
      // we had a positive occurence left
1341
19998
      children.push_back(it->first);
1342
    }
1343
1172
    else if (neg % 2)
1344
    {
1345
      // we had a negative occurence left
1346
1093
      children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1347
    }
1348
    // otherwise both reduced to false
1349
  }
1350
1351
25026
  std::vector<BitVector> xorConst;
1352
25026
  BitVector true_bv = BitVector::mkOnes(size);
1353
25026
  BitVector false_bv(size, (unsigned)0);
1354
1355
12513
  if (true_count)
1356
  {
1357
    // true xor ... xor true ==> true (odd)
1358
    //                       ==> false (even)
1359
7
    xorConst.push_back(true_count % 2 ? true_bv : false_bv);
1360
  }
1361
12513
  if (seen_false)
1362
  {
1363
79
    xorConst.push_back(false_bv);
1364
  }
1365
12513
  if (const_set)
1366
  {
1367
3378
    xorConst.push_back(constant);
1368
  }
1369
1370
12513
  if (xorConst.size() > 0)
1371
  {
1372
6920
    BitVector result = xorConst[0];
1373
3464
    for (unsigned i = 1; i < xorConst.size(); ++i)
1374
    {
1375
4
      result = result ^ xorConst[i];
1376
    }
1377
3460
    children.push_back(utils::mkConst(result));
1378
  }
1379
1380
12513
  Assert(children.size());
1381
1382
25026
  return utils::mkSortedNode(kind::BITVECTOR_XOR, children);
1383
}
1384
1385
/**
1386
 * BitwiseSlicing
1387
 *
1388
 * (a bvand c) ==> (concat (bvand a[i0:j0] c0) ... (bvand a[in:jn] cn))
1389
 *  where c0,..., cn are maximally continuous substrings of 0 or 1 in the constant c
1390
 *
1391
 * Note: this rule assumes AndSimplify has already been called on the node
1392
 */
1393
template<> inline
1394
203238
bool RewriteRule<BitwiseSlicing>::applies(TNode node) {
1395
567114
  if ((node.getKind() != kind::BITVECTOR_AND &&
1396
260959
      node.getKind() != kind::BITVECTOR_OR &&
1397
743169
      node.getKind() != kind::BITVECTOR_XOR) ||
1398
439610
      utils::getSize(node) == 1)
1399
145932
    return false;
1400
  // find the first constant and return true if it's not only 1..1 or only 0..0
1401
  // (there could be more than one constant)
1402
175090
  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
1403
121984
    if (node[i].getKind() == kind::CONST_BITVECTOR) {
1404
8400
      BitVector constant = node[i].getConst<BitVector>();
1405
      // we do not apply the rule if the constant is all 0s or all 1s
1406
4200
      if (constant == BitVector(utils::getSize(node), 0u)) return false;
1407
1408
9196
      for (unsigned j = 0, csize = constant.getSize(); j < csize; ++j)
1409
      {
1410
8916
        if (!constant.isBitSet(j)) return true;
1411
      }
1412
280
      return false;
1413
    }
1414
  }
1415
53106
  return false;
1416
}
1417
1418
template <>
1419
1960
inline Node RewriteRule<BitwiseSlicing>::apply(TNode node)
1420
{
1421
3920
  Debug("bv-rewrite") << "RewriteRule<BitwiseSlicing>(" << node << ")"
1422
1960
                      << std::endl;
1423
1960
  NodeManager *nm = NodeManager::currentNM();
1424
  // get the constant
1425
1960
  bool found_constant = false;
1426
3920
  TNode constant;
1427
3920
  std::vector<Node> other_children;
1428
5972
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1429
  {
1430
4012
    if (node[i].getKind() == kind::CONST_BITVECTOR && !found_constant)
1431
    {
1432
1960
      constant = node[i];
1433
1960
      found_constant = true;
1434
    }
1435
    else
1436
    {
1437
2052
      other_children.push_back(node[i]);
1438
    }
1439
  }
1440
1960
  Assert(found_constant && other_children.size() == node.getNumChildren() - 1);
1441
1442
3920
  Node other = utils::mkNaryNode(node.getKind(), other_children);
1443
1444
3920
  BitVector bv_constant = constant.getConst<BitVector>();
1445
3920
  std::vector<Node> concat_children;
1446
1960
  int start = bv_constant.getSize() - 1;
1447
1960
  int end = start;
1448
42877
  for (int i = end - 1; i >= 0; --i)
1449
  {
1450
40917
    if (bv_constant.isBitSet(i + 1) != bv_constant.isBitSet(i))
1451
    {
1452
6718
      Node other_extract = utils::mkExtract(other, end, start);
1453
6718
      Node const_extract = utils::mkExtract(constant, end, start);
1454
      Node bitwise_op =
1455
6718
          nm->mkNode(node.getKind(), const_extract, other_extract);
1456
3359
      concat_children.push_back(bitwise_op);
1457
3359
      start = end = i;
1458
    }
1459
    else
1460
    {
1461
37558
      start--;
1462
    }
1463
40917
    if (i == 0)
1464
    {
1465
3920
      Node other_extract = utils::mkExtract(other, end, 0);
1466
3920
      Node const_extract = utils::mkExtract(constant, end, 0);
1467
      Node bitwise_op =
1468
3920
          nm->mkNode(node.getKind(), const_extract, other_extract);
1469
1960
      concat_children.push_back(bitwise_op);
1470
    }
1471
  }
1472
1960
  Node result = utils::mkConcat(concat_children);
1473
1960
  Debug("bv-rewrite") << "    =>" << result << std::endl;
1474
3920
  return result;
1475
}
1476
1477
template <>
1478
inline bool RewriteRule<NormalizeEqAddNeg>::applies(TNode node)
1479
{
1480
  return node.getKind() == kind::EQUAL
1481
         && (node[0].getKind() == kind::BITVECTOR_ADD
1482
             || node[1].getKind() == kind::BITVECTOR_ADD);
1483
}
1484
1485
template <>
1486
inline Node RewriteRule<NormalizeEqAddNeg>::apply(TNode node)
1487
{
1488
  Debug("bv-rewrite") << "RewriteRule<NormalizeEqAddNeg>(" << node << ")"
1489
                      << std::endl;
1490
1491
  NodeBuilder nb_lhs(kind::BITVECTOR_ADD);
1492
  NodeBuilder nb_rhs(kind::BITVECTOR_ADD);
1493
  NodeManager *nm = NodeManager::currentNM();
1494
1495
  if (node[0].getKind() == kind::BITVECTOR_ADD)
1496
  {
1497
    for (const TNode &n : node[0])
1498
    {
1499
      if (n.getKind() == kind::BITVECTOR_NEG)
1500
        nb_rhs << n[0];
1501
      else
1502
        nb_lhs << n;
1503
    }
1504
  }
1505
  else
1506
  {
1507
    nb_lhs << node[0];
1508
  }
1509
1510
  if (node[1].getKind() == kind::BITVECTOR_ADD)
1511
  {
1512
    for (const TNode &n : node[1])
1513
    {
1514
      if (n.getKind() == kind::BITVECTOR_NEG)
1515
        nb_lhs << n[0];
1516
      else
1517
        nb_rhs << n;
1518
    }
1519
  }
1520
  else
1521
  {
1522
    nb_rhs << node[1];
1523
  }
1524
1525
  Node zero = utils::mkZero(utils::getSize(node[0]));
1526
1527
  Node lhs, rhs;
1528
  if (nb_lhs.getNumChildren() == 0)
1529
  {
1530
    lhs = zero;
1531
  }
1532
  else if (nb_lhs.getNumChildren() == 1)
1533
  {
1534
    lhs = nb_lhs[0];
1535
  }
1536
  else
1537
  {
1538
    lhs = nb_lhs.constructNode();
1539
  }
1540
  if (nb_rhs.getNumChildren() == 0)
1541
  {
1542
    rhs = zero;
1543
  }
1544
  else if (nb_rhs.getNumChildren() == 1)
1545
  {
1546
    rhs = nb_rhs[0];
1547
  }
1548
  else
1549
  {
1550
    rhs = nb_rhs.constructNode();
1551
  }
1552
  return nm->mkNode(node.getKind(), lhs, rhs);
1553
}
1554
1555
// template<> inline
1556
// bool RewriteRule<>::applies(TNode node) {
1557
//   return (node.getKind() == kind::BITVECTOR_CONCAT);
1558
// }
1559
1560
// template<> inline
1561
// Node RewriteRule<>::apply(TNode node) {
1562
//   Debug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
1563
//   return resultNode;
1564
// }
1565
1566
1567
1568
}
1569
}
1570
}  // namespace cvc5