GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv_rewrite_rules_core.h Lines: 144 144 100.0 %
Date: 2021-09-10 Branches: 265 460 57.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Dejan Jovanovic, Liana Hadarean, 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 "theory/bv/theory_bv_rewrite_rules.h"
24
#include "theory/bv/theory_bv_utils.h"
25
26
namespace cvc5 {
27
namespace theory {
28
namespace bv {
29
30
/* -------------------------------------------------------------------------- */
31
32
template<> inline
33
336146
bool RewriteRule<ConcatFlatten>::applies(TNode node) {
34
336146
  return (node.getKind() == kind::BITVECTOR_CONCAT);
35
}
36
37
template<> inline
38
168073
Node RewriteRule<ConcatFlatten>::apply(TNode node) {
39
168073
  Debug("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << node << ")" << std::endl;
40
336146
  NodeBuilder result(kind::BITVECTOR_CONCAT);
41
336146
  std::vector<Node> processing_stack;
42
168073
  processing_stack.push_back(node);
43
1619289
  while (!processing_stack.empty()) {
44
1451216
    Node current = processing_stack.back();
45
725608
    processing_stack.pop_back();
46
725608
    if (current.getKind() == kind::BITVECTOR_CONCAT) {
47
732173
      for (int i = current.getNumChildren() - 1; i >= 0; i--)
48
557535
        processing_stack.push_back(current[i]);
49
    } else {
50
550970
      result << current;
51
    }
52
  }
53
168073
  Node resultNode = result;
54
168073
  Debug("bv-rewrite") << "RewriteRule<ConcatFlatten>(" << resultNode << ")" << std::endl;
55
336146
  return resultNode;
56
}
57
58
/* -------------------------------------------------------------------------- */
59
60
template<> inline
61
336146
bool RewriteRule<ConcatExtractMerge>::applies(TNode node) {
62
336146
  return (node.getKind() == kind::BITVECTOR_CONCAT);
63
}
64
65
template<> inline
66
168073
Node RewriteRule<ConcatExtractMerge>::apply(TNode node) {
67
68
168073
  Debug("bv-rewrite") << "RewriteRule<ConcatExtractMerge>(" << node << ")" << std::endl;
69
70
336146
  std::vector<Node> mergedExtracts;
71
72
336146
  Node current = node[0];
73
168073
  bool mergeStarted = false;
74
168073
  unsigned currentHigh = 0;
75
168073
  unsigned currentLow  = 0;
76
77
550970
  for(size_t i = 1, end = node.getNumChildren(); i < end; ++ i) {
78
    // The next candidate for merging
79
454744
    Node next = node[i];
80
    // If the current is not an extract we just go to the next
81
693947
    if (current.getKind() != kind::BITVECTOR_EXTRACT) {
82
311050
      mergedExtracts.push_back(current);
83
311050
      current = next;
84
311050
      continue;
85
    }
86
    // If it is an extract and the first one, get the extract parameters
87
71847
    else if (!mergeStarted) {
88
71814
      currentHigh = utils::getExtractHigh(current);
89
71814
      currentLow = utils::getExtractLow(current);
90
    }
91
92
    // If the next one can be merged, try to merge
93
71847
    bool merged = false;
94
71847
    if (next.getKind() == kind::BITVECTOR_EXTRACT && current[0] == next[0]) {
95
      // x[i : j] @ x[j - 1 : k] -> c x[i : k]
96
25413
      unsigned nextHigh = utils::getExtractHigh(next);
97
25413
      unsigned nextLow  = utils::getExtractLow(next);
98
25413
      if(nextHigh + 1 == currentLow) {
99
116
        currentLow = nextLow;
100
116
        mergeStarted = true;
101
116
        merged = true;
102
      }
103
    }
104
    // If we haven't merged anything, add the previous merge and continue with the next
105
71847
    if (!merged) {
106
71731
      if (!mergeStarted) mergedExtracts.push_back(current);
107
9
      else mergedExtracts.push_back(utils::mkExtract(current[0], currentHigh, currentLow));
108
71731
      current = next;
109
71731
      mergeStarted = false;
110
    }
111
  }
112
113
  // Add the last child
114
168073
  if (!mergeStarted) mergedExtracts.push_back(current);
115
83
  else mergedExtracts.push_back(utils::mkExtract(current[0], currentHigh, currentLow));
116
117
  // Return the result
118
336146
  return utils::mkConcat(mergedExtracts);
119
}
120
121
/* -------------------------------------------------------------------------- */
122
123
template<> inline
124
336089
bool RewriteRule<ConcatConstantMerge>::applies(TNode node) {
125
336089
  return node.getKind() == kind::BITVECTOR_CONCAT;
126
}
127
128
template<> inline
129
168016
Node RewriteRule<ConcatConstantMerge>::apply(TNode node) {
130
131
168016
  Debug("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ")" << std::endl;
132
133
336032
  std::vector<Node> mergedConstants;
134
683558
  for (unsigned i = 0, end = node.getNumChildren(); i < end;) {
135
515542
    if (node[i].getKind() != kind::CONST_BITVECTOR) {
136
      // If not a constant, just add it
137
375154
      mergedConstants.push_back(node[i]);
138
375154
      ++i;
139
    } else {
140
      // Find the longest sequence of constants
141
140388
      unsigned j = i + 1;
142
210898
      while (j < end) {
143
116600
        if (node[j].getKind() != kind::CONST_BITVECTOR) {
144
81345
          break;
145
        } else {
146
35255
          ++ j;
147
        }
148
      }
149
      // Append all the constants
150
280776
      BitVector current = node[i].getConst<BitVector>();
151
175643
      for (unsigned k = i + 1; k < j; ++ k) {
152
35255
        current = current.concat(node[k].getConst<BitVector>());
153
      }
154
      // Add the new merged constant
155
140388
      mergedConstants.push_back(utils::mkConst(current));
156
140388
      i = j;
157
    }
158
  }
159
160
168016
  Debug("bv-rewrite") << "RewriteRule<ConcatConstantMerge>(" << node << ") => " << utils::mkConcat(mergedConstants) << std::endl;
161
162
336032
  return utils::mkConcat(mergedConstants);
163
}
164
165
/* -------------------------------------------------------------------------- */
166
167
template<> inline
168
623647
bool RewriteRule<ExtractWhole>::applies(TNode node) {
169
623647
  if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
170
182084
  unsigned length = utils::getSize(node[0]);
171
182084
  unsigned extractHigh = utils::getExtractHigh(node);
172
182084
  if (extractHigh != length - 1) return false;
173
88324
  unsigned extractLow  = utils::getExtractLow(node);
174
88324
  if (extractLow != 0) return false;
175
19843
  return true;
176
}
177
178
template<> inline
179
15172
Node RewriteRule<ExtractWhole>::apply(TNode node) {
180
15172
  Debug("bv-rewrite") << "RewriteRule<ExtractWhole>(" << node << ")" << std::endl;
181
15172
  return node[0];
182
}
183
184
/* -------------------------------------------------------------------------- */
185
186
template<> inline
187
127943
bool RewriteRule<ExtractConstant>::applies(TNode node) {
188
127943
  if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
189
127943
  if (node[0].getKind() != kind::CONST_BITVECTOR) return false;
190
49132
  return true;
191
}
192
193
template<> inline
194
24566
Node RewriteRule<ExtractConstant>::apply(TNode node) {
195
24566
  Debug("bv-rewrite") << "RewriteRule<ExtractConstant>(" << node << ")" << std::endl;
196
49132
  Node child = node[0];
197
49132
  BitVector childValue = child.getConst<BitVector>();
198
49132
  return utils::mkConst(childValue.extract(utils::getExtractHigh(node), utils::getExtractLow(node)));
199
}
200
201
/* -------------------------------------------------------------------------- */
202
203
template<> inline
204
126084
bool RewriteRule<ExtractConcat>::applies(TNode node) {
205
  //Debug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
206
126084
  if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
207
126084
  if (node[0].getKind() != kind::BITVECTOR_CONCAT) return false;
208
20502
  return true;
209
}
210
211
template<> inline
212
10251
Node RewriteRule<ExtractConcat>::apply(TNode node) {
213
10251
  Debug("bv-rewrite") << "RewriteRule<ExtractConcat>(" << node << ")" << std::endl;
214
10251
  int extract_high = utils::getExtractHigh(node);
215
10251
  int extract_low = utils::getExtractLow(node);
216
217
20502
  std::vector<Node> resultChildren;
218
219
20502
  Node concat = node[0];
220
33559
  for (int i = concat.getNumChildren() - 1; i >= 0 && extract_high >= 0; i--) {
221
46616
    Node concatChild = concat[i];
222
23308
    int concatChildSize = utils::getSize(concatChild);
223
23308
    if (extract_low < concatChildSize) {
224
19919
      int extract_start = extract_low < 0 ? 0 : extract_low;
225
19919
      int extract_end = extract_high < concatChildSize ? extract_high : concatChildSize - 1;
226
19919
      resultChildren.push_back(utils::mkExtract(concatChild, extract_end, extract_start));
227
    }
228
23308
    extract_low -= concatChildSize;
229
23308
    extract_high -= concatChildSize;
230
  }
231
232
10251
  std::reverse(resultChildren.begin(), resultChildren.end());
233
234
20502
  return utils::mkConcat(resultChildren);
235
}
236
237
/* -------------------------------------------------------------------------- */
238
239
template<> inline
240
105503
bool RewriteRule<ExtractExtract>::applies(TNode node) {
241
105503
  if (node.getKind() != kind::BITVECTOR_EXTRACT) return false;
242
80937
  if (node[0].getKind() != kind::BITVECTOR_EXTRACT) return false;
243
4252
  return true;
244
}
245
246
template<> inline
247
2126
Node RewriteRule<ExtractExtract>::apply(TNode node) {
248
2126
  Debug("bv-rewrite") << "RewriteRule<ExtractExtract>(" << node << ")" << std::endl;
249
250
  // x[i:j][k:l] ~>  x[k+j:l+j]
251
4252
  Node child = node[0];
252
2126
  unsigned k = utils::getExtractHigh(node);
253
2126
  unsigned l = utils::getExtractLow(node);
254
2126
  unsigned j = utils::getExtractLow(child);
255
256
2126
  Node result = utils::mkExtract(child[0], k + j, l + j);
257
4252
  return result;
258
}
259
260
/* -------------------------------------------------------------------------- */
261
262
template<> inline
263
418895
bool RewriteRule<FailEq>::applies(TNode node) {
264
  //Debug("bv-rewrite") << "RewriteRule<FailEq>(" << node << ")" << std::endl;
265
418895
  if (node.getKind() != kind::EQUAL) return false;
266
418895
  if (node[0].getKind() != kind::CONST_BITVECTOR) return false;
267
69180
  if (node[1].getKind() != kind::CONST_BITVECTOR) return false;
268
50853
  return node[0] != node[1];
269
}
270
271
template<> inline
272
24230
Node RewriteRule<FailEq>::apply(TNode node) {
273
24230
  return utils::mkFalse();
274
}
275
276
/* -------------------------------------------------------------------------- */
277
278
template<> inline
279
401443
bool RewriteRule<SimplifyEq>::applies(TNode node) {
280
401443
  if (node.getKind() != kind::EQUAL) return false;
281
377213
  return node[0] == node[1];
282
}
283
284
template<> inline
285
6778
Node RewriteRule<SimplifyEq>::apply(TNode node) {
286
6778
  Debug("bv-rewrite") << "RewriteRule<SimplifyEq>(" << node << ")" << std::endl;
287
6778
  return utils::mkTrue();
288
}
289
290
/* -------------------------------------------------------------------------- */
291
292
template<> inline
293
436868
bool RewriteRule<ReflexivityEq>::applies(TNode node) {
294
436868
  return (node.getKind() == kind::EQUAL && node[0] < node[1]);
295
}
296
297
template<> inline
298
42203
Node RewriteRule<ReflexivityEq>::apply(TNode node) {
299
42203
  Debug("bv-rewrite") << "RewriteRule<ReflexivityEq>(" << node << ")" << std::endl;
300
42203
  Node res = node[1].eqNode(node[0]);
301
42203
  return res;
302
}
303
304
}
305
}
306
}  // namespace cvc5