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

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Aina Niemetz, Clark Barrett
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * [[ Add one-line brief description here ]]
14
 *
15
 * [[ Add lengthier description here ]]
16
 * \todo document this file
17
 */
18
19
#include "cvc5_private.h"
20
21
#pragma once
22
23
#include <unordered_map>
24
#include <unordered_set>
25
26
#include "expr/node_algorithm.h"
27
#include "theory/bv/theory_bv_rewrite_rules.h"
28
#include "theory/bv/theory_bv_utils.h"
29
#include "theory/rewriter.h"
30
#include "util/bitvector.h"
31
32
namespace cvc5 {
33
namespace theory {
34
namespace bv {
35
36
/**
37
 * ExtractBitwise
38
 *   (x bvop y) [i:j] ==> x[i:j] bvop y[i:j]
39
 *  where bvop is bvand,bvor, bvxor
40
 */
41
template<> inline
42
bool RewriteRule<ExtractBitwise>::applies(TNode node) {
43
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
44
          (node[0].getKind() == kind::BITVECTOR_AND ||
45
           node[0].getKind() == kind::BITVECTOR_OR ||
46
           node[0].getKind() == kind::BITVECTOR_XOR ));
47
}
48
49
template<> inline
50
Node RewriteRule<ExtractBitwise>::apply(TNode node) {
51
  Debug("bv-rewrite") << "RewriteRule<ExtractBitwise>(" << node << ")" << std::endl;
52
  unsigned high = utils::getExtractHigh(node);
53
  unsigned low = utils::getExtractLow(node);
54
  std::vector<Node> children;
55
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i) {
56
    children.push_back(utils::mkExtract(node[0][i], high, low));
57
  }
58
  Kind kind = node[0].getKind();
59
  return utils::mkSortedNode(kind, children);
60
}
61
62
/**
63
 * ExtractNot
64
 *
65
 *  (~ a) [i:j] ==> ~ (a[i:j])
66
 */
67
template<> inline
68
106619
bool RewriteRule<ExtractNot>::applies(TNode node) {
69
319857
  return (node.getKind() == kind::BITVECTOR_EXTRACT &&
70
319857
          node[0].getKind() == kind::BITVECTOR_NOT);
71
}
72
73
template <>
74
1672
inline Node RewriteRule<ExtractNot>::apply(TNode node)
75
{
76
1672
  Debug("bv-rewrite") << "RewriteRule<ExtractNot>(" << node << ")" << std::endl;
77
1672
  unsigned low = utils::getExtractLow(node);
78
1672
  unsigned high = utils::getExtractHigh(node);
79
3344
  Node a = utils::mkExtract(node[0][0], high, low);
80
3344
  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
106013
bool RewriteRule<ExtractSignExtend>::applies(TNode node) {
93
424052
  if (node.getKind() == kind::BITVECTOR_EXTRACT &&
94
318039
      node[0].getKind() == kind::BITVECTOR_SIGN_EXTEND) {
95
1066
    return true;
96
  }
97
104947
  return false;
98
}
99
100
template <>
101
533
inline Node RewriteRule<ExtractSignExtend>::apply(TNode node)
102
{
103
1066
  Debug("bv-rewrite") << "RewriteRule<ExtractSignExtend>(" << node << ")"
104
533
                      << std::endl;
105
1066
  TNode extendee = node[0][0];
106
533
  unsigned extendee_size = utils::getSize(extendee);
107
108
533
  unsigned high = utils::getExtractHigh(node);
109
533
  unsigned low = utils::getExtractLow(node);
110
111
533
  Node resultNode;
112
  // extract falls on extendee
113
533
  if (high < extendee_size)
114
  {
115
187
    resultNode = utils::mkExtract(extendee, high, low);
116
  }
117
346
  else if (low < extendee_size && high >= extendee_size)
118
  {
119
    // if extract overlaps sign extend and extendee
120
122
    Node low_extract = utils::mkExtract(extendee, extendee_size - 1, low);
121
61
    unsigned new_amount = high - extendee_size + 1;
122
122
    resultNode = utils::mkSignExtend(low_extract, new_amount);
123
  }
124
  else
125
  {
126
    // extract only over sign extend
127
285
    Assert(low >= extendee_size);
128
285
    unsigned top = utils::getSize(extendee) - 1;
129
570
    Node most_significant_bit = utils::mkExtract(extendee, top, top);
130
570
    std::vector<Node> bits;
131
753
    for (unsigned i = 0; i < high - low + 1; ++i)
132
    {
133
468
      bits.push_back(most_significant_bit);
134
    }
135
285
    resultNode = utils::mkConcat(bits);
136
  }
137
1066
  Debug("bv-rewrite") << "                           =>" << resultNode
138
533
                      << std::endl;
139
1066
  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
399231
bool RewriteRule<FlattenAssocCommut>::applies(TNode node) {
207
399231
  Kind kind = node.getKind();
208
399231
  if (kind != kind::BITVECTOR_ADD && kind != kind::BITVECTOR_MULT
209
9190
      && kind != kind::BITVECTOR_OR && kind != kind::BITVECTOR_XOR
210
      && kind != kind::BITVECTOR_AND)
211
    return false;
212
399231
  TNode::iterator child_it = node.begin();
213
2718631
  for(; child_it != node.end(); ++child_it) {
214
1212242
    if ((*child_it).getKind() == kind) {
215
52542
      return true;
216
    }
217
  }
218
346689
  return false;
219
}
220
221
template <>
222
26275
inline Node RewriteRule<FlattenAssocCommut>::apply(TNode node)
223
{
224
52550
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")"
225
26275
                      << std::endl;
226
52550
  std::vector<Node> processingStack;
227
26275
  processingStack.push_back(node);
228
52550
  std::vector<Node> children;
229
26275
  Kind kind = node.getKind();
230
231
452585
  while (!processingStack.empty())
232
  {
233
426310
    TNode current = processingStack.back();
234
213155
    processingStack.pop_back();
235
236
    // flatten expression
237
213155
    if (current.getKind() == kind)
238
    {
239
248274
      for (unsigned i = 0; i < current.getNumChildren(); ++i)
240
      {
241
186880
        processingStack.push_back(current[i]);
242
      }
243
    }
244
    else
245
    {
246
151761
      children.push_back(current);
247
    }
248
  }
249
52550
  if (node.getKind() == kind::BITVECTOR_ADD
250
26275
      || node.getKind() == kind::BITVECTOR_MULT)
251
  {
252
26200
    return utils::mkNaryNode(kind, children);
253
  }
254
  else
255
  {
256
75
    return utils::mkSortedNode(kind, children);
257
  }
258
}
259
260
575858
static inline void addToCoefMap(std::map<Node, BitVector>& map,
261
                                TNode term, const BitVector& coef) {
262
575858
  if (map.find(term) != map.end()) {
263
440
    map[term] = map[term] + coef;
264
  } else {
265
575418
    map[term] = coef;
266
  }
267
575858
}
268
269
270
734457
static inline void updateCoefMap(TNode current, unsigned size,
271
                                 std::map<Node, BitVector>& factorToCoefficient,
272
                                 BitVector& constSum) {
273
734457
  switch (current.getKind()) {
274
246456
    case kind::BITVECTOR_MULT: {
275
      // look for c * term, where c is a constant
276
492912
      BitVector coeff;
277
492912
      Node term;
278
246456
      if (current.getNumChildren() == 2) {
279
        // Mult should be normalized with only one constant at end
280
57993
        Assert(!current[0].isConst());
281
57993
        if (current[1].isConst()) {
282
44482
          coeff = current[1].getConst<BitVector>();
283
44482
          term = current[0];
284
        }
285
      }
286
188463
      else if (current[current.getNumChildren()-1].isConst()) {
287
359816
        NodeBuilder nb(kind::BITVECTOR_MULT);
288
179908
        TNode::iterator child_it = current.begin();
289
1192980
        for(; (child_it+1) != current.end(); ++child_it) {
290
506536
          Assert(!(*child_it).isConst());
291
506536
          nb << (*child_it);
292
        }
293
179908
        term = nb;
294
179908
        coeff = (*child_it).getConst<BitVector>();
295
      }
296
246456
      if (term.isNull()) {
297
22066
        coeff = BitVector(size, (unsigned)1);
298
22066
        term = current;
299
      }
300
246456
      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
246456
      else if(term.getKind() == kind::BITVECTOR_NEG) {
307
        addToCoefMap(factorToCoefficient, term[0], -BitVector(size, coeff));
308
      }
309
      else {
310
246456
        addToCoefMap(factorToCoefficient, term, coeff);
311
      }
312
246456
      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
73808
    case kind::BITVECTOR_NEG:
321
73808
      addToCoefMap(factorToCoefficient, current[0], -BitVector(size, (unsigned)1));
322
73808
      break;
323
158599
    case kind::CONST_BITVECTOR: {
324
317198
      BitVector constValue = current.getConst<BitVector>();
325
158599
      constSum = constSum + constValue;
326
158599
      break;
327
    }
328
255594
    default:
329
      // store as 1 * current
330
255594
      addToCoefMap(factorToCoefficient, current, BitVector(size, (unsigned)1));
331
255594
      break;
332
  }
333
734457
}
334
335
572740
static inline void addToChildren(TNode term,
336
                                 unsigned size,
337
                                 BitVector coeff,
338
                                 std::vector<Node> &children)
339
{
340
572740
  NodeManager *nm = NodeManager::currentNM();
341
572740
  if (coeff == BitVector(size, (unsigned)0))
342
  {
343
86
    return;
344
  }
345
572654
  else if (coeff == BitVector(size, (unsigned)1))
346
  {
347
275498
    children.push_back(term);
348
  }
349
297156
  else if (coeff == -BitVector(size, (unsigned)1))
350
  {
351
    // avoid introducing an extra multiplication
352
72486
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, term));
353
  }
354
224670
  else if (term.getKind() == kind::BITVECTOR_MULT)
355
  {
356
359808
    NodeBuilder nb(kind::BITVECTOR_MULT);
357
179904
    TNode::iterator child_it = term.begin();
358
1192940
    for (; child_it != term.end(); ++child_it)
359
    {
360
506518
      nb << *child_it;
361
    }
362
179904
    nb << utils::mkConst(coeff);
363
179904
    children.push_back(Node(nb));
364
  }
365
  else
366
  {
367
89532
    Node coeffNode = utils::mkConst(coeff);
368
89532
    Node product = nm->mkNode(kind::BITVECTOR_MULT, term, coeffNode);
369
44766
    children.push_back(product);
370
  }
371
}
372
373
template <>
374
145594
inline bool RewriteRule<AddCombineLikeTerms>::applies(TNode node)
375
{
376
145594
  return (node.getKind() == kind::BITVECTOR_ADD);
377
}
378
379
template <>
380
72797
inline Node RewriteRule<AddCombineLikeTerms>::apply(TNode node)
381
{
382
145594
  Debug("bv-rewrite") << "RewriteRule<AddCombineLikeTerms>(" << node << ")"
383
72797
                      << std::endl;
384
72797
  unsigned size = utils::getSize(node);
385
145594
  BitVector constSum(size, (unsigned)0);
386
145594
  std::map<Node, BitVector> factorToCoefficient;
387
388
  // combine like-terms
389
477363
  for (size_t i = 0, n = node.getNumChildren(); i < n; ++i)
390
  {
391
809132
    TNode current = node[i];
392
404566
    updateCoefMap(current, size, factorToCoefficient, constSum);
393
  }
394
395
145594
  std::vector<Node> children;
396
397
  // construct result
398
72797
  std::map<Node, BitVector>::const_iterator it = factorToCoefficient.begin();
399
400
713709
  for (; it != factorToCoefficient.end(); ++it)
401
  {
402
320456
    addToChildren(it->first, size, it->second, children);
403
  }
404
405
72797
  if (constSum != BitVector(size, (unsigned)0))
406
  {
407
45145
    children.push_back(utils::mkConst(constSum));
408
  }
409
410
72797
  size_t csize = children.size();
411
72797
  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
36042
    return node;
420
  }
421
422
  return csize == 0 ? utils::mkZero(size)
423
36755
                    : utils::mkNaryNode(kind::BITVECTOR_ADD, children);
424
}
425
426
template<> inline
427
469530
bool RewriteRule<MultSimplify>::applies(TNode node) {
428
469530
  return node.getKind() == kind::BITVECTOR_MULT;
429
}
430
431
template <>
432
234765
inline Node RewriteRule<MultSimplify>::apply(TNode node)
433
{
434
469530
  Debug("bv-rewrite") << "RewriteRule<MultSimplify>(" << node << ")"
435
234765
                      << std::endl;
436
234765
  NodeManager *nm = NodeManager::currentNM();
437
234765
  unsigned size = utils::getSize(node);
438
469530
  BitVector constant(size, Integer(1));
439
440
234765
  bool isNeg = false;
441
469530
  std::vector<Node> children;
442
880060
  for (const TNode &current : node)
443
  {
444
1300079
    Node c = current;
445
654784
    if (c.getKind() == kind::BITVECTOR_NEG)
446
    {
447
1363
      isNeg = !isNeg;
448
1363
      c = c[0];
449
    }
450
451
654784
    if (c.getKind() == kind::CONST_BITVECTOR)
452
    {
453
461263
      BitVector value = c.getConst<BitVector>();
454
235376
      constant = constant * value;
455
235376
      if (constant == BitVector(size, (unsigned)0))
456
      {
457
9489
        return utils::mkConst(size, 0);
458
      }
459
    }
460
    else
461
    {
462
419408
      children.push_back(c);
463
    }
464
  }
465
450552
  BitVector oValue = BitVector(size, static_cast<unsigned>(1));
466
450552
  BitVector noValue = BitVector::mkOnes(size);
467
468
225276
  if (children.empty())
469
  {
470
20796
    return utils::mkConst(isNeg ? -constant : constant);
471
  }
472
473
204480
  std::sort(children.begin(), children.end());
474
475
204480
  if (constant == noValue)
476
  {
477
1686
    isNeg = !isNeg;
478
  }
479
202794
  else if (constant != oValue)
480
  {
481
174647
    if (isNeg)
482
    {
483
1168
      isNeg = !isNeg;
484
1168
      constant = -constant;
485
    }
486
174647
    children.push_back(utils::mkConst(constant));
487
  }
488
489
408960
  Node ret = utils::mkNaryNode(kind::BITVECTOR_MULT, children);
490
491
  // if negative, negate entire node
492
204480
  if (isNeg && size > 1)
493
  {
494
893
    ret = nm->mkNode(kind::BITVECTOR_NEG, ret);
495
  }
496
204480
  return ret;
497
}
498
499
template<> inline
500
90210
bool RewriteRule<MultDistribConst>::applies(TNode node) {
501
159286
  if (node.getKind() != kind::BITVECTOR_MULT ||
502
69076
      node.getNumChildren() != 2) {
503
64024
    return false;
504
  }
505
26186
  Assert(!node[0].isConst());
506
26186
  if (!node[1].isConst()) {
507
11541
    return false;
508
  }
509
29290
  TNode factor = node[0];
510
14645
  return (factor.getKind() == kind::BITVECTOR_ADD
511
12481
          || factor.getKind() == kind::BITVECTOR_SUB
512
27126
          || 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
89514
bool RewriteRule<MultDistrib>::applies(TNode node) {
545
156812
  if (node.getKind() != kind::BITVECTOR_MULT ||
546
67298
      node.getNumChildren() != 2) {
547
65106
    return false;
548
  }
549
73224
  if (node[0].getKind() == kind::BITVECTOR_ADD
550
73224
      || 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
73038
  return node[1].getKind() == kind::BITVECTOR_ADD
556
73038
         || node[1].getKind() == kind::BITVECTOR_SUB;
557
}
558
559
template <>
560
386
inline Node RewriteRule<MultDistrib>::apply(TNode node)
561
{
562
772
  Debug("bv-rewrite") << "RewriteRule<MultDistrib>(" << node << ")"
563
386
                      << std::endl;
564
565
386
  NodeManager *nm = NodeManager::currentNM();
566
1158
  bool is_rhs_factor = node[0].getKind() == kind::BITVECTOR_ADD
567
1158
                       || node[0].getKind() == kind::BITVECTOR_SUB;
568
772
  TNode factor = !is_rhs_factor ? node[0] : node[1];
569
772
  TNode sum = is_rhs_factor ? node[0] : node[1];
570
386
  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
772
  std::vector<Node> children;
576
20994
  for (unsigned i = 0; i < sum.getNumChildren(); ++i)
577
  {
578
20608
    children.push_back(nm->mkNode(kind::BITVECTOR_MULT, sum[i], factor));
579
  }
580
581
772
  return utils::mkNaryNode(sum.getKind(), children);
582
}
583
584
template<> inline
585
8
bool RewriteRule<ConcatToMult>::applies(TNode node) {
586
8
  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
368148
inline bool RewriteRule<SolveEq>::applies(TNode node)
619
{
620
736296
  if (node.getKind() != kind::EQUAL
621
712804
      || (node[0].isVar() && !expr::hasSubterm(node[1], node[0]))
622
1029810
      || (node[1].isVar() && !expr::hasSubterm(node[0], node[1])))
623
  {
624
99374
    return false;
625
  }
626
268774
  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
134387
inline Node RewriteRule<SolveEq>::apply(TNode node)
633
{
634
134387
  Debug("bv-rewrite") << "RewriteRule<SolveEq>(" << node << ")" << std::endl;
635
636
268774
  TNode left = node[0];
637
268774
  TNode right = node[1];
638
639
134387
  unsigned size = utils::getSize(left);
640
268774
  BitVector zero(size, (unsigned)0);
641
268774
  BitVector leftConst(size, (unsigned)0);
642
268774
  BitVector rightConst(size, (unsigned)0);
643
268774
  std::map<Node, BitVector> leftMap, rightMap;
644
645
  // Collect terms and coefficients plus constant for left
646
134387
  if (left.getKind() == kind::BITVECTOR_ADD)
647
  {
648
68399
    for (unsigned i = 0; i < left.getNumChildren(); ++i)
649
    {
650
60709
      updateCoefMap(left[i], size, leftMap, leftConst);
651
    }
652
  }
653
126697
  else if (left.getKind() == kind::BITVECTOR_NOT && left[0] == right)
654
  {
655
40
    return utils::mkFalse();
656
  }
657
  else
658
  {
659
126657
    updateCoefMap(left, size, leftMap, leftConst);
660
  }
661
662
  // Collect terms and coefficients plus constant for right
663
134347
  if (right.getKind() == kind::BITVECTOR_ADD)
664
  {
665
23548
    for (unsigned i = 0; i < right.getNumChildren(); ++i)
666
    {
667
15863
      updateCoefMap(right[i], size, rightMap, rightConst);
668
    }
669
  }
670
126662
  else if (right.getKind() == kind::BITVECTOR_NOT && right[0] == left)
671
  {
672
    return utils::mkFalse();
673
  }
674
  else
675
  {
676
126662
    updateCoefMap(right, size, rightMap, rightConst);
677
  }
678
679
268694
  std::vector<Node> childrenLeft, childrenRight;
680
681
134347
  std::map<Node, BitVector>::const_iterator iLeft = leftMap.begin(),
682
134347
                                            iLeftEnd = leftMap.end();
683
134347
  std::map<Node, BitVector>::const_iterator iRight = rightMap.begin(),
684
134347
                                            iRightEnd = rightMap.end();
685
686
268694
  BitVector coeffLeft;
687
268694
  TNode termLeft;
688
134347
  if (iLeft != iLeftEnd)
689
  {
690
131605
    coeffLeft = iLeft->second;
691
131605
    termLeft = iLeft->first;
692
  }
693
694
268694
  BitVector coeffRight;
695
268694
  TNode termRight;
696
134347
  if (iRight != iRightEnd)
697
  {
698
74236
    coeffRight = iRight->second;
699
74236
    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
134347
  bool changed = false;
710
  bool incLeft, incRight;
711
712
641531
  while (iLeft != iLeftEnd || iRight != iRightEnd)
713
  {
714
253592
    incLeft = incRight = false;
715
253592
    if (iLeft != iLeftEnd && (iRight == iRightEnd || termLeft < termRight))
716
    {
717
177251
      addToChildren(termLeft, size, coeffLeft, childrenLeft);
718
177251
      incLeft = true;
719
    }
720
76341
    else if (iLeft == iLeftEnd || termRight < termLeft)
721
    {
722
74971
      Assert(iRight != iRightEnd);
723
74971
      addToChildren(termRight, size, coeffRight, childrenRight);
724
74971
      incRight = true;
725
    }
726
    else
727
    {
728
1370
      if (coeffLeft > coeffRight)
729
      {
730
62
        addToChildren(termLeft, size, coeffLeft - coeffRight, childrenLeft);
731
      }
732
1308
      else if (coeffRight > coeffLeft)
733
      {
734
        addToChildren(termRight, size, coeffRight - coeffLeft, childrenRight);
735
      }
736
1370
      incLeft = incRight = true;
737
1370
      changed = true;
738
    }
739
253592
    if (incLeft)
740
    {
741
178621
      ++iLeft;
742
178621
      if (iLeft != iLeftEnd)
743
      {
744
47016
        Assert(termLeft < iLeft->first);
745
47016
        coeffLeft = iLeft->second;
746
47016
        termLeft = iLeft->first;
747
      }
748
    }
749
253592
    if (incRight)
750
    {
751
76341
      ++iRight;
752
76341
      if (iRight != iRightEnd)
753
      {
754
2105
        Assert(termRight < iRight->first);
755
2105
        coeffRight = iRight->second;
756
2105
        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
134347
  if (rightConst != zero)
766
  {
767
48199
    changed |= (leftConst != zero);
768
48199
    rightConst = rightConst - leftConst;
769
48199
    leftConst = zero;
770
48199
    if (rightConst != zero)
771
    {
772
47655
      childrenRight.push_back(utils::mkConst(rightConst));
773
    }
774
  }
775
86148
  else if (leftConst != zero)
776
  {
777
5457
    childrenLeft.push_back(utils::mkConst(leftConst));
778
  }
779
780
268694
  Node newLeft, newRight;
781
782
134347
  if (childrenRight.size() == 0 && leftConst != zero)
783
  {
784
465
    Assert(childrenLeft.back().isConst()
785
           && childrenLeft.back().getConst<BitVector>() == leftConst);
786
465
    if (childrenLeft.size() == 1)
787
    {
788
      // c = 0 ==> false
789
132
      return utils::mkFalse();
790
    }
791
    // special case - if right is empty and left has a constant, move the
792
    // constant
793
333
    childrenRight.push_back(utils::mkConst(-leftConst));
794
333
    childrenLeft.pop_back();
795
333
    changed = true;
796
  }
797
798
134215
  if (childrenLeft.size() == 0)
799
  {
800
2019
    if (rightConst != zero)
801
    {
802
1523
      Assert(childrenRight.back().isConst()
803
             && childrenRight.back().getConst<BitVector>() == rightConst);
804
1523
      if (childrenRight.size() == 1)
805
      {
806
        // 0 = c ==> false
807
1128
        return utils::mkFalse();
808
      }
809
      // special case - if left is empty and right has a constant, move the
810
      // constant
811
395
      newLeft = utils::mkConst(-rightConst);
812
395
      childrenRight.pop_back();
813
395
      changed = true;
814
    }
815
    else
816
    {
817
496
      newLeft = utils::mkConst(size, (unsigned)0);
818
    }
819
  }
820
  else
821
  {
822
132196
    newLeft = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenLeft);
823
  }
824
825
133087
  if (childrenRight.size() == 0)
826
  {
827
17868
    newRight = utils::mkConst(size, (unsigned)0);
828
  }
829
  else
830
  {
831
115219
    newRight = utils::mkNaryNode(kind::BITVECTOR_ADD, childrenRight);
832
  }
833
834
133087
  if (!changed)
835
  {
836
130988
    return node;
837
  }
838
839
2099
  if (newLeft == newRight)
840
  {
841
14
    Assert(newLeft == utils::mkConst(size, (unsigned)0));
842
14
    return utils::mkTrue();
843
  }
844
845
2085
  if (newLeft < newRight)
846
  {
847
707
    Assert((newRight == left && newLeft == right)
848
           || Rewriter::rewrite(newRight) != left
849
           || Rewriter::rewrite(newLeft) != right);
850
707
    return newRight.eqNode(newLeft);
851
  }
852
853
1378
  Assert((newLeft == left && newRight == right)
854
         || Rewriter::rewrite(newLeft) != left
855
         || Rewriter::rewrite(newRight) != right);
856
1378
  return newLeft.eqNode(newRight);
857
}
858
859
template<> inline
860
46
bool RewriteRule<BitwiseEq>::applies(TNode node) {
861
132
  if (node.getKind() != kind::EQUAL ||
862
86
      utils::getSize(node[0]) != 1) {
863
46
    return false;
864
  }
865
  TNode term;
866
  BitVector c;
867
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
868
    c = node[0].getConst<BitVector>();
869
    term = node[1];
870
  }
871
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
872
    c = node[1].getConst<BitVector>();
873
    term = node[0];
874
  }
875
  else {
876
    return false;
877
  }
878
  switch (term.getKind()) {
879
    case kind::BITVECTOR_AND:
880
    case kind::BITVECTOR_OR:
881
      //operator BITVECTOR_XOR 2: "bitwise xor"
882
    case kind::BITVECTOR_NOT:
883
    case kind::BITVECTOR_NAND:
884
    case kind::BITVECTOR_NOR:
885
      //operator BITVECTOR_XNOR 2 "bitwise xnor"
886
    case kind::BITVECTOR_COMP:
887
    case kind::BITVECTOR_NEG:
888
      return true;
889
      break;
890
    default:
891
      break;
892
  }
893
  return false;
894
}
895
896
897
static inline Node mkNodeKind(Kind k, TNode node, TNode c) {
898
  unsigned i = 0;
899
  unsigned nc = node.getNumChildren();
900
  NodeBuilder nb(k);
901
  for(; i < nc; ++i) {
902
    nb << node[i].eqNode(c);
903
  }
904
  return nb;
905
}
906
907
908
template<> inline
909
Node RewriteRule<BitwiseEq>::apply(TNode node) {
910
  Debug("bv-rewrite") << "RewriteRule<BitwiseEq>(" << node << ")" << std::endl;
911
912
  TNode term;
913
  BitVector c;
914
915
  if (node[0].getKind() == kind::CONST_BITVECTOR) {
916
    c = node[0].getConst<BitVector>();
917
    term = node[1];
918
  }
919
  else if (node[1].getKind() == kind::CONST_BITVECTOR) {
920
    c = node[1].getConst<BitVector>();
921
    term = node[0];
922
  }
923
924
  bool eqOne = (c == BitVector(1,(unsigned)1));
925
926
  switch (term.getKind()) {
927
    case kind::BITVECTOR_AND:
928
      if (eqOne) {
929
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
930
      }
931
      else {
932
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
933
      }
934
      break;
935
    case kind::BITVECTOR_NAND:
936
      if (eqOne) {
937
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)0));
938
      }
939
      else {
940
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)1));
941
      }
942
      break;
943
    case kind::BITVECTOR_OR:
944
      if (eqOne) {
945
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
946
      }
947
      else {
948
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
949
      }
950
      break;
951
    case kind::BITVECTOR_NOR:
952
      if (eqOne) {
953
        return mkNodeKind(kind::AND, term, utils::mkConst(1, (unsigned)0));
954
      }
955
      else {
956
        return mkNodeKind(kind::OR, term, utils::mkConst(1, (unsigned)1));
957
      }
958
      break;
959
    case kind::BITVECTOR_NOT:
960
      return term[0].eqNode(utils::mkConst(~c));
961
    case kind::BITVECTOR_COMP:
962
      Assert(term.getNumChildren() == 2);
963
      if (eqOne) {
964
        return term[0].eqNode(term[1]);
965
      }
966
      else {
967
        return term[0].eqNode(term[1]).notNode();
968
      }
969
    case kind::BITVECTOR_NEG:
970
      return term[0].eqNode(utils::mkConst(c));
971
    default:
972
      break;
973
  }
974
  Unreachable();
975
}
976
977
978
/**
979
 * -(c * expr) ==> (-c * expr)
980
 * where c is a constant
981
 */
982
template<> inline
983
17158
bool RewriteRule<NegMult>::applies(TNode node) {
984
68632
  if(node.getKind()!= kind::BITVECTOR_NEG ||
985
51474
     node[0].getKind() != kind::BITVECTOR_MULT) {
986
16086
    return false;
987
  }
988
1072
  return node[node.getNumChildren()-1].isConst();
989
}
990
991
template<> inline
992
Node RewriteRule<NegMult>::apply(TNode node) {
993
  Debug("bv-rewrite") << "RewriteRule<NegMult>(" << node << ")" << std::endl;
994
  TNode mult = node[0];
995
  NodeBuilder nb(kind::BITVECTOR_MULT);
996
  BitVector bv(utils::getSize(node), (unsigned)1);
997
  TNode::iterator child_it = mult.begin();
998
  for(; (child_it+1) != mult.end(); ++child_it) {
999
    nb << (*child_it);
1000
  }
1001
  Assert((*child_it).isConst());
1002
  bv = (*child_it).getConst<BitVector>();
1003
  nb << utils::mkConst(-bv);
1004
  return Node(nb);
1005
}
1006
1007
template<> inline
1008
32928
bool RewriteRule<NegSub>::applies(TNode node) {
1009
83770
  return (node.getKind() == kind::BITVECTOR_NEG &&
1010
83770
          node[0].getKind() == kind::BITVECTOR_SUB);
1011
}
1012
1013
template <>
1014
208
inline Node RewriteRule<NegSub>::apply(TNode node)
1015
{
1016
208
  Debug("bv-rewrite") << "RewriteRule<NegSub>(" << node << ")" << std::endl;
1017
  return NodeManager::currentNM()->mkNode(
1018
208
      kind::BITVECTOR_SUB, node[0][1], node[0][0]);
1019
}
1020
1021
template <>
1022
33970
inline bool RewriteRule<NegAdd>::applies(TNode node)
1023
{
1024
33970
  return (node.getKind() == kind::BITVECTOR_NEG
1025
67940
          && node[0].getKind() == kind::BITVECTOR_ADD);
1026
}
1027
1028
template <>
1029
1250
inline Node RewriteRule<NegAdd>::apply(TNode node)
1030
{
1031
1250
  Debug("bv-rewrite") << "RewriteRule<NegAdd>(" << node << ")" << std::endl;
1032
1250
  NodeManager *nm = NodeManager::currentNM();
1033
2500
  std::vector<Node> children;
1034
3758
  for (unsigned i = 0; i < node[0].getNumChildren(); ++i)
1035
  {
1036
2508
    children.push_back(nm->mkNode(kind::BITVECTOR_NEG, node[0][i]));
1037
  }
1038
2500
  return utils::mkNaryNode(kind::BITVECTOR_ADD, children);
1039
}
1040
1041
struct Count {
1042
  unsigned pos;
1043
  unsigned neg;
1044
861419
  Count() : pos(0), neg(0) {}
1045
861419
  Count(unsigned p, unsigned n):
1046
    pos(p),
1047
861419
    neg(n)
1048
861419
  {}
1049
};
1050
1051
862150
inline static void insert(std::unordered_map<TNode, Count>& map,
1052
                          TNode node,
1053
                          bool neg)
1054
{
1055
862150
  if(map.find(node) == map.end()) {
1056
861419
    Count c = neg? Count(0,1) : Count(1, 0);
1057
861419
    map[node] = c;
1058
  } else {
1059
731
    if (neg) {
1060
262
      ++(map[node].neg);
1061
    } else {
1062
469
      ++(map[node].pos);
1063
    }
1064
  }
1065
862150
}
1066
1067
template<> inline
1068
240506
bool RewriteRule<AndSimplify>::applies(TNode node) {
1069
240506
  return (node.getKind() == kind::BITVECTOR_AND);
1070
}
1071
1072
template <>
1073
120253
inline Node RewriteRule<AndSimplify>::apply(TNode node)
1074
{
1075
240506
  Debug("bv-rewrite") << "RewriteRule<AndSimplify>(" << node << ")"
1076
120253
                      << std::endl;
1077
1078
120253
  NodeManager *nm = NodeManager::currentNM();
1079
  // this will remove duplicates
1080
240506
  std::unordered_map<TNode, Count> subterms;
1081
120253
  unsigned size = utils::getSize(node);
1082
240506
  BitVector constant = BitVector::mkOnes(size);
1083
402636
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1084
  {
1085
564766
    TNode current = node[i];
1086
    // simplify constants
1087
282383
    if (current.getKind() == kind::CONST_BITVECTOR)
1088
    {
1089
186170
      BitVector bv = current.getConst<BitVector>();
1090
93085
      constant = constant & bv;
1091
    }
1092
    else
1093
    {
1094
189298
      if (current.getKind() == kind::BITVECTOR_NOT)
1095
      {
1096
65527
        insert(subterms, current[0], true);
1097
      }
1098
      else
1099
      {
1100
123771
        insert(subterms, current, false);
1101
      }
1102
    }
1103
  }
1104
1105
240506
  std::vector<Node> children;
1106
1107
120253
  if (constant == BitVector(size, (unsigned)0))
1108
  {
1109
27945
    return utils::mkZero(size);
1110
  }
1111
1112
92308
  if (constant != BitVector::mkOnes(size))
1113
  {
1114
31083
    children.push_back(utils::mkConst(constant));
1115
  }
1116
1117
92308
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1118
1119
448406
  for (; it != subterms.end(); ++it)
1120
  {
1121
178135
    if (it->second.pos > 0 && it->second.neg > 0)
1122
    {
1123
      // if we have a and ~a
1124
86
      return utils::mkZero(size);
1125
    }
1126
    else
1127
    {
1128
      // idempotence
1129
178049
      if (it->second.neg > 0)
1130
      {
1131
        // if it only occured negated
1132
60992
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1133
      }
1134
      else
1135
      {
1136
        // if it only occured positive
1137
117057
        children.push_back(it->first);
1138
      }
1139
    }
1140
  }
1141
92222
  if (children.size() == 0)
1142
  {
1143
210
    return utils::mkOnes(size);
1144
  }
1145
1146
92012
  return utils::mkSortedNode(kind::BITVECTOR_AND, children);
1147
}
1148
1149
template<> inline
1150
288538
bool RewriteRule<FlattenAssocCommutNoDuplicates>::applies(TNode node) {
1151
288538
  Kind kind = node.getKind();
1152
288538
  if (kind != kind::BITVECTOR_OR &&
1153
      kind != kind::BITVECTOR_AND)
1154
    return false;
1155
288538
  TNode::iterator child_it = node.begin();
1156
2138838
  for(; child_it != node.end(); ++child_it) {
1157
961440
    if ((*child_it).getKind() == kind) {
1158
36290
      return true;
1159
    }
1160
  }
1161
252248
  return false;
1162
}
1163
1164
template<> inline
1165
18145
Node RewriteRule<FlattenAssocCommutNoDuplicates>::apply(TNode node) {
1166
18145
  Debug("bv-rewrite") << "RewriteRule<FlattenAssocCommut>(" << node << ")" << std::endl;
1167
36290
  std::vector<Node> processingStack;
1168
18145
  processingStack.push_back(node);
1169
36290
  std::unordered_set<TNode> processed;
1170
36290
  std::vector<Node> children;
1171
18145
  Kind kind = node.getKind();
1172
1173
456305
  while (! processingStack.empty()) {
1174
437181
    TNode current = processingStack.back();
1175
219080
    processingStack.pop_back();
1176
219080
    if (processed.count(current))
1177
979
      continue;
1178
1179
218101
    processed.insert(current);
1180
1181
    // flatten expression
1182
218101
    if (current.getKind() == kind) {
1183
241439
      for (unsigned i = 0; i < current.getNumChildren(); ++i) {
1184
200935
        processingStack.push_back(current[i]);
1185
      }
1186
    } else {
1187
177597
      children.push_back(current);
1188
    }
1189
  }
1190
36290
  return utils::mkSortedNode(kind, children);
1191
}
1192
1193
1194
template<> inline
1195
300276
bool RewriteRule<OrSimplify>::applies(TNode node) {
1196
300276
  return (node.getKind() == kind::BITVECTOR_OR);
1197
}
1198
1199
template <>
1200
150136
inline Node RewriteRule<OrSimplify>::apply(TNode node)
1201
{
1202
150136
  Debug("bv-rewrite") << "RewriteRule<OrSimplify>(" << node << ")" << std::endl;
1203
1204
150136
  NodeManager *nm = NodeManager::currentNM();
1205
  // this will remove duplicates
1206
300272
  std::unordered_map<TNode, Count> subterms;
1207
150136
  unsigned size = utils::getSize(node);
1208
300272
  BitVector constant(size, (unsigned)0);
1209
1210
953106
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1211
  {
1212
1605940
    TNode current = node[i];
1213
    // simplify constants
1214
802970
    if (current.getKind() == kind::CONST_BITVECTOR)
1215
    {
1216
292086
      BitVector bv = current.getConst<BitVector>();
1217
146043
      constant = constant | bv;
1218
    }
1219
    else
1220
    {
1221
656927
      if (current.getKind() == kind::BITVECTOR_NOT)
1222
      {
1223
23212
        insert(subterms, current[0], true);
1224
      }
1225
      else
1226
      {
1227
633715
        insert(subterms, current, false);
1228
      }
1229
    }
1230
  }
1231
1232
300272
  std::vector<Node> children;
1233
1234
150136
  if (constant == BitVector::mkOnes(size))
1235
  {
1236
7932
    return utils::mkOnes(size);
1237
  }
1238
1239
142204
  if (constant != BitVector(size, (unsigned)0))
1240
  {
1241
60111
    children.push_back(utils::mkConst(constant));
1242
  }
1243
1244
142204
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1245
1246
1448720
  for (; it != subterms.end(); ++it)
1247
  {
1248
653395
    if (it->second.pos > 0 && it->second.neg > 0)
1249
    {
1250
      // if we have a or ~a
1251
137
      return utils::mkOnes(size);
1252
    }
1253
    else
1254
    {
1255
      // idempotence
1256
653258
      if (it->second.neg > 0)
1257
      {
1258
        // if it only occured negated
1259
22841
        children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1260
      }
1261
      else
1262
      {
1263
        // if it only occured positive
1264
630417
        children.push_back(it->first);
1265
      }
1266
    }
1267
  }
1268
1269
142067
  if (children.size() == 0)
1270
  {
1271
1067
    return utils::mkZero(size);
1272
  }
1273
141000
  return utils::mkSortedNode(kind::BITVECTOR_OR, children);
1274
}
1275
1276
template<> inline
1277
18230
bool RewriteRule<XorSimplify>::applies(TNode node) {
1278
18230
  return (node.getKind() == kind::BITVECTOR_XOR);
1279
}
1280
1281
template <>
1282
9115
inline Node RewriteRule<XorSimplify>::apply(TNode node)
1283
{
1284
18230
  Debug("bv-rewrite") << "RewriteRule<XorSimplify>(" << node << ")"
1285
9115
                      << std::endl;
1286
1287
9115
  NodeManager *nm = NodeManager::currentNM();
1288
18230
  std::unordered_map<TNode, Count> subterms;
1289
9115
  unsigned size = utils::getSize(node);
1290
18230
  BitVector constant;
1291
9115
  bool const_set = false;
1292
1293
27525
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1294
  {
1295
36820
    TNode current = node[i];
1296
    // simplify constants
1297
18410
    if (current.getKind() == kind::CONST_BITVECTOR)
1298
    {
1299
4970
      BitVector bv = current.getConst<BitVector>();
1300
2485
      if (const_set)
1301
      {
1302
467
        constant = constant ^ bv;
1303
      }
1304
      else
1305
      {
1306
2018
        const_set = true;
1307
2018
        constant = bv;
1308
      }
1309
    }
1310
    else
1311
    {
1312
      // collect number of occurances of each term and its negation
1313
15925
      if (current.getKind() == kind::BITVECTOR_NOT)
1314
      {
1315
916
        insert(subterms, current[0], true);
1316
      }
1317
      else
1318
      {
1319
15009
        insert(subterms, current, false);
1320
      }
1321
    }
1322
  }
1323
1324
18230
  std::vector<Node> children;
1325
1326
9115
  std::unordered_map<TNode, Count>::const_iterator it = subterms.begin();
1327
9115
  unsigned true_count = 0;
1328
9115
  bool seen_false = false;
1329
40813
  for (; it != subterms.end(); ++it)
1330
  {
1331
15849
    unsigned pos = it->second.pos;  // number of positive occurances
1332
15849
    unsigned neg = it->second.neg;  // number of negated occurances
1333
1334
    // remove duplicates using the following rules
1335
    // a xor a ==> false
1336
    // false xor false ==> false
1337
15849
    seen_false = seen_false ? seen_false : (pos > 1 || neg > 1);
1338
    // check what did not reduce
1339
15849
    if (pos % 2 && neg % 2)
1340
    {
1341
      // we have a xor ~a ==> true
1342
5
      ++true_count;
1343
    }
1344
15844
    else if (pos % 2)
1345
    {
1346
      // we had a positive occurence left
1347
14862
      children.push_back(it->first);
1348
    }
1349
982
    else if (neg % 2)
1350
    {
1351
      // we had a negative occurence left
1352
911
      children.push_back(nm->mkNode(kind::BITVECTOR_NOT, it->first));
1353
    }
1354
    // otherwise both reduced to false
1355
  }
1356
1357
18230
  std::vector<BitVector> xorConst;
1358
18230
  BitVector true_bv = BitVector::mkOnes(size);
1359
18230
  BitVector false_bv(size, (unsigned)0);
1360
1361
9115
  if (true_count)
1362
  {
1363
    // true xor ... xor true ==> true (odd)
1364
    //                       ==> false (even)
1365
5
    xorConst.push_back(true_count % 2 ? true_bv : false_bv);
1366
  }
1367
9115
  if (seen_false)
1368
  {
1369
71
    xorConst.push_back(false_bv);
1370
  }
1371
9115
  if (const_set)
1372
  {
1373
2018
    xorConst.push_back(constant);
1374
  }
1375
1376
9115
  if (xorConst.size() > 0)
1377
  {
1378
4184
    BitVector result = xorConst[0];
1379
2094
    for (unsigned i = 1; i < xorConst.size(); ++i)
1380
    {
1381
2
      result = result ^ xorConst[i];
1382
    }
1383
2092
    children.push_back(utils::mkConst(result));
1384
  }
1385
1386
9115
  Assert(children.size());
1387
1388
18230
  return utils::mkSortedNode(kind::BITVECTOR_XOR, children);
1389
}
1390
1391
/**
1392
 * BitwiseSlicing
1393
 *
1394
 * (a bvand c) ==> (concat (bvand a[i0:j0] c0) ... (bvand a[in:jn] cn))
1395
 *  where c0,..., cn are maximally continuous substrings of 0 or 1 in the constant c
1396
 *
1397
 * Note: this rule assumes AndSimplify has already been called on the node
1398
 */
1399
template<> inline
1400
151520
bool RewriteRule<BitwiseSlicing>::applies(TNode node) {
1401
421403
  if ((node.getKind() != kind::BITVECTOR_AND &&
1402
190386
      node.getKind() != kind::BITVECTOR_OR &&
1403
556717
      node.getKind() != kind::BITVECTOR_XOR) ||
1404
333174
      utils::getSize(node) == 1)
1405
113151
    return false;
1406
  // find the first constant and return true if it's not only 1..1 or only 0..0
1407
  // (there could be more than one constant)
1408
116371
  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
1409
80965
    if (node[i].getKind() == kind::CONST_BITVECTOR) {
1410
5926
      BitVector constant = node[i].getConst<BitVector>();
1411
      // we do not apply the rule if the constant is all 0s or all 1s
1412
2963
      if (constant == BitVector(utils::getSize(node), 0u)) return false;
1413
1414
5902
      for (unsigned j = 0, csize = constant.getSize(); j < csize; ++j)
1415
      {
1416
5795
        if (!constant.isBitSet(j)) return true;
1417
      }
1418
107
      return false;
1419
    }
1420
  }
1421
35406
  return false;
1422
}
1423
1424
template <>
1425
1428
inline Node RewriteRule<BitwiseSlicing>::apply(TNode node)
1426
{
1427
2856
  Debug("bv-rewrite") << "RewriteRule<BitwiseSlicing>(" << node << ")"
1428
1428
                      << std::endl;
1429
1428
  NodeManager *nm = NodeManager::currentNM();
1430
  // get the constant
1431
1428
  bool found_constant = false;
1432
2856
  TNode constant;
1433
2856
  std::vector<Node> other_children;
1434
4341
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
1435
  {
1436
2913
    if (node[i].getKind() == kind::CONST_BITVECTOR && !found_constant)
1437
    {
1438
1428
      constant = node[i];
1439
1428
      found_constant = true;
1440
    }
1441
    else
1442
    {
1443
1485
      other_children.push_back(node[i]);
1444
    }
1445
  }
1446
1428
  Assert(found_constant && other_children.size() == node.getNumChildren() - 1);
1447
1448
2856
  Node other = utils::mkNaryNode(node.getKind(), other_children);
1449
1450
2856
  BitVector bv_constant = constant.getConst<BitVector>();
1451
2856
  std::vector<Node> concat_children;
1452
1428
  int start = bv_constant.getSize() - 1;
1453
1428
  int end = start;
1454
26107
  for (int i = end - 1; i >= 0; --i)
1455
  {
1456
24679
    if (bv_constant.isBitSet(i + 1) != bv_constant.isBitSet(i))
1457
    {
1458
4948
      Node other_extract = utils::mkExtract(other, end, start);
1459
4948
      Node const_extract = utils::mkExtract(constant, end, start);
1460
      Node bitwise_op =
1461
4948
          nm->mkNode(node.getKind(), const_extract, other_extract);
1462
2474
      concat_children.push_back(bitwise_op);
1463
2474
      start = end = i;
1464
    }
1465
    else
1466
    {
1467
22205
      start--;
1468
    }
1469
24679
    if (i == 0)
1470
    {
1471
2856
      Node other_extract = utils::mkExtract(other, end, 0);
1472
2856
      Node const_extract = utils::mkExtract(constant, end, 0);
1473
      Node bitwise_op =
1474
2856
          nm->mkNode(node.getKind(), const_extract, other_extract);
1475
1428
      concat_children.push_back(bitwise_op);
1476
    }
1477
  }
1478
1428
  Node result = utils::mkConcat(concat_children);
1479
1428
  Debug("bv-rewrite") << "    =>" << result << std::endl;
1480
2856
  return result;
1481
}
1482
1483
template <>
1484
54
inline bool RewriteRule<NormalizeEqAddNeg>::applies(TNode node)
1485
{
1486
54
  return node.getKind() == kind::EQUAL
1487
178
         && (node[0].getKind() == kind::BITVECTOR_ADD
1488
120
             || node[1].getKind() == kind::BITVECTOR_ADD);
1489
}
1490
1491
template <>
1492
8
inline Node RewriteRule<NormalizeEqAddNeg>::apply(TNode node)
1493
{
1494
16
  Debug("bv-rewrite") << "RewriteRule<NormalizeEqAddNeg>(" << node << ")"
1495
8
                      << std::endl;
1496
1497
16
  NodeBuilder nb_lhs(kind::BITVECTOR_ADD);
1498
16
  NodeBuilder nb_rhs(kind::BITVECTOR_ADD);
1499
8
  NodeManager *nm = NodeManager::currentNM();
1500
1501
8
  if (node[0].getKind() == kind::BITVECTOR_ADD)
1502
  {
1503
24
    for (const TNode &n : node[0])
1504
    {
1505
16
      if (n.getKind() == kind::BITVECTOR_NEG)
1506
        nb_rhs << n[0];
1507
      else
1508
16
        nb_lhs << n;
1509
    }
1510
  }
1511
  else
1512
  {
1513
    nb_lhs << node[0];
1514
  }
1515
1516
8
  if (node[1].getKind() == kind::BITVECTOR_ADD)
1517
  {
1518
    for (const TNode &n : node[1])
1519
    {
1520
      if (n.getKind() == kind::BITVECTOR_NEG)
1521
        nb_lhs << n[0];
1522
      else
1523
        nb_rhs << n;
1524
    }
1525
  }
1526
  else
1527
  {
1528
8
    nb_rhs << node[1];
1529
  }
1530
1531
16
  Node zero = utils::mkZero(utils::getSize(node[0]));
1532
1533
16
  Node lhs, rhs;
1534
8
  if (nb_lhs.getNumChildren() == 0)
1535
  {
1536
    lhs = zero;
1537
  }
1538
8
  else if (nb_lhs.getNumChildren() == 1)
1539
  {
1540
    lhs = nb_lhs[0];
1541
  }
1542
  else
1543
  {
1544
8
    lhs = nb_lhs.constructNode();
1545
  }
1546
8
  if (nb_rhs.getNumChildren() == 0)
1547
  {
1548
    rhs = zero;
1549
  }
1550
8
  else if (nb_rhs.getNumChildren() == 1)
1551
  {
1552
8
    rhs = nb_rhs[0];
1553
  }
1554
  else
1555
  {
1556
    rhs = nb_rhs.constructNode();
1557
  }
1558
16
  return nm->mkNode(node.getKind(), lhs, rhs);
1559
}
1560
1561
// template<> inline
1562
// bool RewriteRule<>::applies(TNode node) {
1563
//   return (node.getKind() == kind::BITVECTOR_CONCAT);
1564
// }
1565
1566
// template<> inline
1567
// Node RewriteRule<>::apply(TNode node) {
1568
//   Debug("bv-rewrite") << "RewriteRule<>(" << node << ")" << std::endl;
1569
//   return resultNode;
1570
// }
1571
1572
1573
1574
}
1575
}
1576
}  // namespace cvc5