GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/theory_bv.cpp Lines: 183 185 98.9 %
Date: 2021-09-15 Branches: 304 617 49.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Mathias Preiner, Andrew Reynolds, Haniel Barbosa
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
 * Theory of bit-vectors.
14
 */
15
16
#include "theory/bv/theory_bv.h"
17
18
#include "options/bv_options.h"
19
#include "options/smt_options.h"
20
#include "proof/proof_checker.h"
21
#include "smt/smt_statistics_registry.h"
22
#include "theory/bv/bv_solver_bitblast.h"
23
#include "theory/bv/bv_solver_bitblast_internal.h"
24
#include "theory/bv/bv_solver_layered.h"
25
#include "theory/bv/theory_bv_utils.h"
26
#include "theory/ee_setup_info.h"
27
#include "theory/trust_substitutions.h"
28
29
namespace cvc5 {
30
namespace theory {
31
namespace bv {
32
33
9942
TheoryBV::TheoryBV(Env& env,
34
                   OutputChannel& out,
35
                   Valuation valuation,
36
9942
                   std::string name)
37
    : Theory(THEORY_BV, env, out, valuation, name),
38
      d_internal(nullptr),
39
      d_rewriter(),
40
      d_state(env, valuation),
41
      d_im(env, *this, d_state, nullptr, "theory::bv::"),
42
      d_notify(d_im),
43
      d_invalidateModelCache(context(), true),
44
9942
      d_stats(statisticsRegistry(), "theory::bv::")
45
{
46
9942
  switch (options().bv.bvSolver)
47
  {
48
6160
    case options::BVSolver::BITBLAST:
49
6160
      d_internal.reset(new BVSolverBitblast(env, &d_state, d_im, d_pnm));
50
6160
      break;
51
52
4
    case options::BVSolver::LAYERED:
53
12
      d_internal.reset(new BVSolverLayered(
54
8
          env, *this, context(), userContext(), d_pnm, name));
55
4
      break;
56
57
3778
    default:
58
3778
      AlwaysAssert(options().bv.bvSolver == options::BVSolver::BITBLAST_INTERNAL);
59
7556
      d_internal.reset(
60
3778
          new BVSolverBitblastInternal(d_env, &d_state, d_im, d_pnm));
61
  }
62
9942
  d_theoryState = &d_state;
63
9942
  d_inferManager = &d_im;
64
9942
}
65
66
19878
TheoryBV::~TheoryBV() {}
67
68
9942
TheoryRewriter* TheoryBV::getTheoryRewriter() { return &d_rewriter; }
69
70
3796
ProofRuleChecker* TheoryBV::getProofChecker()
71
{
72
3796
  if (options().bv.bvSolver == options::BVSolver::BITBLAST_INTERNAL)
73
  {
74
3764
    return static_cast<BVSolverBitblastInternal*>(d_internal.get())
75
3764
        ->getProofChecker();
76
  }
77
32
  return nullptr;
78
}
79
80
9942
bool TheoryBV::needsEqualityEngine(EeSetupInfo& esi)
81
{
82
9942
  bool need_ee = d_internal->needsEqualityEngine(esi);
83
84
  /* Set up default notify class for equality engine. */
85
9942
  if (need_ee && esi.d_notify == nullptr)
86
  {
87
9938
    esi.d_notify = &d_notify;
88
9938
    esi.d_name = "theory::bv::ee";
89
  }
90
91
9942
  return need_ee;
92
}
93
94
9942
void TheoryBV::finishInit()
95
{
96
  // these kinds are semi-evaluated in getModelValue (applications of this
97
  // kind are treated as variables)
98
9942
  getValuation().setSemiEvaluatedKind(kind::BITVECTOR_ACKERMANNIZE_UDIV);
99
9942
  getValuation().setSemiEvaluatedKind(kind::BITVECTOR_ACKERMANNIZE_UREM);
100
9942
  d_internal->finishInit();
101
102
9942
  eq::EqualityEngine* ee = getEqualityEngine();
103
9942
  if (ee)
104
  {
105
    // The kinds we are treating as function application in congruence
106
9940
    ee->addFunctionKind(kind::BITVECTOR_CONCAT, true);
107
    //    ee->addFunctionKind(kind::BITVECTOR_AND);
108
    //    ee->addFunctionKind(kind::BITVECTOR_OR);
109
    //    ee->addFunctionKind(kind::BITVECTOR_XOR);
110
    //    ee->addFunctionKind(kind::BITVECTOR_NOT);
111
    //    ee->addFunctionKind(kind::BITVECTOR_NAND);
112
    //    ee->addFunctionKind(kind::BITVECTOR_NOR);
113
    //    ee->addFunctionKind(kind::BITVECTOR_XNOR);
114
    //    ee->addFunctionKind(kind::BITVECTOR_COMP);
115
9940
    ee->addFunctionKind(kind::BITVECTOR_MULT, true);
116
9940
    ee->addFunctionKind(kind::BITVECTOR_ADD, true);
117
9940
    ee->addFunctionKind(kind::BITVECTOR_EXTRACT, true);
118
    //    ee->addFunctionKind(kind::BITVECTOR_SUB);
119
    //    ee->addFunctionKind(kind::BITVECTOR_NEG);
120
    //    ee->addFunctionKind(kind::BITVECTOR_UDIV);
121
    //    ee->addFunctionKind(kind::BITVECTOR_UREM);
122
    //    ee->addFunctionKind(kind::BITVECTOR_SDIV);
123
    //    ee->addFunctionKind(kind::BITVECTOR_SREM);
124
    //    ee->addFunctionKind(kind::BITVECTOR_SMOD);
125
    //    ee->addFunctionKind(kind::BITVECTOR_SHL);
126
    //    ee->addFunctionKind(kind::BITVECTOR_LSHR);
127
    //    ee->addFunctionKind(kind::BITVECTOR_ASHR);
128
    //    ee->addFunctionKind(kind::BITVECTOR_ULT);
129
    //    ee->addFunctionKind(kind::BITVECTOR_ULE);
130
    //    ee->addFunctionKind(kind::BITVECTOR_UGT);
131
    //    ee->addFunctionKind(kind::BITVECTOR_UGE);
132
    //    ee->addFunctionKind(kind::BITVECTOR_SLT);
133
    //    ee->addFunctionKind(kind::BITVECTOR_SLE);
134
    //    ee->addFunctionKind(kind::BITVECTOR_SGT);
135
    //    ee->addFunctionKind(kind::BITVECTOR_SGE);
136
9940
    ee->addFunctionKind(kind::BITVECTOR_TO_NAT);
137
9940
    ee->addFunctionKind(kind::INT_TO_BITVECTOR);
138
  }
139
9942
}
140
141
326831
void TheoryBV::preRegisterTerm(TNode node)
142
{
143
326831
  d_internal->preRegisterTerm(node);
144
145
326831
  eq::EqualityEngine* ee = getEqualityEngine();
146
326831
  if (ee)
147
  {
148
326831
    if (node.getKind() == kind::EQUAL)
149
    {
150
51149
      ee->addTriggerPredicate(node);
151
    }
152
    else
153
    {
154
275682
      ee->addTerm(node);
155
    }
156
  }
157
326831
}
158
159
933031
bool TheoryBV::preCheck(Effort e) { return d_internal->preCheck(e); }
160
161
933031
void TheoryBV::postCheck(Effort e)
162
{
163
933031
  d_invalidateModelCache = true;
164
933031
  d_internal->postCheck(e);
165
933031
}
166
167
2694290
bool TheoryBV::preNotifyFact(
168
    TNode atom, bool pol, TNode fact, bool isPrereg, bool isInternal)
169
{
170
2694290
  return d_internal->preNotifyFact(atom, pol, fact, isPrereg, isInternal);
171
}
172
173
2694290
void TheoryBV::notifyFact(TNode atom, bool pol, TNode fact, bool isInternal)
174
{
175
2694290
  d_internal->notifyFact(atom, pol, fact, isInternal);
176
2694290
}
177
178
8912
bool TheoryBV::needsCheckLastEffort()
179
{
180
8912
  return d_internal->needsCheckLastEffort();
181
}
182
183
7570
void TheoryBV::computeRelevantTerms(std::set<Node>& termSet)
184
{
185
7570
  return d_internal->computeRelevantTerms(termSet);
186
}
187
188
7570
bool TheoryBV::collectModelValues(TheoryModel* m, const std::set<Node>& termSet)
189
{
190
7570
  return d_internal->collectModelValues(m, termSet);
191
}
192
193
1495088
void TheoryBV::propagate(Effort e) { return d_internal->propagate(e); }
194
195
4499
Theory::PPAssertStatus TheoryBV::ppAssert(
196
    TrustNode tin, TrustSubstitutionMap& outSubstitutions)
197
{
198
8998
  TNode in = tin.getNode();
199
4499
  Kind k = in.getKind();
200
4499
  if (k == kind::EQUAL)
201
  {
202
    // Substitute variables
203
1273
    if (in[0].isVar() && isLegalElimination(in[0], in[1]))
204
    {
205
275
      ++d_stats.d_solveSubstitutions;
206
275
      outSubstitutions.addSubstitutionSolved(in[0], in[1], tin);
207
1107
      return Theory::PP_ASSERT_STATUS_SOLVED;
208
    }
209
998
    if (in[1].isVar() && isLegalElimination(in[1], in[0]))
210
    {
211
529
      ++d_stats.d_solveSubstitutions;
212
529
      outSubstitutions.addSubstitutionSolved(in[1], in[0], tin);
213
529
      return Theory::PP_ASSERT_STATUS_SOLVED;
214
    }
215
    /**
216
     * Eliminate extract over bit-vector variables.
217
     *
218
     * Given x[h:l] = c, where c is a constant and x is a variable.
219
     *
220
     * We rewrite to:
221
     *
222
     * x = sk1::c       if l == 0, where bw(sk1) = bw(x)-1-h
223
     * x = c::sk2       if h == bw(x)-1, where bw(sk2) = l
224
     * x = sk1::c::sk2  otherwise, where bw(sk1) = bw(x)-1-h and bw(sk2) = l
225
     */
226
910
    Node node = rewrite(in);
227
1466
    if ((node[0].getKind() == kind::BITVECTOR_EXTRACT && node[1].isConst())
228
2367
        || (node[1].getKind() == kind::BITVECTOR_EXTRACT
229
536
            && node[0].isConst()))
230
    {
231
68
      Node extract = node[0].isConst() ? node[1] : node[0];
232
48
      if (extract[0].isVar())
233
      {
234
28
        Node c = node[0].isConst() ? node[0] : node[1];
235
236
28
        uint32_t high = utils::getExtractHigh(extract);
237
28
        uint32_t low = utils::getExtractLow(extract);
238
28
        uint32_t var_bw = utils::getSize(extract[0]);
239
28
        std::vector<Node> children;
240
241
        // create sk1 with size bw(x)-1-h
242
28
        if (low == 0 || high != var_bw - 1)
243
        {
244
24
          Assert(high != var_bw - 1);
245
24
          uint32_t skolem_size = var_bw - high - 1;
246
48
          Node skolem = utils::mkVar(skolem_size);
247
24
          children.push_back(skolem);
248
        }
249
250
28
        children.push_back(c);
251
252
        // create sk2 with size l
253
28
        if (high == var_bw - 1 || low != 0)
254
        {
255
6
          Assert(low != 0);
256
6
          uint32_t skolem_size = low;
257
12
          Node skolem = utils::mkVar(skolem_size);
258
6
          children.push_back(skolem);
259
        }
260
261
28
        Node concat = utils::mkConcat(children);
262
28
        Assert(utils::getSize(concat) == utils::getSize(extract[0]));
263
28
        if (isLegalElimination(extract[0], concat))
264
        {
265
28
          outSubstitutions.addSubstitutionSolved(extract[0], concat, tin);
266
28
          return Theory::PP_ASSERT_STATUS_SOLVED;
267
        }
268
      }
269
    }
270
  }
271
3667
  return Theory::PP_ASSERT_STATUS_UNSOLVED;
272
}
273
274
408746
TrustNode TheoryBV::ppRewrite(TNode t, std::vector<SkolemLemma>& lems)
275
{
276
  // first, see if we need to expand definitions
277
817492
  TrustNode texp = d_rewriter.expandDefinition(t);
278
408746
  if (!texp.isNull())
279
  {
280
96
    return texp;
281
  }
282
408650
  return d_internal->ppRewrite(t);
283
}
284
285
15264
void TheoryBV::presolve() { d_internal->presolve(); }
286
287
28965
EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
288
{
289
28965
  EqualityStatus status = d_internal->getEqualityStatus(a, b);
290
291
28965
  if (status == EqualityStatus::EQUALITY_UNKNOWN)
292
  {
293
57930
    Node value_a = getValue(a);
294
57930
    Node value_b = getValue(b);
295
296
28965
    if (value_a.isNull() || value_b.isNull())
297
    {
298
      return status;
299
    }
300
301
28965
    if (value_a == value_b)
302
    {
303
4172
      Debug("theory-bv") << EQUALITY_TRUE_IN_MODEL << std::endl;
304
4172
      return EQUALITY_TRUE_IN_MODEL;
305
    }
306
24793
    Debug("theory-bv") << EQUALITY_FALSE_IN_MODEL << std::endl;
307
24793
    return EQUALITY_FALSE_IN_MODEL;
308
  }
309
  return status;
310
}
311
312
4990
TrustNode TheoryBV::explain(TNode node) { return d_internal->explain(node); }
313
314
92195
void TheoryBV::notifySharedTerm(TNode t)
315
{
316
92195
  d_internal->notifySharedTerm(t);
317
92195
}
318
319
105462
void TheoryBV::ppStaticLearn(TNode in, NodeBuilder& learned)
320
{
321
105462
  d_internal->ppStaticLearn(in, learned);
322
105462
}
323
324
4
bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions,
325
                                std::vector<Node>& new_assertions)
326
{
327
4
  return d_internal->applyAbstraction(assertions, new_assertions);
328
}
329
330
57930
Node TheoryBV::getValue(TNode node)
331
{
332
57930
  if (d_invalidateModelCache.get())
333
  {
334
248
    d_modelCache.clear();
335
  }
336
57930
  d_invalidateModelCache.set(false);
337
338
115860
  std::vector<TNode> visit;
339
340
115860
  TNode cur;
341
57930
  visit.push_back(node);
342
561
  do
343
  {
344
58491
    cur = visit.back();
345
58491
    visit.pop_back();
346
347
58491
    auto it = d_modelCache.find(cur);
348
58491
    if (it != d_modelCache.end() && !it->second.isNull())
349
    {
350
115107
      continue;
351
    }
352
353
1722
    if (cur.isConst())
354
    {
355
281
      d_modelCache[cur] = cur;
356
281
      continue;
357
    }
358
359
1594
    Node value = d_internal->getValue(cur, false);
360
1639
    if (value.isConst())
361
    {
362
479
      d_modelCache[cur] = value;
363
479
      continue;
364
    }
365
366
928
    if (Theory::isLeafOf(cur, theory::THEORY_BV))
367
    {
368
247
      value = d_internal->getValue(cur, true);
369
247
      d_modelCache[cur] = value;
370
247
      continue;
371
    }
372
373
434
    if (it == d_modelCache.end())
374
    {
375
217
      visit.push_back(cur);
376
217
      d_modelCache.emplace(cur, Node());
377
217
      visit.insert(visit.end(), cur.begin(), cur.end());
378
    }
379
217
    else if (it->second.isNull())
380
    {
381
434
      NodeBuilder nb(cur.getKind());
382
217
      if (cur.getMetaKind() == kind::metakind::PARAMETERIZED)
383
      {
384
29
        nb << cur.getOperator();
385
      }
386
387
217
      std::unordered_map<Node, Node>::iterator iit;
388
561
      for (const TNode& child : cur)
389
      {
390
344
        iit = d_modelCache.find(child);
391
344
        Assert(iit != d_modelCache.end());
392
344
        Assert(iit->second.isConst());
393
344
        nb << iit->second;
394
      }
395
217
      it->second = rewrite(nb.constructNode());
396
    }
397
58491
  } while (!visit.empty());
398
399
57930
  auto it = d_modelCache.find(node);
400
57930
  Assert(it != d_modelCache.end());
401
115860
  return it->second;
402
}
403
404
9942
TheoryBV::Statistics::Statistics(StatisticsRegistry& reg,
405
9942
                                 const std::string& name)
406
9942
    : d_solveSubstitutions(reg.registerInt(name + "NumSolveSubstitutions"))
407
{
408
9942
}
409
410
}  // namespace bv
411
}  // namespace theory
412
29577
}  // namespace cvc5