• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SRI-CSL / yices2 / 4691668724

pending completion
4691668724

push

github

GitHub
Update bool_plugin.c

1 of 1 new or added line in 1 file covered. (100.0%)

76432 of 119008 relevant lines covered (64.22%)

950047.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.7
/src/solvers/bv/bvsolver.c
1
/*
2
 * This file is part of the Yices SMT Solver.
3
 * Copyright (C) 2017 SRI International.
4
 *
5
 * Yices is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * Yices is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
/*
20
 * BIT-VECTOR SOLVER (BASELINE)
21
 */
22

23
#include <assert.h>
24

25
#include "solvers/bv/bv64_intervals.h"
26
#include "solvers/bv/bvsolver.h"
27
#include "terms/bv64_constants.h"
28
#include "utils/hash_functions.h"
29
#include "utils/index_vectors.h"
30
#include "utils/int_partitions.h"
31
#include "utils/int_powers.h"
32
#include "utils/memalloc.h"
33
#include "utils/refcount_int_arrays.h"
34

35

36
#define TRACE 0
37

38
#define DUMP 0
39

40
#if TRACE || DUMP
41

42
#include <stdio.h>
43
#include <inttypes.h>
44

45
#include "api/yices_globals.h"
46
#include "io/term_printer.h"
47
#include "solvers/bv/bvsolver_printer.h"
48
#include "solvers/cdcl/gates_printer.h"
49
#include "solvers/cdcl/smt_core_printer.h"
50
#include "solvers/egraph/egraph_printer.h"
51

52

53
static void print_solver_state(FILE *f, bv_solver_t *solver) {  
54
  fprintf(f, "\n--- Terms ---\n");
55
  print_term_table(f, __yices_globals.terms);
56
  fprintf(f, "\n--- Bitvector Partition ---\n");
57
  print_bv_solver_partition(f, solver);
58
  fprintf(f, "\n--- Bitvector Variables ---\n");
59
  print_bv_solver_vars(f, solver);
60
  fprintf(f, "\n--- Bitvector Atoms ---\n");
61
  print_bv_solver_atoms(f, solver);
62
  fprintf(f, "\ntotal: %"PRIu32" atoms\n", solver->atbl.natoms);
63
  fprintf(f, "\n--- Bitvector Bounds ---\n");
64
  print_bv_solver_bounds(f, solver);
65
  fprintf(f, "\n--- DAG ---\n");
66
  print_bv_solver_dag(f, solver);
67
  if (solver->blaster != NULL) {
68
    fprintf(f, "\n--- Gates ---\n");
69
    print_gate_table(f, solver->blaster->htbl);
70
  }
71
  fprintf(f, "\n--- Clauses ---\n");
72
  print_clauses(f, solver->core);
73
  fprintf(f, "\n");
74
}
75

76

77
#endif
78

79

80
#if DUMP
81

82
static void bv_solver_dump_state(bv_solver_t *solver, const char *filename);
83

84
#endif
85

86

87

88
/*****************
89
 *  BOUND QUEUE  *
90
 ****************/
91

92
/*
93
 * Initialize the queue: initial size = 0
94
 */
95
static void init_bv_bound_queue(bv_bound_queue_t *queue) {
11,476✔
96
  queue->data = NULL;
11,476✔
97
  queue->top = 0;
11,476✔
98
  queue->size = 0;
11,476✔
99
  queue->bound = NULL;
11,476✔
100
  queue->bsize = 0;
11,476✔
101
}
11,476✔
102

103

104
/*
105
 * Allocate the data array of make it 50% larger
106
 */
107
static void bv_bound_queue_extend(bv_bound_queue_t *queue) {
961✔
108
  uint32_t n;
109

110
  n = queue->size;
961✔
111
  if (n == 0) {
961✔
112
    n = DEF_BV_BOUND_QUEUE_SIZE;
950✔
113
    assert(n <= MAX_BV_BOUND_QUEUE_SIZE);
114
    queue->data = (bv_bound_t *) safe_malloc(n * sizeof(bv_bound_t));
950✔
115
    queue->size = n;
950✔
116

117
  } else {
118
    n += (n >> 1); // 50% larger
11✔
119
    assert(n > queue->size);
120
    if (n > MAX_BV_BOUND_QUEUE_SIZE) {
11✔
121
      out_of_memory();
×
122
    }
123
    queue->data = (bv_bound_t *) safe_realloc(queue->data, n * sizeof(bv_bound_t));
11✔
124
    queue->size = n;
11✔
125
  }
126
}
961✔
127

128

129
/*
130
 * Make the bound array large enough to store bound[x]
131
 * - x must be a variable index (between 0 and MAX_BV_BOUND_NUM_LISTS)
132
 * - this should be called when x >= queue->bsize
133
 */
134
static void bv_bound_queue_resize(bv_bound_queue_t *queue, thvar_t x) {
964✔
135
  uint32_t i, n;
136
  int32_t *tmp;
137

138
  assert(x >= queue->bsize);
139

140
  n = queue->bsize;
964✔
141
  if (n == 0) {
964✔
142
    n = DEF_BV_BOUND_NUM_LISTS;
950✔
143
  } else {
144
    n += (n >> 1);
14✔
145
    assert(n > queue->bsize);
146
  }
147

148
  if (n <= (uint32_t) x) {
964✔
149
    n = x + 1;
6✔
150
  }
151

152
  if (n > MAX_BV_BOUND_NUM_LISTS) {
964✔
153
    out_of_memory();
×
154
  }
155

156
  tmp = (int32_t *) safe_realloc(queue->bound, n * sizeof(int32_t));
964✔
157
  for (i=queue->bsize; i<n; i++) {
98,072✔
158
    tmp[i] = -1;
97,108✔
159
  }
160

161
  queue->bound = tmp;
964✔
162
  queue->bsize = n;
964✔
163
}
964✔
164

165

166
/*
167
 * Add a bound for variable x:
168
 * - id = the atom index
169
 */
170
static void bv_bound_queue_push(bv_bound_queue_t *queue, thvar_t x, int32_t id) {
1,931✔
171
  int32_t k, i;
172

173
  if (x >= queue->bsize) {
1,931✔
174
    bv_bound_queue_resize(queue, x);
964✔
175
    assert(x < queue->bsize);
176
  }
177

178
  k = queue->bound[x];
1,931✔
179
  assert(-1 <= k && k < (int32_t) queue->top);
180

181
  i = queue->top;
1,931✔
182
  if (i == queue->size) {
1,931✔
183
    bv_bound_queue_extend(queue);
961✔
184
  }
185
  assert(i < queue->size);
186

187
  queue->data[i].atom_id = id;
1,931✔
188
  queue->data[i].pre = k;
1,931✔
189
  queue->bound[x] = i;
1,931✔
190

191
  queue->top = i+1;
1,931✔
192
}
1,931✔
193

194

195

196
/*
197
 * Get the index of the first bound on x
198
 * - return -1 if there's no bound on x
199
 */
200
static inline int32_t bv_bound_for_var(bv_bound_queue_t *queue, thvar_t x) {
35,983✔
201
  int32_t k;
202

203
  k = -1;
35,983✔
204
  if (x < queue->bsize) {
35,983✔
205
    k = queue->bound[x];
20,183✔
206
    assert(-1 <= k && k < (int32_t) queue->top);
207
  }
208

209
  return k;
35,983✔
210
}
211

212

213

214
/*
215
 * Delete the queue
216
 */
217
static void delete_bv_bound_queue(bv_bound_queue_t *queue) {
11,476✔
218
  safe_free(queue->data);
11,476✔
219
  safe_free(queue->bound);
11,476✔
220
  queue->data = NULL;
11,476✔
221
  queue->bound = NULL;
11,476✔
222
}
11,476✔
223

224

225
/*
226
 * Empty the queue
227
 */
228
static void reset_bv_bound_queue(bv_bound_queue_t *queue) {
1✔
229
  uint32_t i, n;
230

231
  n = queue->bsize;
1✔
232
  for (i=0; i<n; i++) {
101✔
233
    queue->bound[i] = -1;
100✔
234
  }
235
  queue->top = 0;
1✔
236
}
1✔
237

238

239

240
/**********************************
241
 *  INTERVAL-COMPUTATION BUFFERS  *
242
 *********************************/
243

244
/*
245
 * Initialize the stack
246
 */
247
static void init_bv_interval_stack(bv_interval_stack_t *stack) {
11,476✔
248
  stack->data = NULL;
11,476✔
249
  stack->buffers = NULL;
11,476✔
250
  stack->size = 0;
11,476✔
251
  stack->top = 0;
11,476✔
252
}
11,476✔
253

254

255
/*
256
 * Delete: free all memory
257
 */
258
static void delete_bv_interval_stack(bv_interval_stack_t *stack) {
11,477✔
259
  uint32_t i, n;
260

261
  n = stack->size;
11,477✔
262
  if (n != 0) {
11,477✔
263
    assert(stack->data != NULL && stack->buffers != NULL);
264
    delete_bv_aux_buffers(stack->buffers);
39✔
265
    for (i=0; i<n; i++) {
273✔
266
      delete_bv_interval(stack->data + i);
234✔
267
    }
268
    safe_free(stack->buffers);
39✔
269
    safe_free(stack->data);
39✔
270

271
    stack->buffers = NULL;
39✔
272
    stack->data = NULL;
39✔
273
    stack->top = 0;
39✔
274
    stack->size = 0;
39✔
275
  }
276
}
11,477✔
277

278

279

280
/*
281
 * Reset: same as delete
282
 */
283
static inline void reset_bv_interval_stack(bv_interval_stack_t *stack) {
1✔
284
  delete_bv_interval_stack(stack);
1✔
285
}
1✔
286

287

288
/*
289
 * Allocate the stack (if not allocated already)
290
 * - use the default size
291
 */
292
static void alloc_bv_interval_stack(bv_interval_stack_t *stack) {
813✔
293
  uint32_t i, n;
294
  bv_interval_t *d;
295
  bv_aux_buffers_t *b;
296

297
  n = stack->size;
813✔
298
  if (n == 0) {
813✔
299
    n = DEF_BV_INTV_STACK_SIZE;
39✔
300
    assert(n <= MAX_BV_INTV_STACK_SIZE);
301
    d = (bv_interval_t *) safe_malloc(n * sizeof(bv_interval_t));
39✔
302
    for (i=0; i<n; i++) {
273✔
303
      init_bv_interval(d + i);
234✔
304
    }
305

306
    b = (bv_aux_buffers_t *) safe_malloc(sizeof(bv_aux_buffers_t));
39✔
307
    init_bv_aux_buffers(b);
39✔
308

309
    stack->data = d;
39✔
310
    stack->buffers = b;
39✔
311
    stack->size = n;
39✔
312
  }
313
}
813✔
314

315

316

317
/*
318
 * Get an interval object
319
 * - this uses a FIFO allocation model
320
 * - return NULL if the stack is full (fails)
321
 */
322
static bv_interval_t *get_bv_interval(bv_interval_stack_t *stack) {
1,747✔
323
  bv_interval_t *d;
324
  uint32_t i;
325

326
  d = NULL;
1,747✔
327
  i = stack->top;
1,747✔
328
  if (i < stack->size) {
1,747✔
329
    d = stack->data + i;
1,747✔
330
    stack->top = i+1;
1,747✔
331
  }
332
  return d;
1,747✔
333
}
334

335

336
/*
337
 * Free the last allocated interval object (i.e., decrement top)
338
 */
339
static inline void release_bv_interval(bv_interval_stack_t *stack) {
121✔
340
  assert(stack->top > 0);
341
  stack->top --;
121✔
342
}
121✔
343

344

345
/*
346
 * Free all the allocated intervals
347
 */
348
static inline void release_all_bv_intervals(bv_interval_stack_t *stack) {
813✔
349
  stack->top = 0;
813✔
350
}
813✔
351

352
/*
353
 * Get the auxiliary buffer structure
354
 * - alloc_bv_interval_stack must be called before this function
355
 */
356
static inline bv_aux_buffers_t *get_bv_aux_buffers(bv_interval_stack_t *stack) {
121✔
357
  assert(stack->size != 0 && stack->buffers != NULL);
358
  return stack->buffers;
121✔
359
}
360

361

362

363

364
/**********************
365
 *  VARIABLE QUEUES   *
366
 *********************/
367

368
/*
369
 * Initialize to the empty queue
370
 */
371
static inline void init_bv_queue(bv_queue_t *queue) {
34,428✔
372
  queue->data = NULL;
34,428✔
373
  queue->top = 0;
34,428✔
374
  queue->size = 0;
34,428✔
375
}
34,428✔
376

377
/*
378
 * Make the queue larger
379
 */
380
static void bv_queue_extend(bv_queue_t *queue) {
19,769✔
381
  uint32_t n;
382

383
  n = queue->size;
19,769✔
384
  if (n == 0) {
19,769✔
385
    // first allocation
386
    n = DEF_BV_QUEUE_SIZE;
19,738✔
387
    assert(n > 0 && n <= MAX_BV_QUEUE_SIZE && queue->data == NULL);
388
  } else {
389
    n += (n >> 1); // 50% large
31✔
390
    assert(n > queue->size);
391
    if (n > MAX_BV_QUEUE_SIZE) {
31✔
392
      out_of_memory();
×
393
    }
394
  }
395

396
  queue->data = (thvar_t *) safe_realloc(queue->data, n * sizeof(thvar_t));
19,769✔
397
  queue->size = n;
19,769✔
398
}
19,769✔
399

400

401
/*
402
 * Push x on the queue
403
 */
404
static void bv_queue_push(bv_queue_t *queue, thvar_t x) {
51,066✔
405
  uint32_t i;
406

407
  i = queue->top;
51,066✔
408
  if (i == queue->size) {
51,066✔
409
    bv_queue_extend(queue);
19,769✔
410
  }
411
  assert(i < queue->size);
412
  queue->data[i] = x;
51,066✔
413
  queue->top = i + 1;
51,066✔
414
}
51,066✔
415

416

417
/*
418
 * Empty the queue
419
 */
420
static inline void reset_bv_queue(bv_queue_t *queue) {
3✔
421
  queue->top = 0;
3✔
422
}
3✔
423

424

425
/*
426
 * Delete
427
 */
428
static void delete_bv_queue(bv_queue_t *queue) {
34,428✔
429
  if (queue->data != NULL) {
34,428✔
430
    safe_free(queue->data);
19,738✔
431
    queue->data = NULL;
19,738✔
432
  }
433
}
34,428✔
434

435

436

437

438

439

440

441
/********************
442
 *  PUSH/POP STACK  *
443
 *******************/
444

445
/*
446
 * Initialize the stack: initial size = 0
447
 */
448
static void init_bv_trail(bv_trail_stack_t *stack) {
11,476✔
449
  stack->size = 0;
11,476✔
450
  stack->top = 0;
11,476✔
451
  stack->data = NULL;
11,476✔
452
}
11,476✔
453

454

455

456
/*
457
 * Save a base level
458
 * - nv = number of variables
459
 * - na = number of atoms
460
 * - nb = number of bounds
461
 * - ns = number of select variables
462
 * - ndm = number of delayed mapped variables
463
 * - ndb = number of delayed blasted variables
464
 * - bb = bitblast pointer
465
 */
466
static void bv_trail_save(bv_trail_stack_t *stack, uint32_t nv, uint32_t na, uint32_t nb,
6,769✔
467
                          uint32_t ns, uint32_t ndm, uint32_t ndb, uint32_t bb) {
468
  uint32_t i, n;
469

470
  i = stack->top;
6,769✔
471
  n = stack->size;
6,769✔
472
  if (i == n) {
6,769✔
473
    if (n == 0) {
6,732✔
474
      n = DEF_BV_TRAIL_SIZE;
6,732✔
475
      assert(0<n &&  n<MAX_BV_TRAIL_SIZE);
476
    } else {
477
      n += n;
×
478
      if (n >= MAX_BV_TRAIL_SIZE) {
×
479
        out_of_memory();
×
480
      }
481
    }
482
    stack->data = (bv_trail_t *) safe_realloc(stack->data, n * sizeof(bv_trail_t));
6,732✔
483
    stack->size = n;
6,732✔
484
  }
485
  assert(i < stack->size);
486

487
  stack->data[i].nvars = nv;
6,769✔
488
  stack->data[i].natoms = na;
6,769✔
489
  stack->data[i].nbounds = nb;
6,769✔
490
  stack->data[i].nselects = ns;
6,769✔
491
  stack->data[i].ndelayed_mapped = ndm;
6,769✔
492
  stack->data[i].ndelayed_blasted = ndb;
6,769✔
493
  stack->data[i].nbblasted = bb;
6,769✔
494

495
  stack->top = i+1;
6,769✔
496
}
6,769✔
497

498

499
/*
500
 * Get the top trail record
501
 */
502
static bv_trail_t *bv_trail_top(bv_trail_stack_t *stack) {
59,660✔
503
  assert(stack->top > 0);
504
  return stack->data + (stack->top - 1);
59,660✔
505
}
506

507

508
/*
509
 * Remove the top record
510
 */
511
static inline void bv_trail_pop(bv_trail_stack_t *stack) {
37✔
512
  assert(stack->top > 0);
513
  stack->top --;
37✔
514
}
37✔
515

516

517
/*
518
 * Delete the stack
519
 */
520
static inline void delete_bv_trail(bv_trail_stack_t *stack) {
11,476✔
521
  safe_free(stack->data);
11,476✔
522
  stack->data = NULL;
11,476✔
523
}
11,476✔
524

525

526
/*
527
 * Empty the stack
528
 */
529
static inline void reset_bv_trail(bv_trail_stack_t *stack) {
1✔
530
  stack->top = 0;
1✔
531
}
1✔
532

533

534

535

536

537

538
/***********************
539
 *  STATISTICS RECORD  *
540
 **********************/
541

542
static void init_bv_stats(bv_stats_t *s) {
11,477✔
543
  s->eq_atoms = 0;
11,477✔
544
  s->on_the_fly_atoms = 0;
11,477✔
545
  s->ge_atoms = 0;
11,477✔
546
  s->sge_atoms = 0;
11,477✔
547
  s->equiv_lemmas = 0;
11,477✔
548
  s->equiv_conflicts = 0;
11,477✔
549
  s->half_equiv_lemmas = 0;
11,477✔
550
  s->interface_lemmas = 0;
11,477✔
551
}
11,477✔
552

553
static inline void reset_bv_stats(bv_stats_t *s) {
1✔
554
  init_bv_stats(s);
1✔
555
}
1✔
556

557

558

559
/**************
560
 *  MARKING   *
561
 *************/
562

563
/*
564
 * The top-level useful variables are marked and we recursively
565
 * mark all the variables on which they depend.
566
 * - the top-level marked variables include:
567
 *   all variables that occur in atoms
568
 *   all variables (x, y) such that x := y in the merge table
569
 *   all variables x that occur in (bit-select x i)
570
 */
571
static void bv_solver_mark_variable(bv_solver_t *solver, thvar_t x);
572

573
static void bv_solver_mark_poly64_vars(bv_solver_t *solver, bvpoly64_t *p) {
20,305✔
574
  uint32_t i, n;
575
  thvar_t x;
576

577
  n = p->nterms;
20,305✔
578
  i = 0;
20,305✔
579
  if (p->mono[0].var == const_idx) {
20,305✔
580
    i ++;
2,447✔
581
  }
582
  while (i < n ) {
43,990✔
583
    x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
23,685✔
584
    bv_solver_mark_variable(solver, x);
23,685✔
585
    i ++;
23,685✔
586
  }
587
}
20,305✔
588

589
static void bv_solver_mark_poly_vars(bv_solver_t *solver, bvpoly_t *p) {
596✔
590
  uint32_t i, n;
591
  thvar_t x;
592

593
  n = p->nterms;
596✔
594
  i = 0;
596✔
595
  if (p->mono[0].var == const_idx) {
596✔
596
    i ++;
544✔
597
  }
598
  while (i < n ) {
1,233✔
599
    x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
637✔
600
    bv_solver_mark_variable(solver, x);
637✔
601
    i ++;
637✔
602
  }
603
}
596✔
604

605
static void bv_solver_mark_pprod_vars(bv_solver_t *solver, pprod_t *p) {
518✔
606
  uint32_t i, n;
607
  thvar_t x;
608

609
  n = p->len;
518✔
610
  for (i=0; i<n; i++) {
1,541✔
611
    x = mtbl_get_root(&solver->mtbl, p->prod[i].var);
1,023✔
612
    bv_solver_mark_variable(solver, x);
1,023✔
613
  }
614
}
518✔
615

616
static void bv_solver_mark_variable(bv_solver_t *solver, thvar_t x) {
288,975✔
617
  bv_vartable_t *vtbl;
618
  bv_ite_t *ite;
619

620
  vtbl = &solver->vtbl;
288,975✔
621

622
  if (! bvvar_is_marked(vtbl, x)) {
288,975✔
623
    bvvar_set_mark(vtbl, x);
171,264✔
624
    switch (bvvar_tag(vtbl, x)) {
171,264✔
625
    case BVTAG_VAR:
86,334✔
626
    case BVTAG_CONST64:
627
    case BVTAG_CONST:
628
    case BVTAG_BIT_ARRAY:
629
      // nothing more to do
630
      break;
86,334✔
631

632
    case BVTAG_POLY64:
20,305✔
633
      bv_solver_mark_poly64_vars(solver, bvvar_poly64_def(vtbl, x));
20,305✔
634
      break;
20,305✔
635

636
    case BVTAG_POLY:
596✔
637
      bv_solver_mark_poly_vars(solver, bvvar_poly_def(vtbl, x));
596✔
638
      break;
596✔
639

640
    case BVTAG_PPROD:
518✔
641
      bv_solver_mark_pprod_vars(solver, bvvar_pprod_def(vtbl, x));
518✔
642
      break;
518✔
643

644
    case BVTAG_ITE:
60,766✔
645
      ite = bvvar_ite_def(vtbl, x);
60,766✔
646
      // could check whether ite->cond is true or false?
647
      bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, ite->left));
60,766✔
648
      bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, ite->right));
60,766✔
649
      break;
60,766✔
650

651
    case BVTAG_UDIV:
2,745✔
652
    case BVTAG_UREM:
653
    case BVTAG_SREM:
654
    case BVTAG_SDIV:
655
    case BVTAG_SMOD:
656
    case BVTAG_SHL:
657
    case BVTAG_LSHR:
658
    case BVTAG_ASHR:
659
    case BVTAG_ADD:
660
    case BVTAG_SUB:
661
    case BVTAG_MUL:
662
      bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, vtbl->def[x].op[0]));
2,745✔
663
      bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, vtbl->def[x].op[1]));
2,745✔
664
      break;
2,745✔
665

666
    case BVTAG_NEG:
×
667
      bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, vtbl->def[x].op[0]));
×
668
      break;
×
669
    }
670
  }
671
}
288,975✔
672

673

674

675

676
/********************
677
 *  DELAYED QUEUES  *
678
 *******************/
679

680
/*
681
 * Check whether x was created before the current base level
682
 * - if so, add x to the delayed_blasted queue
683
 */
684
static void bv_solver_save_delayed_blasted_var(bv_solver_t *solver, thvar_t x) {
108,188✔
685
  bv_trail_stack_t *trail;
686

687
  trail = &solver->trail_stack;
108,188✔
688
  if (trail->top > 0 && x < bv_trail_top(trail)->nvars) {
108,188✔
689
    bv_queue_push(&solver->delayed_blasted, x);
17,643✔
690
  }
691
}
108,188✔
692

693
/*
694
 * Check whether x was created before the current base level
695
 * - if so, add x to the delayed_mapped queue
696
 *
697
 * If x is in the delayed_mapped, we'll remove x's pseudo map on pop.
698
 */
699
static void bv_solver_save_delayed_mapped_var(bv_solver_t *solver, thvar_t x) {
109,061✔
700
  bv_trail_stack_t *trail;
701

702
  trail = &solver->trail_stack;
109,061✔
703
  if (trail->top > 0 && x < bv_trail_top(trail)->nvars) {
109,061✔
704
    bv_queue_push(&solver->delayed_mapped, x);
15,068✔
705
  }
706
}
109,061✔
707

708

709
/*
710
 * Store m as pseudo map for variable x. Also add x to the delayed queue
711
 * if x was created before the current base level.
712
 * - x must not be mapped already (i.e., solver->vtbl.map[x] must be NULL
713
 * - m must be a non-null array
714
 */
715
static void bv_solver_set_map(bv_solver_t *solver, thvar_t x, literal_t *m) {
109,061✔
716
  bvvar_set_map(&solver->vtbl, x, m);
109,061✔
717
  bv_solver_save_delayed_mapped_var(solver, x);
109,061✔
718
}
109,061✔
719

720

721

722

723
/*****************
724
 *  BIT EXTRACT  *
725
 ****************/
726

727
/*
728
 * Return the remap table (allocate and initialize it if necessary)
729
 */
730
static remap_table_t *bv_solver_get_remap(bv_solver_t *solver) {
29,113✔
731
  remap_table_t *tmp;
732

733
  tmp = solver->remap;
29,113✔
734
  if (tmp == NULL) {
29,113✔
735
    tmp = (remap_table_t *) safe_malloc(sizeof(remap_table_t));
10,788✔
736
    init_remap_table(tmp);
10,788✔
737
    remap_table_set_level(tmp, solver->base_level);
10,788✔
738
    solver->remap = tmp;
10,788✔
739
  }
740

741
  return tmp;
29,113✔
742
}
743

744

745
#ifndef NDEBUG
746

747
/*
748
 * For debugging: check whether x occurs in the select_queue
749
 */
750
static bool bvvar_in_select_queue(bv_solver_t *solver, thvar_t x) {
751
  bv_queue_t *squeue;
752
  uint32_t i, n;
753

754
  squeue = &solver->select_queue;
755
  n = squeue->top;
756
  for (i=0; i<n; i++) {
757
    if (squeue->data[i] == x) return true;
758
  }
759

760
  return false;
761
}
762

763
/*
764
 * Also for debugging: check whether x is bitblasted or compiled
765
 * to a variable that's bit-blasted.
766
 */
767
static bool bvvar_is_bitblasted_or_compiled(bv_solver_t *solver, thvar_t x) {
768
  thvar_t y;
769

770
  if (bvvar_is_bitblasted(&solver->vtbl, x)) {
771
    return true;
772
  }
773
  if (solver->compiler != NULL) {
774
    y = bvvar_compiles_to(solver->compiler, x);
775
    return y > 0 && bvvar_is_bitblasted(&solver->vtbl, y);
776
  }
777
  return false;
778
}
779

780
#endif
781

782

783
/*
784
 * Return the pseudo literal array mapped to x
785
 * - allocate a new array of n literals if x is not mapped yet
786
 *   and store x in the select queue
787
 */
788
static literal_t *select_bvvar_get_pseudo_map(bv_solver_t *solver, thvar_t x) {
302,096✔
789
  remap_table_t *rmap;
790
  literal_t *tmp;
791
  uint32_t n;
792

793
  tmp = bvvar_get_map(&solver->vtbl, x);
302,096✔
794
  if (tmp == NULL) {
302,096✔
795
    n = bvvar_bitsize(&solver->vtbl, x);
18,355✔
796
    rmap = bv_solver_get_remap(solver);
18,355✔
797
    tmp = remap_table_fresh_array(rmap, n);
18,355✔
798
    bv_solver_set_map(solver, x, tmp);
18,355✔
799
    bv_queue_push(&solver->select_queue, x);
18,355✔
800
  }
801

802
  assert(bvvar_is_bitblasted_or_compiled(solver, x) || bvvar_in_select_queue(solver, x));
803

804
  return tmp;
302,096✔
805
}
806

807

808

809
/*
810
 * Extract bit i of a 64bit constant x
811
 * - convert to true_literal or false_literal
812
 */
813
static literal_t bvconst64_get_bit(bv_vartable_t *vtbl, thvar_t x, uint32_t i) {
890✔
814
  literal_t l;
815

816
  l = false_literal;
890✔
817
  if (tst_bit64(bvvar_val64(vtbl, x), i)) {
890✔
818
    l= true_literal;
267✔
819
  }
820

821
  return l;
890✔
822
}
823

824

825
/*
826
 * Extract bit i of a general constant x
827
 */
828
static literal_t bvconst_get_bit(bv_vartable_t *vtbl, thvar_t x, uint32_t i) {
1,128✔
829
  literal_t l;
830

831
  l = false_literal;
1,128✔
832
  if (bvconst_tst_bit(bvvar_val(vtbl, x), i)) {
1,128✔
833
    l = true_literal;
715✔
834
  }
835

836
  return l;
1,128✔
837
}
838

839

840
/*
841
 * Extract bit i of a bvarray variable x
842
 */
843
static literal_t bvarray_get_bit(bv_vartable_t *vtbl, thvar_t x, uint32_t i) {
264✔
844
  literal_t *a;
845

846
  assert(i < bvvar_bitsize(vtbl, x));
847

848
  a = bvvar_bvarray_def(vtbl, x);
264✔
849
  return a[i];
264✔
850
}
851

852

853
/*
854
 * Extract bit i of variable x:
855
 * - get it from the pseudo literal array mapped to x
856
 * - also add x to solver->select_queue
857
 */
858
static literal_t bvvar_get_bit(bv_solver_t *solver, thvar_t x, uint32_t i) {
302,096✔
859
  remap_table_t *rmap;
860
  literal_t *map;
861
  literal_t r, l;
862

863
  map = select_bvvar_get_pseudo_map(solver, x);
302,096✔
864

865
  rmap = solver->remap;
302,096✔
866
  r = remap_table_find_root(rmap, map[i]); // r := root of map[i]
302,096✔
867
  l = remap_table_find(rmap, r);           // l := real literal for r
302,096✔
868
  if (l == null_literal) {
302,096✔
869
    // nothing attached to r: create a new literal and attach it to r
870
    l = pos_lit(create_boolean_variable(solver->core));
301,675✔
871
    remap_table_assign(rmap, r, l);
301,675✔
872
  }
873

874
  return l;
302,096✔
875
}
876

877

878

879

880
/******************
881
 *  BIT BLASTING  *
882
 *****************/
883

884
/*
885
 * Allocate and initialize the bit-blaster object if needed
886
 * - also allocate the remap table if needed
887
 */
888
static void bv_solver_prepare_blasting(bv_solver_t *solver) {
25,324✔
889
  bit_blaster_t *blaster;
890
  remap_table_t *remap;
891

892
  if (solver->blaster == NULL) {
25,324✔
893
    remap = bv_solver_get_remap(solver);
10,758✔
894
    blaster = (bit_blaster_t *) safe_malloc(sizeof(bit_blaster_t));
10,758✔
895
    init_bit_blaster(blaster, solver->core, remap);
10,758✔
896
    solver->blaster = blaster;
10,758✔
897
  }
898
}
25,324✔
899

900

901
/*
902
 * Allocate and initialize the compiler object (if needed)
903
 */
904
static void bv_solver_alloc_compiler(bv_solver_t *solver) {
25,324✔
905
  bvc_t *c;
906

907
  c = solver->compiler;
25,324✔
908
  if (c == NULL) {
25,324✔
909
    c = (bvc_t *) safe_malloc(sizeof(bvc_t));
10,758✔
910
    init_bv_compiler(c, &solver->vtbl, &solver->mtbl);
10,758✔
911
    bv_compiler_set_level(c, solver->base_level);
10,758✔
912
    solver->compiler = c;
10,758✔
913
  }
914
}
25,324✔
915

916

917
/*
918
 * Scan the set of atoms created at the current base-level
919
 * - mark all the variables that occur in these atoms
920
 */
921
static void bv_solver_mark_vars_in_atoms(bv_solver_t *solver) {
25,324✔
922
  bv_atomtable_t *atbl;
923
  bvatm_t *atm;
924
  uint32_t i, n;
925

926
  /*
927
   * scan all the atoms and mark their variables
928
   *
929
   * TODO: make this more efficient by keeping track
930
   * of the atoms that have been processed (keep track
931
   * of this in the trail_stack?)
932
   */
933
  atbl = &solver->atbl;
25,324✔
934
  n = atbl->natoms;
25,324✔
935
  for (i=0; i<n; i++) {
59,612✔
936
    atm = bvatom_desc(atbl, i);
34,288✔
937
    bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, atm->left));
34,288✔
938
    bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, atm->right));
34,288✔
939
  }
940
}
25,324✔
941

942

943
/*
944
 * Scan the variables
945
 * - if x == y is in the merge table then mark both x and y
946
 * - also if x has an eterm, mark x
947
 */
948
static void bv_solver_mark_merged_vars(bv_solver_t *solver) {
25,324✔
949
  bv_vartable_t *vtbl;
950
  uint32_t i, n;
951
  thvar_t x;
952

953
  vtbl = &solver->vtbl;
25,324✔
954
  n = vtbl->nvars;
25,324✔
955
  for (i=1; i<n; i++) {
213,312✔
956
    x = mtbl_get_root(&solver->mtbl, i);
187,988✔
957
    if (i != x) {
187,988✔
958
      bv_solver_mark_variable(solver, i);
15,745✔
959
      bv_solver_mark_variable(solver, x);
15,745✔
960
    } else if (bvvar_has_eterm(vtbl, i)) {
172,243✔
961
      bv_solver_mark_variable(solver, i);
5,386✔
962
    }
963
  }
964
}
25,324✔
965

966

967
/*
968
 * Mark the variables that are in the select_queue
969
 */
970
static void bv_solver_mark_select_vars(bv_solver_t *solver) {
25,324✔
971
  bv_queue_t *squeue;
972
  uint32_t i, n;
973

974
  squeue = &solver->select_queue;
25,324✔
975
  n = squeue->top;
25,324✔
976
  for (i=0; i<n; i++) {
56,480✔
977
    bv_solver_mark_variable(solver, mtbl_get_root(&solver->mtbl, squeue->data[i]));
31,156✔
978
  }
979
}
25,324✔
980

981

982
/*
983
 * Check whether a variable is useful (i.e., requires bitblasting)
984
 * - x is useful if it occurs in an atom (i.e., x is marked)
985
 *   or if it's mapped to another variable y in the merge table
986
 *   or if it has an egraph term attached.
987
 */
988
static bool bvvar_is_useful(bv_solver_t *solver, thvar_t x) {
21,498✔
989
  thvar_t y;
990

991
  y = mtbl_get_root(&solver->mtbl, x);
21,498✔
992
  return x != y || bvvar_is_marked(&solver->vtbl, x) || bvvar_has_eterm(&solver->vtbl, x);
21,498✔
993
}
994

995

996
/*
997
 * Compile all the useful polynomial variables
998
 */
999
static void bv_solver_compile_polynomials(bv_solver_t *solver) {
25,324✔
1000
  bv_vartable_t *vtbl;
1001
  bvc_t *compiler;
1002
  uint32_t i, n;
1003

1004
#if 0
1005
  printf("---- COMPILE POLYNOMIALS ----\n");
1006
  print_bv_vartable(stdout, &solver->vtbl);
1007
  print_bv_atomtable(stdout, &solver->atbl);
1008
  printf("\n");
1009
#endif
1010

1011
  bv_solver_alloc_compiler(solver);
25,324✔
1012

1013
  compiler = solver->compiler;
25,324✔
1014
  vtbl = &solver->vtbl;
25,324✔
1015
  n = vtbl->nvars;
25,324✔
1016
  for (i=1; i<n; i++) {
213,312✔
1017
    switch (bvvar_tag(vtbl, i)) {
187,988✔
1018
    case BVTAG_POLY64:
21,498✔
1019
    case BVTAG_POLY:
1020
    case BVTAG_PPROD:
1021
      if (bvvar_is_useful(solver, i)) {
21,498✔
1022
#if 0
1023
        printf("  push var: ");
1024
        print_bv_solver_vardef(stdout, solver, i);
1025
        printf("\n");
1026
#endif
1027
        bv_compiler_push_var(compiler, i);
21,419✔
1028
      }
1029
      break;
21,498✔
1030

1031
    default:
166,490✔
1032
      break;
166,490✔
1033
    }
1034
    bvvar_clr_mark(vtbl, i);
187,988✔
1035
  }
1036

1037
  // process the polynomials
1038
  bv_compiler_process_queue(compiler);
25,324✔
1039

1040
  //  print_solver_state(stdout, solver);
1041
}
25,324✔
1042

1043

1044

1045
/*
1046
 * PSEUDO-LITERAL MAPS
1047
 */
1048

1049
/*
1050
 * Convert constant c to an array of pseudo literals
1051
 * - n = number of bits in c
1052
 */
1053
static literal_t *bvconst64_get_pseudo_map(uint64_t c, uint32_t n) {
18,359✔
1054
  literal_t *a;
1055
  uint32_t i;
1056

1057
  assert(0 < n && n <= 64);
1058
  a = (literal_t *) alloc_int_array(n);
18,359✔
1059
  for (i=0; i<n; i++) {
296,798✔
1060
    a[i] = bool2literal(c & 1);
278,439✔
1061
    c >>= 1;
278,439✔
1062
  }
1063

1064
  return a;
18,359✔
1065
}
1066

1067
static literal_t *bvconst_get_pseudo_map(uint32_t *c, uint32_t n) {
631✔
1068
  literal_t *a;
1069
  uint32_t i;
1070

1071
  assert(64 < n);
1072
  a = (literal_t *) alloc_int_array(n);
631✔
1073
  for (i=0; i<n; i++) {
110,251✔
1074
    a[i] = bool2literal(bvconst_tst_bit(c, i));
109,620✔
1075
  }
1076

1077
  return a;
631✔
1078
}
1079

1080

1081
/*
1082
 * Pseudo-literal array mapped to an array of literals a
1083
 * - n = number of literals in a
1084
 */
1085
static literal_t *bvarray_get_pseudo_map(remap_table_t *rmap, literal_t *a, uint32_t n) {
17,244✔
1086
  literal_t *tmp;
1087
  uint32_t i;
1088

1089
  tmp = remap_table_fresh_array(rmap, n);
17,244✔
1090
  for (i=0; i<n; i++) {
447,972✔
1091
    remap_table_assign(rmap, tmp[i], a[i]);
430,728✔
1092
  }
1093

1094
  return tmp;
17,244✔
1095
}
1096

1097

1098
/*
1099
 * Get/create a pseudo map for x
1100
 * - assign a map to x if x is constant or bit array
1101
 * - return map[x]
1102
 */
1103
static literal_t *bvvar_simple_pseudo_map(bv_solver_t *solver, thvar_t x) {
65,910✔
1104
  bv_vartable_t *vtbl;
1105
  literal_t *tmp;
1106

1107
  assert(solver->remap != NULL);
1108

1109
  vtbl = &solver->vtbl;
65,910✔
1110
  tmp = bvvar_get_map(vtbl, x);
65,910✔
1111
  if (tmp == NULL) {
65,910✔
1112
    switch (bvvar_tag(vtbl, x)) {
34,330✔
1113
    case BVTAG_CONST64:
4,331✔
1114
      tmp = bvconst64_get_pseudo_map(bvvar_val64(vtbl, x), bvvar_bitsize(vtbl, x));
4,331✔
1115
      bv_solver_set_map(solver, x, tmp);
4,331✔
1116
      break;
4,331✔
1117

1118
    case BVTAG_CONST:
12✔
1119
      tmp = bvconst_get_pseudo_map(bvvar_val(vtbl, x), bvvar_bitsize(vtbl, x));
12✔
1120
      bv_solver_set_map(solver, x, tmp);
12✔
1121
      break;
12✔
1122

1123
    case BVTAG_BIT_ARRAY:
3,410✔
1124
      tmp = bvarray_get_pseudo_map(solver->remap, bvvar_bvarray_def(vtbl, x), bvvar_bitsize(vtbl, x));
3,410✔
1125
      bv_solver_set_map(solver, x, tmp);
3,410✔
1126
      break;
3,410✔
1127

1128
    default:
26,577✔
1129
      break;
26,577✔
1130
    }
1131
  }
1132

1133
  return tmp;
65,910✔
1134
}
1135

1136

1137

1138
/*
1139
 * Assert that pseudo literals s1 and s2 are equal
1140
 * - attempt to merge their equivalence classes in the remap table first
1141
 * - if that's not possible, assert (l1 == l2) in the core
1142
 *   where l1 = literal mapped to s1
1143
 *     and l2 = literal mapped to s2
1144
 * - return false if s1 == not s2
1145
 */
1146
static bool merge_pseudo_literals(bv_solver_t *solver, literal_t s1, literal_t s2) {
34,543✔
1147
  remap_table_t *rmap;
1148
  literal_t l1, l2;
1149

1150
  assert(solver->remap != NULL && solver->blaster != NULL);
1151

1152
  rmap = solver->remap;
34,543✔
1153
  s1 = remap_table_find_root(rmap, s1);
34,543✔
1154
  s2 = remap_table_find_root(rmap, s2);
34,543✔
1155
  if (remap_table_mergeable(rmap, s1, s2)) {
34,543✔
1156
    remap_table_merge(rmap, s1, s2);
22,704✔
1157
  } else if (s1 == not(s2)) {
11,839✔
1158
    // contradiction detected
1159
    return false;
1✔
1160
  } else if (s1 != s2) {
11,838✔
1161
    l1 = remap_table_find(rmap, s1);
7,123✔
1162
    l2 = remap_table_find(rmap, s2);
7,123✔
1163
    bit_blaster_eq(solver->blaster, l1, l2);
7,123✔
1164
  }
1165

1166
  return true;
34,542✔
1167
}
1168

1169

1170
/*
1171
 * Assert that two arrays a and b of n pseudo literals are equal
1172
 * - return false if a[i] == not b[i] for some i
1173
 */
1174
static bool merge_pseudo_maps(bv_solver_t *solver, literal_t *a, literal_t *b, uint32_t n) {
9,609✔
1175
  uint32_t i;
1176

1177
  if (a == b) {
9,609✔
1178
    return true;
8,188✔
1179
  }
1180

1181
  for (i=0; i<n; i++) {
35,963✔
1182
    if (! merge_pseudo_literals(solver, a[i], b[i])) {
34,543✔
1183
      return false;
1✔
1184
    }
1185
  }
1186

1187
  return true;
1,420✔
1188
}
1189

1190

1191

1192
/*
1193
 * Merge the pseudo maps of variables x and y
1194
 * - if x and y have no map, then create a common pseudo-literal array for both
1195
 * - return false if a contradiction is detected
1196
 */
1197
static bool merge_pseudo_maps2(bv_solver_t *solver, thvar_t x, thvar_t y) {
20,403✔
1198
  literal_t *mx, *my;
1199
  uint32_t n;
1200

1201
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y)
1202
         && x != y && solver->remap != NULL && solver->blaster != NULL);
1203

1204
  mx = bvvar_simple_pseudo_map(solver, x);
20,403✔
1205
  my = bvvar_simple_pseudo_map(solver, y);
20,403✔
1206
  n = bvvar_bitsize(&solver->vtbl, x);
20,403✔
1207

1208
  if (mx == my) {
20,403✔
1209
    if (mx == NULL) {
8,864✔
1210
      // allocate a fresh map
1211
      mx = remap_table_fresh_array(solver->remap, n);
3,955✔
1212
      bv_solver_set_map(solver, x, mx);
3,955✔
1213
      bv_solver_set_map(solver, y, mx);
3,955✔
1214
    }
1215
  } else {
1216
    if (mx == NULL) {
11,539✔
1217
      bv_solver_set_map(solver, x, my);
4,801✔
1218
    } else if (my == NULL) {
6,738✔
1219
      bv_solver_set_map(solver, y, mx);
5,319✔
1220
    } else {
1221
      return merge_pseudo_maps(solver, mx, my, n);
1,419✔
1222
    }
1223
  }
1224

1225
  return true;
18,984✔
1226
}
1227

1228

1229
// merge the maps of x, y, and z
1230
static bool merge_pseudo_map3(bv_solver_t *solver, thvar_t x, thvar_t y, thvar_t z) {
8,368✔
1231
  literal_t *mx, *my, *mz;
1232
  uint32_t n, k;
1233

1234
  assert(x != y && x != z && y != z && solver->remap != NULL && solver->blaster != NULL);
1235

1236
  mx = bvvar_simple_pseudo_map(solver, x);
8,368✔
1237
  my = bvvar_simple_pseudo_map(solver, y);
8,368✔
1238
  mz = bvvar_simple_pseudo_map(solver, z);
8,368✔
1239

1240
  n = bvvar_bitsize(&solver->vtbl, x);
8,368✔
1241

1242
  assert(bvvar_bitsize(&solver->vtbl, y) == n && bvvar_bitsize(&solver->vtbl, z) == n);
1243

1244
  k = 0;
8,368✔
1245
  if (mx != NULL) k |= 4;
8,368✔
1246
  if (my != NULL) k |= 2;
8,368✔
1247
  if (mz != NULL) k |= 1;
8,368✔
1248

1249
  assert(0 <= k && k <= 7);
1250
  switch (k) {
8,368✔
1251
  case 0:
1✔
1252
    assert(mx == NULL && my == NULL && mz == NULL);
1253
    mx = remap_table_fresh_array(solver->remap, n);
1✔
1254
    bv_solver_set_map(solver, x, mx);
1✔
1255
    bv_solver_set_map(solver, y, mx);
1✔
1256
    bv_solver_set_map(solver, z, mx);
1✔
1257
    break;
1✔
1258

1259
  case 1:
×
1260
    assert(mx == NULL && my == NULL && mz != NULL);
1261
    bv_solver_set_map(solver, x, mz);
×
1262
    bv_solver_set_map(solver, y, mz);
×
1263
    break;
×
1264

1265
  case 2:
4,270✔
1266
    assert(mx == NULL && my != NULL && mz == NULL);
1267
    bv_solver_set_map(solver, x, my);
4,270✔
1268
    bv_solver_set_map(solver, z, my);
4,270✔
1269
    break;
4,270✔
1270

1271
  case 3:
1✔
1272
    assert(mx == NULL && my != NULL && mz != NULL);
1273
    bv_solver_set_map(solver, x, my);
1✔
1274
    return merge_pseudo_maps(solver, my, mz, n);
1✔
1275

1276
  case 4:
1✔
1277
    assert(mx != NULL && my == NULL && mz == NULL);
1278
    bv_solver_set_map(solver, y, mx);
1✔
1279
    bv_solver_set_map(solver, z, mx);
1✔
1280
    break;
1✔
1281

1282
  case 5:
×
1283
    assert(mx != NULL && my == NULL && mz != NULL);
1284
    bv_solver_set_map(solver, y, mx);
×
1285
    return merge_pseudo_maps(solver, mx, mz, n);
×
1286

1287
  case 6:
1✔
1288
    assert(mx != NULL && my != NULL && mz == NULL);
1289
    bv_solver_set_map(solver, z, mx);
1✔
1290
    return merge_pseudo_maps(solver, mx, my, n);
1✔
1291

1292
  case 7:
4,094✔
1293
    assert(mx != NULL && my != NULL && mz != NULL);
1294
    return merge_pseudo_maps(solver, mx, my, n) && merge_pseudo_maps(solver, mx, mz, n);
4,094✔
1295
  }
1296

1297
  return true;
4,272✔
1298
}
1299

1300

1301
/*
1302
 * Check whether to merge the maps of x y and z
1303
 * - y = root of x's class
1304
 * - z = what x is compiled to (may be -1)
1305
 */
1306
static bool bv_solver_check_shared_pmaps(bv_solver_t *solver, thvar_t x, thvar_t y, thvar_t z) {
211,972✔
1307
  if (z == null_thvar) {
211,972✔
1308
    z = x;
190,559✔
1309
  }
1310

1311
  if (x == y && z == x) {
211,972✔
1312
    return true;
183,201✔
1313
  } else if (x == y && z != x) {
28,771✔
1314
    return merge_pseudo_maps2(solver, x, z);
13,027✔
1315
  } else if (z == x || z == y) {
15,744✔
1316
    return merge_pseudo_maps2(solver, x, y);
7,376✔
1317
  } else {
1318
    return merge_pseudo_map3(solver, x, y, z);
8,368✔
1319
  }
1320
}
1321

1322

1323
/*
1324
 * Go through all variables and build the shared pseudo maps
1325
 */
1326
static bool bv_solver_make_shared_pseudo_maps(bv_solver_t *solver) {
25,324✔
1327
  bv_vartable_t *vtbl;
1328
  bvc_t *compiler;
1329
  uint32_t i, n;
1330
  thvar_t x, y;
1331

1332
  assert(solver->compiler != NULL);
1333

1334
  compiler = solver->compiler;
25,324✔
1335

1336
  vtbl = &solver->vtbl;
25,324✔
1337
  n = vtbl->nvars;
25,324✔
1338
  for (i=1; i<n; i++) {
237,295✔
1339
    x = mtbl_get_root(&solver->mtbl, i);
211,972✔
1340
    y = bvvar_compiles_to(compiler, i);
211,972✔
1341
    if (! bv_solver_check_shared_pmaps(solver, i, x, y)) {
211,972✔
1342
      return false;
1✔
1343
    }
1344
  }
1345

1346
  return true;
25,323✔
1347
}
1348

1349

1350
/*
1351
 * Return the pseudo-map of x
1352
 * - replace x by its root in the merge table
1353
 * - allocate a fresh pseudo map if x doesn't have one already
1354
 */
1355
static literal_t *bvvar_pseudo_map(bv_solver_t *solver, thvar_t x) {
108,211✔
1356
  bv_vartable_t *vtbl;
1357
  literal_t *tmp;
1358

1359
  assert(solver->remap != NULL);
1360

1361
  vtbl = &solver->vtbl;
108,211✔
1362

1363
  x = mtbl_get_root(&solver->mtbl, x);
108,211✔
1364

1365
  tmp = bvvar_get_map(vtbl, x);
108,211✔
1366
  if (tmp == NULL) {
108,211✔
1367
    switch (bvvar_tag(vtbl, x)) {
56,376✔
1368
    case BVTAG_CONST64:
14,028✔
1369
      tmp = bvconst64_get_pseudo_map(bvvar_val64(vtbl, x), bvvar_bitsize(vtbl, x));
14,028✔
1370
      break;
14,028✔
1371

1372
    case BVTAG_CONST:
619✔
1373
      tmp = bvconst_get_pseudo_map(bvvar_val(vtbl, x), bvvar_bitsize(vtbl, x));
619✔
1374
      break;
619✔
1375

1376
    case BVTAG_BIT_ARRAY:
13,834✔
1377
      tmp = bvarray_get_pseudo_map(solver->remap, bvvar_bvarray_def(vtbl, x), bvvar_bitsize(vtbl, x));
13,834✔
1378
      break;
13,834✔
1379

1380
    case BVTAG_POLY64:
×
1381
    case BVTAG_POLY:
1382
    case BVTAG_PPROD:
1383
      x = bvvar_compiles_to(solver->compiler, x);
×
1384
      assert(x != null_thvar); // fall-through intended
1385
    default:
27,895✔
1386
      tmp = remap_table_fresh_array(solver->remap, bvvar_bitsize(vtbl, x));
27,895✔
1387
      break;
27,895✔
1388
    }
1389

1390
    bv_solver_set_map(solver, x, tmp);
56,376✔
1391
  }
1392

1393
  return tmp;
108,211✔
1394
}
1395

1396
/*
1397
 * Check whether array a[0...n-1] is of the form 2^k for some k
1398
 * - if so return k otherwise, return n
1399
 */
1400
static uint32_t bv_is_power_of_two(bit_blaster_t *blaster, literal_t *a, uint32_t n) {
8,821✔
1401
  uint32_t i, k;
1402

1403
  k = n;
8,821✔
1404
  for (i=0; i<n; i++) {
99,068✔
1405
    switch (literal_base_value(blaster->solver, a[i])) {
97,935✔
1406
    case VAL_FALSE:
87,624✔
1407
      break;
87,624✔
1408

1409
    case VAL_TRUE:
4,106✔
1410
      if (k == n) {
4,106✔
1411
        k = i;
2,623✔
1412
        break;
2,623✔
1413
      }
1414

1415
    default:
1416
      goto done;
7,688✔
1417
    }
1418
  }
1419

1420
  return k;
1,133✔
1421

1422
 done:
7,688✔
1423
  return n;
7,688✔
1424
}
1425

1426

1427
/*
1428
 * Check whether a[0 ... n-1] if of the form -2^k for some k (with 0 <= k < n-2)
1429
 * - if so return k, otherwise return n
1430
 */
1431
static uint32_t bv_is_minus_power_of_two(bit_blaster_t *blaster, literal_t *a, uint32_t n) {
6,807✔
1432
  uint32_t i, k;
1433

1434
  k = n;
6,807✔
1435
  for (i=0; i<n; i++) {
17,741✔
1436
    switch (literal_base_value(blaster->solver, a[i])) {
17,574✔
1437
    case VAL_FALSE:
6,346✔
1438
      if (k < n) goto done;
6,346✔
1439
      break;
5,031✔
1440

1441
    case VAL_TRUE:
5,903✔
1442
      if (k == n) {
5,903✔
1443
        k = i;
1,492✔
1444
      }
1445
      break;
5,903✔
1446

1447
    default:
5,325✔
1448
      goto done;
5,325✔
1449
    }
1450
  }
1451

1452
  return k;
167✔
1453

1454
 done:
6,640✔
1455
  return n;
6,640✔
1456
}
1457

1458

1459

1460

1461
/*
1462
 * Assert u == (bvadd a b)
1463
 * - check for special cases where a or b is a power of 2
1464
 */
1465
static void bit_blaster_make_bvadd_var(bit_blaster_t *blaster, literal_t *a, literal_t *b, literal_t *u, uint32_t n) {
3,925✔
1466
  uint32_t k;
1467

1468
  k = bv_is_power_of_two(blaster, a, n);
3,925✔
1469
  if (k < n) {
3,925✔
1470
    // a is 2^k
1471
    // printf("bvinc\n");
1472
    bit_blaster_make_bvinc(blaster, b, k, u, n);
251✔
1473
    return;
251✔
1474
  }
1475

1476
  k = bv_is_power_of_two(blaster, b, n);
3,674✔
1477
  if (k < n) {
3,674✔
1478
    // b is 2^k2
1479
    // printf("bvinc\n");
1480
    bit_blaster_make_bvinc(blaster, a, k, u, n);
877✔
1481
    return;
877✔
1482
  }
1483

1484
  k = bv_is_minus_power_of_two(blaster, a, n);
2,797✔
1485
  if (k < n) {
2,797✔
1486
    // a is -2^k
1487
    // printf("bvdec\n");
1488
    bit_blaster_make_bvdec(blaster, b, k, u, n);
7✔
1489
    return;
7✔
1490
  }
1491

1492
  k = bv_is_minus_power_of_two(blaster, b, n);
2,790✔
1493
  if (k < n) {
2,790✔
1494
    // b is -2^k
1495
    // printf("bvdec\n");
1496
    bit_blaster_make_bvdec(blaster, a, k, u, n);
157✔
1497
    return;
157✔
1498
  }
1499

1500
  // regular adder
1501
  bit_blaster_make_bvadd(blaster, a, b, u, n);
2,633✔
1502
}
1503

1504

1505
/*
1506
 * Assert u == (bvsub a b)
1507
 * - check for the special case where b is a power of 2
1508
 */
1509
static void bit_blaster_make_bvsub_var(bit_blaster_t *blaster, literal_t *a, literal_t *b, literal_t *u, uint32_t n) {
1,222✔
1510
  uint32_t k;
1511

1512
  k = bv_is_power_of_two(blaster, b, n);
1,222✔
1513
  if (k < n) {
1,222✔
1514
    // b is 2^k
1515
    //    printf("bvdec\n");
1516
    bit_blaster_make_bvdec(blaster, a, k, u, n);
2✔
1517
    return;
2✔
1518
  }
1519

1520
  k = bv_is_minus_power_of_two(blaster, b, n);
1,220✔
1521
  if (k < n) {
1,220✔
1522
    // b is -2^k
1523
    bit_blaster_make_bvinc(blaster, a, k, u, n);
×
1524
    return;
×
1525
  }
1526

1527
  // regular subtract
1528
  bit_blaster_make_bvsub(blaster, a, b, u, n);
1,220✔
1529
}
1530

1531

1532
/*
1533
 * Assert (u == (op a b)) for one of the binary operators op
1534
 * - a, b must be fully-defined arrays of n literals
1535
 * - u must be an array of n pseudo literals
1536
 */
1537
static void bit_blaster_make_bvop(bit_blaster_t *blaster, bvvar_tag_t op, literal_t *a, literal_t *b,
16,415✔
1538
                                  literal_t *u, uint32_t n) {
1539
  switch (op) {
16,415✔
1540
  case BVTAG_ADD:
3,925✔
1541
    bit_blaster_make_bvadd_var(blaster, a, b, u, n);
3,925✔
1542
    break;
3,925✔
1543
  case BVTAG_SUB:
1,222✔
1544
    bit_blaster_make_bvsub_var(blaster, a, b, u, n);
1,222✔
1545
    break;
1,222✔
1546
  case BVTAG_MUL:
8,908✔
1547
    bit_blaster_make_bvmul(blaster, a, b, u, n);
8,908✔
1548
    break;
8,908✔
1549
  case BVTAG_SMOD:
×
1550
    bit_blaster_make_smod(blaster, a, b, u, n);
×
1551
    break;
×
1552
  case BVTAG_SHL:
82✔
1553
    bit_blaster_make_shift_left(blaster, a, b, u, n);
82✔
1554
    break;
82✔
1555
  case BVTAG_LSHR:
1,768✔
1556
    bit_blaster_make_lshift_right(blaster, a, b, u, n);
1,768✔
1557
    break;
1,768✔
1558
  case BVTAG_ASHR:
510✔
1559
    bit_blaster_make_ashift_right(blaster, a, b, u, n);
510✔
1560
    break;
510✔
1561

1562
  default:
16,415✔
1563
    assert(false);
1564
  }
1565
}
16,415✔
1566

1567

1568
/*
1569
 * Assert (u == (op a b)) for a division/remainder term (op x y)
1570
 * - a and b must be arrays of n literals
1571
 * - u must be an array of n pseudo-literals
1572
 * Check whether the associate term z = (op' x y) exists and if so
1573
 * apply the bit-blasting operation to z too.
1574
 */
1575
static void bit_blaster_make_bvdivop(bv_solver_t *solver, bvvar_tag_t op, thvar_t x, thvar_t y,
383✔
1576
                                     literal_t *a, literal_t *b, literal_t *u, uint32_t n) {
1577
  bv_vartable_t *vtbl;
1578
  literal_t *v;
1579
  thvar_t z;
1580

1581
  vtbl = &solver->vtbl;
383✔
1582
  v = NULL;
383✔
1583

1584
  switch (op) {
383✔
1585
  case BVTAG_UDIV:
88✔
1586
    z = find_rem(vtbl, x, y);
88✔
1587
    if (z != null_thvar) {
88✔
1588
      v = bvvar_pseudo_map(solver, z);
2✔
1589
    }
1590
    bit_blaster_make_udivision(solver->blaster, a, b, u, v, n);
88✔
1591
    break;
88✔
1592

1593
  case BVTAG_UREM:
146✔
1594
    z = find_div(vtbl, x, y);
146✔
1595
    if (z != null_thvar) {
146✔
1596
      v = bvvar_pseudo_map(solver, z);
2✔
1597
    }
1598
    bit_blaster_make_udivision(solver->blaster, a, b, v, u, n);
146✔
1599
    break;
146✔
1600

1601
  case BVTAG_SDIV:
81✔
1602
    z = find_srem(vtbl, x, y);
81✔
1603
    if (z != null_thvar) {
81✔
1604
      v = bvvar_pseudo_map(solver, z);
1✔
1605
    }
1606
    bit_blaster_make_sdivision(solver->blaster, a, b, u, v, n);
81✔
1607
    break;
81✔
1608

1609
  case BVTAG_SREM:
68✔
1610
    z = find_sdiv(vtbl, x, y);
68✔
1611
    if (z != null_thvar) {
68✔
1612
      v = bvvar_pseudo_map(solver, z);
1✔
1613
    }
1614
    bit_blaster_make_sdivision(solver->blaster, a, b, v, u, n);
68✔
1615
    break;
68✔
1616

1617
  default:
×
1618
    assert(false);
1619
    abort();
×
1620
  }
1621
}
383✔
1622

1623

1624

1625
/*
1626
 * Collect the literals mapped to x in vector v
1627
 * - x must be mapped to an array of pseudo literals
1628
 */
1629
static void collect_bvvar_literals(bv_solver_t *solver, thvar_t x, ivector_t *v) {
1,121,686✔
1630
  remap_table_t *rmap;
1631
  literal_t *a;
1632
  uint32_t i,  n;
1633
  literal_t s;
1634

1635
  assert(solver->remap != NULL);
1636

1637
  rmap = solver->remap;
1,121,686✔
1638

1639
  a = bvvar_get_map(&solver->vtbl, x);
1,121,686✔
1640
  n = bvvar_bitsize(&solver->vtbl, x);
1,121,686✔
1641

1642
  assert(a != NULL);
1643

1644
  ivector_reset(v);
1,121,686✔
1645

1646
  for (i=0; i<n; i++) {
23,836,199✔
1647
    s = a[i];
22,714,513✔
1648
    assert(s != null_literal);
1649
    ivector_push(v, remap_table_find(rmap, s));
22,714,513✔
1650
  }
1651
}
1,121,686✔
1652

1653

1654

1655
/*
1656
 * Recursive bit-blasting:
1657
 * - if x is bitblasted already: do nothing
1658
 */
1659
static void bv_solver_bitblast_variable(bv_solver_t *solver, thvar_t x) {
190,506✔
1660
  bv_vartable_t *vtbl;
1661
  remap_table_t *rmap;
1662
  bv_ite_t *ite;
1663
  ivector_t *a, *b;
1664
  literal_t *u;
1665
  uint32_t i, n;
1666
  literal_t l;
1667
  bvvar_tag_t op;
1668
  thvar_t y, z;
1669

1670
  assert(solver->remap != NULL && solver->blaster != NULL);
1671

1672
  vtbl = &solver->vtbl;
190,506✔
1673
  rmap = solver->remap;
190,506✔
1674

1675
  if (! bvvar_is_bitblasted(vtbl, x)) {
190,506✔
1676
    /*
1677
     * x has not been bitblasted yet
1678
     */
1679
    u = bvvar_pseudo_map(solver, x);
108,205✔
1680
    n = bvvar_bitsize(vtbl, x);
108,205✔
1681
    op = bvvar_tag(vtbl, x);
108,205✔
1682

1683
    if (bvvar_is_marked(vtbl, x)) {
108,205✔
1684
      /*
1685
       * Cycle in the dependencies: break it by treating x
1686
       * as a variable
1687
       */
1688
      for (i=0; i<n; i++) {
197✔
1689
        l = remap_table_find(rmap, u[i]);
180✔
1690
        if (l == null_literal) {
180✔
1691
          l = bit_blaster_fresh_literal(solver->blaster);
74✔
1692
          remap_table_assign(rmap, u[i], l);
74✔
1693
        }
1694
      }
1695
    } else {
1696
      /*
1697
       * x has not been visited yet
1698
       */
1699
      bvvar_set_mark(vtbl, x);
108,188✔
1700

1701
      switch (op) {
108,188✔
1702
      case BVTAG_VAR:
24,297✔
1703
        // complete u's
1704
        for (i=0; i<n; i++) {
492,968✔
1705
          l = remap_table_find(rmap, u[i]);
468,671✔
1706
          if (l == null_literal) {
468,671✔
1707
            l = bit_blaster_fresh_literal(solver->blaster);
214,286✔
1708
            remap_table_assign(rmap, u[i], l);
214,286✔
1709
          }
1710
        }
1711
        break;
24,297✔
1712

1713
      case BVTAG_CONST64:
36,230✔
1714
      case BVTAG_CONST:
1715
      case BVTAG_BIT_ARRAY:
1716
        // nothing to do: u is complete
1717
        break;
36,230✔
1718

1719
      case BVTAG_POLY64:
12,583✔
1720
      case BVTAG_POLY:
1721
      case BVTAG_PPROD:
1722
        // replace x
1723
        y = bvvar_compiles_to(solver->compiler, x);
12,583✔
1724
        assert(y != null_thvar);
1725
        bv_solver_bitblast_variable(solver, y);
12,583✔
1726
        break;
12,583✔
1727

1728
      case BVTAG_ITE:
18,086✔
1729
        ite = bvvar_ite_def(vtbl, x);
18,086✔
1730
        l = ite->cond;
18,086✔
1731
        y = ite->left;
18,086✔
1732
        z = ite->right;
18,086✔
1733
#if TRACE
1734
        if (l == true_literal || l == false_literal) {
1735
          if (l == true_literal) {
1736
            printf("---> condition in ite is true\n");
1737
          } else {
1738
            printf("---> condition in ite is false\n");
1739
          }
1740
          print_bv_solver_vardef(stdout, solver, x);
1741
          print_bv_solver_vardef(stdout, solver, ite->left);
1742
          print_bv_solver_vardef(stdout, solver, ite->right);
1743
          fflush(stdout);
1744
        }
1745
#endif
1746
        // TODO? check if l is true/false?
1747
        bv_solver_bitblast_variable(solver, y);
18,086✔
1748
        bv_solver_bitblast_variable(solver, z);
18,086✔
1749
        a = &solver->a_vector;
18,086✔
1750
        b = &solver->b_vector;
18,086✔
1751
        collect_bvvar_literals(solver, y, a);
18,086✔
1752
        collect_bvvar_literals(solver, z, b);
18,086✔
1753
        assert(a->size == n && b->size == n);
1754
        bit_blaster_make_bvmux(solver->blaster, l, a->data, b->data, u, n);
18,086✔
1755
        break;
18,086✔
1756

1757
      case BVTAG_UDIV:
383✔
1758
      case BVTAG_UREM:
1759
      case BVTAG_SDIV:
1760
      case BVTAG_SREM:
1761
        y = vtbl->def[x].op[0];
383✔
1762
        z = vtbl->def[x].op[1];
383✔
1763
        bv_solver_bitblast_variable(solver, y);
383✔
1764
        bv_solver_bitblast_variable(solver, z);
383✔
1765
        a = &solver->a_vector;
383✔
1766
        b = &solver->b_vector;
383✔
1767
        collect_bvvar_literals(solver, y, a);
383✔
1768
        collect_bvvar_literals(solver, z, b);
383✔
1769
        assert(a->size == n && b->size == n);
1770
        bit_blaster_make_bvdivop(solver, op, y, z, a->data, b->data, u, n);
383✔
1771
        break;
383✔
1772

1773
      case BVTAG_SMOD:
16,415✔
1774
      case BVTAG_SHL:
1775
      case BVTAG_LSHR:
1776
      case BVTAG_ASHR:
1777
      case BVTAG_ADD:
1778
      case BVTAG_SUB:
1779
      case BVTAG_MUL:
1780
        y = vtbl->def[x].op[0];
16,415✔
1781
        z = vtbl->def[x].op[1];
16,415✔
1782
        bv_solver_bitblast_variable(solver, y);
16,415✔
1783
        bv_solver_bitblast_variable(solver, z);
16,415✔
1784
        a = &solver->a_vector;
16,415✔
1785
        b = &solver->b_vector;
16,415✔
1786
        collect_bvvar_literals(solver, y, a);
16,415✔
1787
        collect_bvvar_literals(solver, z, b);
16,415✔
1788
        assert(a->size == n && b->size == n);
1789
        bit_blaster_make_bvop(solver->blaster, op, a->data, b->data, u, n);
16,415✔
1790
        break;
16,415✔
1791

1792
      case BVTAG_NEG:
194✔
1793
        y = vtbl->def[x].op[0];
194✔
1794
        bv_solver_bitblast_variable(solver, y);
194✔
1795
        a = &solver->a_vector;
194✔
1796
        collect_bvvar_literals(solver, y, a);
194✔
1797
        assert(a->size == n);
1798
        bit_blaster_make_bvneg(solver->blaster, a->data, u, n);
194✔
1799
        break;
194✔
1800
      }
1801
    }
1802

1803
    /*
1804
     * If x occurs on a dependency cycle, it may be bit-blasted now,
1805
     * even though it wasn't when we entered this function.
1806
     * In this case, we don't want to add x twice to the delayed_blasted queue.
1807
     */
1808
    if (! bvvar_is_bitblasted(vtbl, x)) {
108,205✔
1809
      // mark x as bitblasted
1810
      bvvar_set_bitblasted(vtbl, x);
108,188✔
1811
      bvvar_clr_mark(vtbl, x);
108,188✔
1812

1813
      bv_solver_save_delayed_blasted_var(solver, x);
108,188✔
1814
    }
1815

1816
    assert(bvvar_is_bitblasted(vtbl, x));
1817
    assert(! bvvar_is_marked(vtbl, x));
1818
  }
1819
}
190,506✔
1820

1821
/*
1822
 * Bitblast all the atoms
1823
 */
1824
static void bv_solver_bitblast_atoms(bv_solver_t *solver) {
25,323✔
1825
  bv_atomtable_t *atbl;
1826
  ivector_t *a, *b;
1827
  uint32_t i, n;
1828
  literal_t l;
1829
  thvar_t x, y;
1830

1831
  atbl = &solver->atbl;
25,323✔
1832
  n = atbl->natoms;
25,323✔
1833

1834
  a = &solver->a_vector;
25,323✔
1835
  b = &solver->b_vector;
25,323✔
1836

1837
  for (i=solver->bbptr; i<n; i++) {
38,556✔
1838
    l = atbl->data[i].lit;
13,233✔
1839
    x = atbl->data[i].left;
13,233✔
1840
    y = atbl->data[i].right;
13,233✔
1841

1842
    /*
1843
     * NOTE: checking for redundant disequalities here
1844
     * (using bounds_imply_diseq) does not help
1845
     */
1846

1847
#if TRACE
1848
    if (i < solver->bbptr + 20) {
1849
      printf("BVSOLVER: bitblasting atom[%"PRIu32"]: ", i + solver->bbptr);
1850
      print_bv_solver_atom(stdout, solver, i);
1851
      printf("\n");
1852
    } else if (i == solver->bbptr + 20) {
1853
      printf("...\n\n");
1854
    }
1855
#endif
1856

1857
    /*
1858
     * Process operands x and y
1859
     */
1860
    bv_solver_bitblast_variable(solver, x);
13,233✔
1861
    bv_solver_bitblast_variable(solver, y);
13,233✔
1862
    collect_bvvar_literals(solver, x, a);
13,233✔
1863
    collect_bvvar_literals(solver, y, b);
13,233✔
1864
    assert(a->size == b->size && a->size > 0);
1865

1866
    switch (bvatm_tag(atbl->data + i)) {
13,233✔
1867
    case BVEQ_ATM:
6,308✔
1868
      bit_blaster_make_bveq2(solver->blaster, a->data, b->data, l, a->size);
6,308✔
1869
      break;
6,308✔
1870

1871
    case BVUGE_ATM:
3,140✔
1872
      bit_blaster_make_bvuge2(solver->blaster, a->data, b->data, l, a->size);
3,140✔
1873
      break;
3,140✔
1874

1875
    case BVSGE_ATM:
3,785✔
1876
      bit_blaster_make_bvsge2(solver->blaster, a->data, b->data, l, a->size);
3,785✔
1877
      break;
3,785✔
1878
    }
1879
  }
1880

1881
  // save new ptr
1882
  solver->bbptr = n;
25,323✔
1883
}
25,323✔
1884

1885

1886
#ifndef NDEBUG
1887

1888
/*
1889
 * For debugging: all variables must be unmarked when we start bitblasting
1890
 */
1891
static bool all_bvvars_unmarked(bv_solver_t *solver) {
1892
  bv_vartable_t *vtbl;
1893
  uint32_t i, n;
1894

1895
  vtbl = &solver->vtbl;
1896
  n = vtbl->nvars;
1897
  for (i=1; i<n; i++) {
1898
    if (bvvar_is_marked(vtbl, i)) return false;
1899
  }
1900

1901
  return true;
1902
}
1903

1904
#endif
1905

1906

1907
/*
1908
 * Complete bit-blasting:
1909
 * - whenever (x == y) in the merge table, bitblast x and y
1910
 * - if x has an egraph term, then bitblast x
1911
 * - also bit-blast all the variables from the select queue
1912
 */
1913
static void bv_solver_bitblast_variables(bv_solver_t *solver) {
25,323✔
1914
  bv_vartable_t *vtbl;
1915
  bv_queue_t *squeue;
1916
  uint32_t i, n;
1917
  thvar_t x;
1918

1919
  vtbl = &solver->vtbl;
25,323✔
1920
  n = vtbl->nvars;
25,323✔
1921
  for (i=1; i<n; i++) {
237,288✔
1922
    x = mtbl_get_root(&solver->mtbl, i);
211,965✔
1923
    if (x != i) {
211,965✔
1924
      bv_solver_bitblast_variable(solver, x);
15,742✔
1925
      bv_solver_bitblast_variable(solver, i);
15,742✔
1926
    } else if (bvvar_has_eterm(vtbl, i)) {
196,223✔
1927
      bv_solver_bitblast_variable(solver, i);
5,386✔
1928
    }
1929
  }
1930

1931
  squeue = &solver->select_queue;
25,323✔
1932
  n = squeue->top;
25,323✔
1933
  for (i=0; i<n; i++) {
56,464✔
1934
    bv_solver_bitblast_variable(solver, squeue->data[i]);
31,141✔
1935
  }
1936
}
25,323✔
1937

1938

1939

1940
/*
1941
 * Top-level bit-blasting: exported for testing
1942
 */
1943
bool bv_solver_bitblast(bv_solver_t *solver) {
25,324✔
1944
#if DUMP
1945
  bv_solver_dump_state(solver, "before-bitblasting.dmp");
1946
#endif
1947
  bv_solver_prepare_blasting(solver);
25,324✔
1948
  bv_solver_mark_vars_in_atoms(solver);
25,324✔
1949
  bv_solver_mark_merged_vars(solver);
25,324✔
1950
  bv_solver_mark_select_vars(solver);
25,324✔
1951
  bv_solver_compile_polynomials(solver);
25,324✔
1952

1953
  assert(all_bvvars_unmarked(solver));
1954

1955
  if (!bv_solver_make_shared_pseudo_maps(solver)) {
25,324✔
1956
    return false;
1✔
1957
  }
1958

1959
#if DUMP
1960
  bv_solver_dump_state(solver, "after-shared-pmaps.dmp");
1961
#endif
1962

1963
  bv_solver_bitblast_atoms(solver);
25,323✔
1964
  bv_solver_bitblast_variables(solver);
25,323✔
1965

1966
#if DUMP
1967
  bv_solver_dump_state(solver, "before-lemmas.dmp");
1968
#endif
1969

1970
  solver->bitblasted = true;
25,323✔
1971

1972
#if 0
1973
  printf("Statistics\n");
1974
  printf("num. bool vars:                 %"PRIu32"\n", num_vars(solver->core));
1975
  printf("num. unit clauses:              %"PRIu32"\n", num_unit_clauses(solver->core));
1976
  printf("num. binary clauses:            %"PRIu32"\n", num_binary_clauses(solver->core));
1977
  printf("num. main clauses:              %"PRIu32"\n", num_prob_clauses(solver->core));
1978
  printf("num. clause literals:           %"PRIu64"\n\n", num_prob_literals(solver->core));
1979
#endif
1980

1981
  //  printf("\nBVSOLVER BITBLAST\n");
1982
  //  print_solver_state(stdout, solver);
1983
  //  printf("\nDONE\n\n");
1984

1985
  return true;
25,323✔
1986
}
1987

1988

1989
/*
1990
 * Variant for testing: stop before the actual bitblasting
1991
 */
1992
bool bv_solver_compile(bv_solver_t *solver) {
×
1993
#if DUMP
1994
  bv_solver_dump_state(solver, "before-bitblasting.dmp");
1995
#endif
1996
  bv_solver_prepare_blasting(solver);
×
1997
  bv_solver_mark_vars_in_atoms(solver);
×
1998
  bv_solver_mark_merged_vars(solver);
×
1999
  bv_solver_compile_polynomials(solver);
×
2000

2001
  assert(all_bvvars_unmarked(solver));
2002

2003
  if (!bv_solver_make_shared_pseudo_maps(solver)) {
×
2004
    return false;
×
2005
  }
2006

2007
#if DUMP
2008
  bv_solver_dump_state(solver, "after-shared-pmaps.dmp");
2009
#endif
2010

2011
  return true;
×
2012
}
2013

2014

2015

2016
/************************************************
2017
 *  VARIABLES THAT ARE EQUAL AFTER BITBLASTING  *
2018
 ***********************************************/
2019

2020
/*
2021
 * Check whether arrays of pseudo literals a and b are equal
2022
 * - n = number of bits
2023
 */
2024
static bool equal_literal_maps(bv_solver_t *solver, literal_t *a, literal_t *b, uint32_t n) {
3,977✔
2025
  remap_table_t *rmap;
2026
  uint32_t i;
2027
  literal_t l1, l2;
2028

2029
  rmap = solver->remap;
3,977✔
2030
  for (i=0; i<n; i++) {
59,691✔
2031
    l1 = remap_table_find(rmap, a[i]);
55,714✔
2032
    l2 = remap_table_find(rmap, b[i]);
55,714✔
2033
    assert(l1 != null_literal && l2 != null_literal);
2034
    if (l1 != l2) {
55,714✔
2035
      return false;
×
2036
    }
2037
  }
2038

2039
  return true;
3,977✔
2040
}
2041

2042
/*
2043
 * Check whether x and y are bitblasted to the same thing
2044
 */
2045
static bool equal_bitblasting(bv_solver_t *solver, thvar_t x, thvar_t y) {
3,980✔
2046
  bv_vartable_t *vtbl;
2047
  literal_t *a, *b;
2048
  uint32_t n;
2049

2050
  assert(solver->bitblasted);
2051

2052
  vtbl = &solver->vtbl;
3,980✔
2053
  n = bvvar_bitsize(vtbl, x);
3,980✔
2054
  if (n != bvvar_bitsize(vtbl, y)) {
3,980✔
2055
    return false;
3✔
2056
  }
2057

2058
  a = bvvar_get_map(vtbl, x);
3,977✔
2059
  b = bvvar_get_map(vtbl, y);
3,977✔
2060

2061
  assert(a != NULL && b != NULL);
2062
  return equal_literal_maps(solver, a, b, n);
3,977✔
2063
}
2064

2065

2066
/*
2067
 * Hash code for the bitblasting of x
2068
 */
2069
static uint32_t hash_bitblasting(bv_solver_t *solver, thvar_t x) {
9,762✔
2070
  bv_vartable_t *vtbl;
2071
  literal_t *a;
2072
  uint32_t n;
2073

2074
  assert(solver->bitblasted);
2075

2076
  vtbl = &solver->vtbl;
9,762✔
2077
  n = bvvar_bitsize(vtbl, x);
9,762✔
2078
  a = bvvar_get_map(vtbl, x);
9,762✔
2079
  assert(a != NULL);
2080

2081
  return jenkins_hash_intarray(a, n);
9,762✔
2082
}
2083

2084

2085
#if 0
2086
/*
2087
 * Display all bitvector variable in vector v
2088
 */
2089
static void show_partition(bv_solver_t *solver, int32_t *v) {
2090
  uint32_t i, n;
2091

2092
  n = iv_size(v);
2093
  assert(n >= 2);
2094
  for (i=0; i<n; i++) {
2095
    print_bv_solver_var_litarray(stdout, solver, v[i]);
2096
  }
2097
}
2098
#endif
2099

2100
/*
2101
 * Go through vector v: propagate the equality v[0] == v[i] for i=1 ... n
2102
 * to the egraph.
2103
 */
2104
static void propagate_equalities_for_class(bv_solver_t *solver, int32_t *v) {
1,661✔
2105
  bv_vartable_t *vtbl;
2106
  uint32_t i, n;
2107
  eterm_t t, u;
2108

2109
  assert(solver->egraph != NULL);
2110

2111
  vtbl = &solver->vtbl;
1,661✔
2112

2113
  n = iv_size(v);
1,661✔
2114
  assert(n >= 2);
2115

2116
  t = bvvar_get_eterm(vtbl, v[0]);
1,661✔
2117
  assert(t != null_eterm);
2118
  for (i= 1; i<n; i++) {
5,638✔
2119
    u = bvvar_get_eterm(vtbl, v[i]);
3,977✔
2120
    assert(u != null_eterm);
2121
    egraph_propagate_equality(solver->egraph, t, u, EXPL_BV_PROPAGATION, NULL);
3,977✔
2122
  }
2123
}
1,661✔
2124

2125
/*
2126
 * Build an explation for t == u for the egraph
2127
 * - the equality t==u is a strong equality propagated by the previous function
2128
 * - there explanation is empty
2129
 */
2130
static void bv_solver_expand_th_explanation(bv_solver_t *solver, thvar_t t, thvar_t u, void *expl, th_explanation_t *result) {
18✔
2131
  // Nothing to do.
2132
}
18✔
2133

2134

2135

2136
/*
2137
 * Propagate all strong equalities to the egraph
2138
 */
2139
static void propagate_strong_equalities(bv_solver_t *solver) {
12,784✔
2140
  ipart_t partition;
2141
  bv_vartable_t *vtbl;
2142
  uint32_t i, n;
2143

2144
  init_int_partition(&partition, 0, solver, (ipart_hash_fun_t ) hash_bitblasting,
12,784✔
2145
                     (ipart_match_fun_t) equal_bitblasting);
2146

2147
  vtbl = &solver->vtbl;
12,784✔
2148

2149
  n = vtbl->nvars;
12,784✔
2150
  for (i=1; i<n; i++) {
141,459✔
2151
    if (bvvar_has_eterm(vtbl, i)) {
128,675✔
2152
      int_partition_add(&partition, i);
9,762✔
2153
    }
2154
  }
2155

2156

2157
  n = int_partition_nclasses(&partition);
12,784✔
2158
  for (i=0; i<n; i++) {
14,445✔
2159
#if 0
2160
    printf("Strong Eq Class %"PRIu32"\n", i);
2161
    show_partition(solver, partition.classes[i]);
2162
    printf("----\n");
2163
#endif
2164
    propagate_equalities_for_class(solver, partition.classes[i]);
1,661✔
2165
  }
2166

2167
  delete_int_partition(&partition);
12,784✔
2168
}
12,784✔
2169

2170

2171
/******************
2172
 *  BOUND ATOMS   *
2173
 *****************/
2174

2175
/*
2176
 * Check whether x is a constant
2177
 */
2178
static inline bool is_constant(bv_vartable_t *table, thvar_t x) {
87,660✔
2179
  bvvar_tag_t tag;
2180

2181
  tag = bvvar_tag(table, x);
87,660✔
2182
  return (tag == BVTAG_CONST64) | (tag == BVTAG_CONST);
87,660✔
2183
}
2184

2185

2186
/*
2187
 * Check whether x or y is a constant
2188
 */
2189
static inline bool is_bv_bound_pair(bv_vartable_t *table, thvar_t x, thvar_t y) {
1,482✔
2190
  bvvar_tag_t tag_x, tag_y;
2191

2192
  tag_x = bvvar_tag(table, x);
1,482✔
2193
  tag_y = bvvar_tag(table, y);
1,482✔
2194

2195
  return (tag_x == BVTAG_CONST64) | (tag_x == BVTAG_CONST)
1,482✔
2196
    | (tag_y == BVTAG_CONST64) | (tag_y == BVTAG_CONST);
1,482✔
2197
}
2198

2199

2200

2201
/*
2202
 * Check whether atom i is a 'bound atom' (i.e., inequality between
2203
 * a constant and a non-constant).
2204
 * - all atoms are of the form (op x y), we just check whether x
2205
 *   or y is a bitvector constant.
2206
 * - this is fine since no atom should involve two constants
2207
 *   (constraints between constants are always simplified to true or false)
2208
 */
2209
#ifndef NDEBUG
2210
static inline bool is_bound_atom(bv_solver_t *solver, int32_t i) {
2211
  bvatm_t *a;
2212

2213
  a = bvatom_desc(&solver->atbl, i);
2214
  return is_constant(&solver->vtbl, a->left) || is_constant(&solver->vtbl, a->right);
2215
}
2216
#endif
2217

2218
/*
2219
 * Get the variable in a bound atom
2220
 */
2221
static thvar_t bound_atom_var(bv_solver_t *solver, int32_t i) {
1✔
2222
  bvatm_t *a;
2223
  thvar_t x;
2224

2225
  a = bvatom_desc(&solver->atbl, i);
1✔
2226
  x = a->left;
1✔
2227
  if (is_constant(&solver->vtbl, x)) {
1✔
2228
    x = a->right;
1✔
2229
  }
2230

2231
  assert(! is_constant(&solver->vtbl, x));
2232

2233
  return x;
1✔
2234
}
2235

2236

2237
/*
2238
 * Add (bvge x y) to the bound queue
2239
 * - either x or y must be a constant
2240
 * - the atom (bvge x y) must exist in the atom table
2241
 *   and (bvge x y) must not be a trivial atom
2242
 *   (i.e., not of the form (bvge x 0b00000) or (bvge 0b11111 x))
2243
 */
2244
static void push_bvuge_bound(bv_solver_t *solver, thvar_t x, thvar_t y) {
659✔
2245
  int32_t i;
2246

2247
  assert(is_bv_bound_pair(&solver->vtbl, x, y));
2248

2249
  i = find_bvuge_atom(&solver->atbl, x, y);
659✔
2250
  assert(i >= 0 && is_bound_atom(solver, i));
2251
  if (is_constant(&solver->vtbl, x)) {
659✔
2252
    x = y;
241✔
2253
  }
2254

2255
  assert(! is_constant(&solver->vtbl, x));
2256
  bv_bound_queue_push(&solver->bqueue, x, i);
659✔
2257
}
659✔
2258

2259

2260
/*
2261
 * Same thing for (bvsge x y)
2262
 * - the atom must not be of the form (bvsge x 0b100000)
2263
 *   or (bvsge 0b011111 x)
2264
 */
2265
static void push_bvsge_bound(bv_solver_t *solver, thvar_t x, thvar_t y) {
353✔
2266
  int32_t i;
2267

2268
  assert(is_bv_bound_pair(&solver->vtbl, x, y));
2269

2270
  i = find_bvsge_atom(&solver->atbl, x, y);
353✔
2271
  assert(i >= 0 && is_bound_atom(solver, i));
2272
  if (is_constant(&solver->vtbl, x)) {
353✔
2273
    x = y;
178✔
2274
  }
2275

2276
  assert(! is_constant(&solver->vtbl, x));
2277
  bv_bound_queue_push(&solver->bqueue, x, i);
353✔
2278
}
353✔
2279

2280

2281
/*
2282
 * Same thing for (eq x y)
2283
 */
2284
static void push_bvdiseq_bound(bv_solver_t *solver, thvar_t x, thvar_t y) {
919✔
2285
  int32_t i;
2286

2287
  assert(is_bv_bound_pair(&solver->vtbl, x, y));
2288

2289
  i = find_bveq_atom(&solver->atbl, x, y);
919✔
2290
  assert(i >= 0 && is_bound_atom(solver, i));
2291
  if (is_constant(&solver->vtbl, x)) {
919✔
2292
    x = y;
×
2293
  }
2294

2295
  assert(! is_constant(&solver->vtbl, x));
2296
  bv_bound_queue_push(&solver->bqueue, x, i);
919✔
2297
}
919✔
2298

2299

2300

2301
/*
2302
 * Remove all bounds of index >= n
2303
 */
2304
static void bv_solver_remove_bounds(bv_solver_t *solver, uint32_t n) {
37✔
2305
  bv_bound_queue_t *queue;
2306
  bv_bound_t *d;
2307
  uint32_t i;
2308
  thvar_t x;
2309

2310
  queue = &solver->bqueue;
37✔
2311
  assert(0 <= n && n <= queue->top);
2312

2313
  i = queue->top;
37✔
2314
  if (i > 0) {
37✔
2315
    assert(queue->data != NULL);
2316
    d = queue->data + i;
3✔
2317
    while (i > n) {
4✔
2318
      i --;
1✔
2319
      d --;
1✔
2320
      x = bound_atom_var(solver, d->atom_id);
1✔
2321
      assert(0 <= x && x < queue->bsize);
2322
      queue->bound[x] = d->pre;
1✔
2323
    }
2324
    queue->top = n;
3✔
2325
  }
2326
}
37✔
2327

2328

2329

2330
/*
2331
 * SEARCH FOR BOUNDS
2332
 */
2333

2334
/*
2335
 * Check whether a bound atom on x is a lower or upper bound
2336
 * - x must be the variable in bound_atom i
2337
 */
2338
static inline bool lit_is_true(smt_core_t *core, literal_t l) {
1,007✔
2339
  return literal_base_value(core, l) == VAL_TRUE;
1,007✔
2340
}
2341

2342
static inline bool lit_is_false(smt_core_t *core, literal_t l) {
1,011✔
2343
  return literal_base_value(core, l) == VAL_FALSE;
1,011✔
2344
}
2345

2346
// upper bound unsigned
2347
static bool bound_is_ub(bv_solver_t *solver, thvar_t x, int32_t i) {
1,534✔
2348
  bvatm_t *a;
2349

2350
  assert(is_bound_atom(solver, i) && bound_atom_var(solver, i) == x);
2351
  a = bvatom_desc(&solver->atbl, i);
1,534✔
2352
  if (bvatm_is_ge(a)) {
1,534✔
2353
    // either (bvge x c) or (bvge c x)
2354
    return (x == a->left && lit_is_false(solver->core, a->lit)) // (bvge x c) is false so x <= c-1
547✔
2355
      || (x == a->right && lit_is_true(solver->core, a->lit));  // (bvge c x) is true so  x <= c
1,322✔
2356
  }
2357

2358
  return false;
759✔
2359
}
2360

2361
// lower bound unsigned
2362
static bool bound_is_lb(bv_solver_t *solver, thvar_t x, int32_t i) {
1,678✔
2363
  bvatm_t *a;
2364

2365
  assert(is_bound_atom(solver, i) && bound_atom_var(solver, i) == x);
2366
  a = bvatom_desc(&solver->atbl, i);
1,678✔
2367
  if (bvatm_is_ge(a)) {
1,678✔
2368
    // either (bvge x c) or (bvge c x)
2369
    return (x == a->left && lit_is_true(solver->core, a->lit))  // (bvge x c) is true so x >= c
590✔
2370
      || (x == a->right && lit_is_false(solver->core, a->lit)); // (bvge c x) is false so x >= c+1
1,461✔
2371
  }
2372

2373
  return false;
807✔
2374
}
2375

2376
// upper bound signed
2377
static bool bound_is_signed_ub(bv_solver_t *solver, thvar_t x, int32_t i) {
729✔
2378
  bvatm_t *a;
2379

2380
  assert(is_bound_atom(solver, i) && bound_atom_var(solver, i) == x);
2381
  a = bvatom_desc(&solver->atbl, i);
729✔
2382
  if (bvatm_is_sge(a)) {
729✔
2383
    // either (bvsge x c) or (bvsge c x)
2384
    return (x == a->left && lit_is_false(solver->core, a->lit)) // (bvge x c) is false so x <= c-1
161✔
2385
      || (x == a->right && lit_is_true(solver->core, a->lit));  // (bvge c x) is true so  x <= c
344✔
2386
  }
2387

2388
  return false;
546✔
2389
}
2390

2391
// lower bound signed
2392
static bool bound_is_signed_lb(bv_solver_t *solver, thvar_t x, int32_t i) {
730✔
2393
  bvatm_t *a;
2394

2395
  assert(is_bound_atom(solver, i) && bound_atom_var(solver, i) == x);
2396
  a = bvatom_desc(&solver->atbl, i);
730✔
2397
  if (bvatm_is_sge(a)) {
730✔
2398
    // either (bvsge x c) or (bvsge c x)
2399
    return (x == a->left && lit_is_true(solver->core, a->lit))  // (bvsge x c) is true so x >= c
161✔
2400
      || (x == a->right && lit_is_false(solver->core, a->lit)); // (bvsge c x) is false so x >= c+1
344✔
2401
  }
2402

2403
  return false;
547✔
2404
}
2405

2406

2407

2408
/*
2409
 * Extract the unsigned or signed upper bound on x from atom i
2410
 * - x must be a bitvector of 64bits or less
2411
 * - for (bvge x c) false, we know (c > 0b00..0)
2412
 * - for (bvsge x c) false, we know (c > 0b1000)
2413
 * In either case, (c-1) can't cause underflow
2414
 * The result is normalized modulo (2 ^ n) where n = size of x
2415
 */
2416
static uint64_t get_upper_bound64(bv_solver_t *solver, thvar_t x, int32_t i) {
623✔
2417
  bvatm_t *a;
2418
  uint64_t c;
2419
  uint32_t n;
2420

2421
  a = bvatom_desc(&solver->atbl, i);
623✔
2422
  if (x == a->left) {
623✔
2423
    // (bvge x c) false: x <= c-1
2424
    n = bvvar_bitsize(&solver->vtbl, x);
426✔
2425
    c = norm64(bvvar_val64(&solver->vtbl, a->right) - 1, n);
426✔
2426
  } else {
2427
    // (bvge c x) true: x <= c
2428
    assert(x == a->right);
2429
    c = bvvar_val64(&solver->vtbl, a->left);
197✔
2430
  }
2431

2432
  assert(c == norm64(c, bvvar_bitsize(&solver->vtbl, x)));
2433

2434
  return c;
623✔
2435
}
2436

2437

2438
/*
2439
 * Extract the unsigned or signed lower bound
2440
 * - x must be a bitvector of 64bits or less
2441
 * - for (bvge c x) false, we know (c < 0b11111)
2442
 * - for (bvsge c x) false, we know (c < 0b01111)
2443
 * In either case, (c+1) can't cause overflow
2444
 * The result is normalized modulo (2 ^ n)
2445
 */
2446
static uint64_t get_lower_bound64(bv_solver_t *solver, thvar_t x, int32_t i) {
427✔
2447
  bvatm_t *a;
2448
  uint64_t c;
2449
  uint32_t n;
2450

2451
  a = bvatom_desc(&solver->atbl, i);
427✔
2452
  if (x == a->left) {
427✔
2453
    //(bvge x c) true: x >= c
2454
    c = bvvar_val64(&solver->vtbl, a->right);
340✔
2455
  } else {
2456
    // (bvge c x) false: x >= c+1
2457
    assert(x == a->right);
2458
    n = bvvar_bitsize(&solver->vtbl, x);
87✔
2459
    c = norm64(bvvar_val64(&solver->vtbl, a->left) + 1, n);
87✔
2460
  }
2461

2462
  assert(c == norm64(c, bvvar_bitsize(&solver->vtbl, x)));
2463

2464
  return c;
427✔
2465
}
2466

2467

2468

2469
/*
2470
 * Extract the unsigned or signed upper bound on x from atom i
2471
 * - x must be a bitvector of more than 64bits
2472
 * - n = size of x
2473
 * - for (bvge x c) false, we know (c > 0b00..0)
2474
 * - for (bvsge x c) false, we know (c > 0b1000)
2475
 * In either case, (c-1) can't cause underflow
2476
 * The result is returned in c and it's normalized modulo (2 ^ n)
2477
 */
2478
static void get_upper_bound(bv_solver_t *solver, thvar_t x, uint32_t n, int32_t i, bvconstant_t *c) {
×
2479
  bvatm_t *a;
2480

2481
  a = bvatom_desc(&solver->atbl, i);
×
2482
  if (x == a->left) {
×
2483
    // (bvge x c) false: x <= c-1
2484
    bvconstant_copy(c, n, bvvar_val(&solver->vtbl, a->right));
×
2485
    bvconstant_sub_one(c);
×
2486
    bvconstant_normalize(c);
×
2487
  } else {
2488
    // (bvge c x) true: x <= c
2489
    assert(x == a->right);
2490
    bvconstant_copy(c, n, bvvar_val(&solver->vtbl, a->left));
×
2491
  }
2492
}
×
2493

2494

2495
/*
2496
 * Extract the unsigned or signed lower bound on x from atom i
2497
 * - x must be a bitvector of more than 64bits
2498
 * - n = size of x
2499
 * - for (bvge x c) false, we know (c > 0b00..0)
2500
 * - for (bvsge x c) false, we know (c > 0b1000)
2501
 * In either case, (c-1) can't cause underflow
2502
 * The result is returned in c and it's normalized modulo (2 ^ n)
2503
 */
2504
static void get_lower_bound(bv_solver_t *solver, thvar_t x, uint32_t n, int32_t i, bvconstant_t *c) {
4✔
2505
  bvatm_t *a;
2506

2507
  a = bvatom_desc(&solver->atbl, i);
4✔
2508
  if (x == a->left) {
4✔
2509
    // (bvge x c) true: x >= c
2510
    bvconstant_copy(c, n, bvvar_val(&solver->vtbl, a->right));
3✔
2511
  } else {
2512
    // (bvge c x) false: x >= c+1
2513
    assert(x == a->right);
2514
    bvconstant_copy(c, n, bvvar_val(&solver->vtbl, a->left));
1✔
2515
    bvconstant_add_one(c);
1✔
2516
    bvconstant_normalize(c);
1✔
2517
  }
2518
}
4✔
2519

2520

2521

2522
/*
2523
 * Check whether there's a bound asserted on variable x
2524
 * - if so, return true and store the bound in *c
2525
 * - otherwise, return false
2526
 */
2527

2528
// upper bound, 64bits, unsigned
2529
static bool bvvar_has_upper_bound64(bv_solver_t *solver, thvar_t x, uint64_t *c) {
8,827✔
2530
  bv_bound_queue_t *queue;
2531
  bv_bound_t *b;
2532
  int32_t k;
2533

2534
  queue = &solver->bqueue;
8,827✔
2535
  k = bv_bound_for_var(queue, x);
8,827✔
2536
  while (k >= 0) {
9,701✔
2537
    assert(k < queue->top);
2538
    b = queue->data + k;
1,480✔
2539
    if (bound_is_ub(solver, x, b->atom_id)) {
1,480✔
2540
      *c = get_upper_bound64(solver, x, b->atom_id);
606✔
2541
      return true;
606✔
2542
    }
2543
    k = b->pre;
874✔
2544
  }
2545

2546
  return false;
8,221✔
2547
}
2548

2549
// lower bound, 64bits, unsigned
2550
static bool bvvar_has_lower_bound64(bv_solver_t *solver, thvar_t x, uint64_t *c) {
8,827✔
2551
  bv_bound_queue_t *queue;
2552
  bv_bound_t *b;
2553
  int32_t k;
2554

2555
  queue = &solver->bqueue;
8,827✔
2556
  k = bv_bound_for_var(queue, x);
8,827✔
2557
  while (k >= 0) {
10,188✔
2558
    assert(k < queue->top);
2559
    b = queue->data + k;
1,625✔
2560
    if (bound_is_lb(solver, x, b->atom_id)) {
1,625✔
2561
      *c = get_lower_bound64(solver, x, b->atom_id);
264✔
2562
      return true;
264✔
2563
    }
2564
    k = b->pre;
1,361✔
2565
  }
2566

2567
  return false;
8,563✔
2568
}
2569

2570
// upper bound, 64bits, signed
2571
static bool bvvar_has_signed_upper_bound64(bv_solver_t *solver, thvar_t x, uint64_t *c) {
7,705✔
2572
  bv_bound_queue_t *queue;
2573
  bv_bound_t *b;
2574
  int32_t k;
2575

2576
  queue = &solver->bqueue;
7,705✔
2577
  k = bv_bound_for_var(queue, x);
7,705✔
2578
  while (k >= 0) {
8,335✔
2579
    assert(k < queue->top);
2580
    b = queue->data + k;
647✔
2581
    if (bound_is_signed_ub(solver, x, b->atom_id)) {
647✔
2582
      *c = get_upper_bound64(solver, x, b->atom_id);
17✔
2583
      return true;
17✔
2584
    }
2585
    k = b->pre;
630✔
2586
  }
2587

2588
  return false;
7,688✔
2589
}
2590

2591

2592
// lower bound, 64bits, signed
2593
static bool bvvar_has_signed_lower_bound64(bv_solver_t *solver, thvar_t x, uint64_t *c) {
7,705✔
2594
  bv_bound_queue_t *queue;
2595
  bv_bound_t *b;
2596
  int32_t k;
2597

2598
  queue = &solver->bqueue;
7,705✔
2599
  k = bv_bound_for_var(queue, x);
7,705✔
2600
  while (k >= 0) {
8,190✔
2601
    assert(k < queue->top);
2602
    b = queue->data + k;
648✔
2603
    if (bound_is_signed_lb(solver, x, b->atom_id)) {
648✔
2604
      *c = get_lower_bound64(solver, x, b->atom_id);
163✔
2605
      return true;
163✔
2606
    }
2607
    k = b->pre;
485✔
2608
  }
2609

2610
  return false;
7,542✔
2611
}
2612

2613

2614
/*
2615
 * Same thing for bitvectors with more than 64bits
2616
 * - n = number of bits in x
2617
 */
2618

2619
// upper bound, unsigned
2620
static bool bvvar_has_upper_bound(bv_solver_t *solver, thvar_t x, uint32_t n, bvconstant_t *c) {
669✔
2621
  bv_bound_queue_t *queue;
2622
  bv_bound_t *b;
2623
  int32_t k;
2624

2625
  queue = &solver->bqueue;
669✔
2626
  k = bv_bound_for_var(queue, x);
669✔
2627
  while (k >= 0) {
723✔
2628
    assert(k < queue->top);
2629
    b = queue->data + k;
54✔
2630
    if (bound_is_ub(solver, x, b->atom_id)) {
54✔
2631
      get_upper_bound(solver, x, n, b->atom_id, c);
×
2632
      return true;
×
2633
    }
2634
    k = b->pre;
54✔
2635
  }
2636

2637
  return false;
669✔
2638
}
2639

2640
// lower bound, unsigned
2641
static bool bvvar_has_lower_bound(bv_solver_t *solver, thvar_t x, uint32_t n, bvconstant_t *c) {
669✔
2642
  bv_bound_queue_t *queue;
2643
  bv_bound_t *b;
2644
  int32_t k;
2645

2646
  queue = &solver->bqueue;
669✔
2647
  k = bv_bound_for_var(queue, x);
669✔
2648
  while (k >= 0) {
721✔
2649
    assert(k < queue->top);
2650
    b = queue->data + k;
53✔
2651
    if (bound_is_lb(solver, x, b->atom_id)) {
53✔
2652
      get_lower_bound(solver, x, n, b->atom_id, c);
1✔
2653
      return true;
1✔
2654
    }
2655
    k = b->pre;
52✔
2656
  }
2657

2658
  return false;
668✔
2659
}
2660

2661
// upper bound, signed
2662
static bool bvvar_has_signed_upper_bound(bv_solver_t *solver, thvar_t x, uint32_t n, bvconstant_t *c) {
784✔
2663
  bv_bound_queue_t *queue;
2664
  bv_bound_t *b;
2665
  int32_t k;
2666

2667
  queue = &solver->bqueue;
784✔
2668
  k = bv_bound_for_var(queue, x);
784✔
2669
  while (k >= 0) {
866✔
2670
    assert(k < queue->top);
2671
    b = queue->data + k;
82✔
2672
    if (bound_is_signed_ub(solver, x, b->atom_id)) {
82✔
2673
      get_upper_bound(solver, x, n, b->atom_id, c);
×
2674
      return true;
×
2675
    }
2676
    k = b->pre;
82✔
2677
  }
2678

2679
  return false;
784✔
2680
}
2681

2682
// lower bound, signed
2683
static bool bvvar_has_signed_lower_bound(bv_solver_t *solver, thvar_t x, uint32_t n, bvconstant_t *c) {
784✔
2684
  bv_bound_queue_t *queue;
2685
  bv_bound_t *b;
2686
  int32_t k;
2687

2688
  queue = &solver->bqueue;
784✔
2689
  k = bv_bound_for_var(queue, x);
784✔
2690
  while (k >= 0) {
863✔
2691
    assert(k < queue->top);
2692
    b = queue->data + k;
82✔
2693
    if (bound_is_signed_lb(solver, x, b->atom_id)) {
82✔
2694
      get_lower_bound(solver, x, n, b->atom_id, c);
3✔
2695
      return true;
3✔
2696
    }
2697
    k = b->pre;
79✔
2698
  }
2699

2700
  return false;
781✔
2701
}
2702

2703

2704
/*
2705
 * Check whether there's a constraint not (x == 0) on x
2706
 * - this just search for a bound atom of the form (eq x c) or (eq c x)
2707
 *   in the queue
2708
 */
2709
static bool bvvar_is_nonzero(bv_solver_t *solver, thvar_t x) {
13✔
2710
  bv_bound_queue_t *queue;
2711
  bv_bound_t *b;
2712
  bvatm_t *a;
2713
  int32_t k;
2714

2715
  queue = &solver->bqueue;
13✔
2716
  k = bv_bound_for_var(queue, x);
13✔
2717
  while (k >= 0) {
16✔
2718
    assert(k < queue->top);
2719
    b = queue->data + k;
11✔
2720
    a = bvatom_desc(&solver->atbl, b->atom_id);
11✔
2721
    assert(a->left == x || a->right == x);
2722
    if (bvatm_is_eq(a)) {
11✔
2723
      return true;
8✔
2724
    }
2725
    k = b->pre;
3✔
2726
  }
2727

2728
  return false;
5✔
2729
}
2730

2731

2732

2733

2734
/**********************
2735
 *  VARIABLE MERGING  *
2736
 *********************/
2737

2738
/*
2739
 * We attempt to keep the simplest element of the class as
2740
 * root of its class, using the following ranking:
2741
 * - constants are simplest:       rank 0
2742
 * - polynomials                   rank 1
2743
 * - bvarray                       rank 2
2744
 * - power products                rank 3
2745
 * - other non-variable terms:     rank 4
2746
 * - variables are last            rank 5
2747
 *
2748
 * The following functions checks whether a is strictly simpler than b
2749
 * based on this ranking.
2750
 */
2751
static const uint8_t bvtag2rank[NUM_BVTAGS] = {
2752
  5,      // BVTAG_VAR
2753
  0,      // BVTAG_CONST64
2754
  0,      // BVTAG_CONST
2755
  1,      // BVTAG_POLY64
2756
  1,      // BVTAG_POLY
2757
  3,      // BVTAG_PPROD
2758
  2,      // BVTAG_BIT_ARRAY
2759
  4,      // BVTAG_ITE
2760
  4,      // BVTAG_UDIV
2761
  4,      // BVTAG_UREM
2762
  4,      // BVTAG_SDIV
2763
  4,      // BVTAG_SREM
2764
  4,      // BVTAG_SMOD
2765
  4,      // BVTAG_SHL
2766
  4,      // BVTAG_LSHR
2767
  4,      // BVTAG_ASHR
2768
};
2769

2770
static inline bool simpler_bvtag(bvvar_tag_t a, bvvar_tag_t b) {
10,456✔
2771
  return bvtag2rank[a] < bvtag2rank[b];
10,456✔
2772
}
2773

2774

2775

2776
/*
2777
 * Merge the equivalence classes of x and y
2778
 * - both x and y must be root of their class
2779
 * - x and y must be distinct variables
2780
 */
2781
static void bv_solver_merge_vars(bv_solver_t *solver, thvar_t x, thvar_t y) {
10,456✔
2782
  mtbl_t *mtbl;
2783
  bvvar_tag_t tag_x, tag_y;
2784
  thvar_t aux;
2785

2786
  mtbl = &solver->mtbl;
10,456✔
2787

2788
  assert(x != y && mtbl_is_root(mtbl, x) && mtbl_is_root(mtbl, y));
2789

2790
  tag_x = bvvar_tag(&solver->vtbl, x);
10,456✔
2791
  tag_y = bvvar_tag(&solver->vtbl, y);
10,456✔
2792

2793
  if (simpler_bvtag(tag_y, tag_x)) {
10,456✔
2794
    aux = x; x = y; y = aux;
6,157✔
2795
  }
2796

2797
  // x is simpler than y, we set map[y] := x
2798
  mtbl_map(mtbl, y, x);
10,456✔
2799
}
10,456✔
2800

2801

2802

2803

2804
/********************************
2805
 *  SUPPORT FOR SIMPLIFICATION  *
2806
 *******************************/
2807

2808
/*
2809
 * Check whether the root of x's class is a 64bit constant
2810
 * - if so return the root, otherwise return x
2811
 */
2812
static thvar_t bvvar_root_if_const64(bv_solver_t *solver, thvar_t x) {
16,404✔
2813
  thvar_t y;
2814

2815
  y = mtbl_get_root(&solver->mtbl, x);
16,404✔
2816
  if (bvvar_is_const64(&solver->vtbl, y)) {
16,404✔
2817
    x = y;
1,149✔
2818
  }
2819

2820
  return x;
16,404✔
2821
}
2822

2823

2824
/*
2825
 * Check whether the root of x's class is a generic constant
2826
 * - if so return the root, otherwise return x
2827
 */
2828
static thvar_t bvvar_root_if_const(bv_solver_t *solver, thvar_t x) {
661✔
2829
  thvar_t y;
2830

2831
  y = mtbl_get_root(&solver->mtbl, x);
661✔
2832
  if (bvvar_is_const(&solver->vtbl, y)) {
661✔
2833
    x = y;
17✔
2834
  }
2835

2836
  return x;
661✔
2837
}
2838

2839

2840
/*
2841
 * Check whether x is equal to 0b0000...
2842
 */
2843
static bool bvvar_is_zero(bv_vartable_t *vtbl, thvar_t x) {
9,961✔
2844
  uint32_t n, k;
2845

2846
  switch (bvvar_tag(vtbl, x)) {
9,961✔
2847
  case BVTAG_CONST64:
2,641✔
2848
    return bvvar_val64(vtbl, x) == 0;
2,641✔
2849

2850
  case BVTAG_CONST:
128✔
2851
    n = bvvar_bitsize(vtbl, x);
128✔
2852
    k = (n + 31) >> 5;
128✔
2853
    return bvconst_is_zero(bvvar_val(vtbl, x), k);
128✔
2854

2855
  default:
7,192✔
2856
    return false;
7,192✔
2857
  }
2858
}
2859

2860

2861
/*
2862
 * Check whether x is equal to 0b1111...
2863
 */
2864
static bool bvvar_is_minus_one(bv_vartable_t *vtbl, thvar_t x) {
4,360✔
2865
  uint32_t n;
2866

2867
  switch (bvvar_tag(vtbl, x)) {
4,360✔
2868
  case BVTAG_CONST64:
1,262✔
2869
    n = bvvar_bitsize(vtbl, x);
1,262✔
2870
    return bvconst64_is_minus_one(bvvar_val64(vtbl, x), n);
1,262✔
2871

2872
  case BVTAG_CONST:
67✔
2873
    n = bvvar_bitsize(vtbl, x);
67✔
2874
    return bvconst_is_minus_one(bvvar_val(vtbl, x), n);
67✔
2875

2876
  default:
3,031✔
2877
    return false;
3,031✔
2878
  }
2879
}
2880

2881

2882
/*
2883
 * Check whether x is equal to 0b1000...
2884
 */
2885
static bool bvvar_is_min_signed(bv_vartable_t *vtbl, thvar_t x) {
4,058✔
2886
  uint32_t n;
2887

2888
  switch (bvvar_tag(vtbl, x)) {
4,058✔
2889
  case BVTAG_CONST64:
539✔
2890
    n = bvvar_bitsize(vtbl, x);
539✔
2891
    return bvvar_val64(vtbl, x) == min_signed64(n);
539✔
2892

2893
  case BVTAG_CONST:
83✔
2894
    n = bvvar_bitsize(vtbl, x);
83✔
2895
    return bvconst_is_min_signed(bvvar_val(vtbl, x), n);
83✔
2896

2897
  default:
3,436✔
2898
    return false;
3,436✔
2899
  }
2900
}
2901

2902

2903
/*
2904
 * Check whether x is equal to 0b0111...
2905
 */
2906
static bool bvvar_is_max_signed(bv_vartable_t *vtbl, thvar_t x) {
4,040✔
2907
  uint32_t n;
2908

2909
  switch (bvvar_tag(vtbl, x)) {
4,040✔
2910
  case BVTAG_CONST64:
573✔
2911
    n = bvvar_bitsize(vtbl, x);
573✔
2912
    return bvvar_val64(vtbl, x) == max_signed64(n);
573✔
2913

2914
  case BVTAG_CONST:
138✔
2915
    n = bvvar_bitsize(vtbl, x);
138✔
2916
    return bvconst_is_max_signed(bvvar_val(vtbl, x), n);
138✔
2917

2918
  default:
3,329✔
2919
    return false;
3,329✔
2920
  }
2921
}
2922

2923

2924
/*
2925
 * Build the zero constant of n bits
2926
 */
2927
static thvar_t get_zero(bv_solver_t *solver, uint32_t nbits) {
284✔
2928
  thvar_t z;
2929

2930
  if (nbits > 64) {
284✔
2931
    bvconstant_set_all_zero(&solver->aux1, nbits);
38✔
2932
    z = get_bvconst(&solver->vtbl, nbits, solver->aux1.data);
38✔
2933
  } else {
2934
    z = get_bvconst64(&solver->vtbl, nbits, 0);
246✔
2935
  }
2936

2937
  return z;
284✔
2938
}
2939

2940

2941
/*
2942
 * Build the opposite of constant a
2943
 */
2944
static inline thvar_t get_opp_bvconst64(bv_solver_t *solver, uint64_t a, uint32_t nbits) {
870✔
2945
  assert(1 <= nbits && nbits <= 64);
2946
  a = norm64(-a, nbits);
870✔
2947
  return get_bvconst64(&solver->vtbl, nbits, a);
870✔
2948
}
2949

2950
// same thing for a large constant. Use solver->aux1 as buffer.
2951
static thvar_t get_opp_bvconst(bv_solver_t *solver, uint32_t *a, uint32_t nbits) {
122✔
2952
  bvconstant_t *aux;
2953

2954
  assert(nbits > 64);
2955
  aux = &solver->aux1;
122✔
2956
  bvconstant_copy(aux, nbits, a);
122✔
2957
  bvconstant_negate(aux);
122✔
2958
  bvconstant_normalize(aux);
122✔
2959
  return get_bvconst(&solver->vtbl, nbits, aux->data);
122✔
2960
}
2961

2962

2963
/*
2964
 * Check whether p can be written as c0 + a0 t or c0
2965
 * - return true if p has one of these special forms
2966
 * - if p is a constant polynomial, then t is set to null_term
2967
 */
2968
static bool bvpoly64_is_simple(bv_solver_t *solver, bvpoly64_t *p, uint64_t *c0, uint64_t *a0, thvar_t *t) {
5,408✔
2969
  bv_vartable_t *vtbl;
2970
  uint32_t i, n, nbits;
2971
  uint64_t cnst;
2972
  thvar_t x, u;
2973

2974
  vtbl = &solver->vtbl;
5,408✔
2975

2976
  *a0 = 0; // otherwise GCC gives a bogus warning
5,408✔
2977

2978
  n = p->nterms;
5,408✔
2979
  nbits = p->bitsize;
5,408✔
2980
  u = null_thvar;
5,408✔
2981

2982
  cnst = 0;
5,408✔
2983
  i = 0;
5,408✔
2984

2985
  // deal with the constant term of p if any
2986
  if (p->mono[0].var == const_idx) {
5,408✔
2987
    cnst = p->mono[0].coeff;
1,078✔
2988
    i ++;
1,078✔
2989
  }
2990

2991
  // rest of p
2992
  while (i < n) {
10,816✔
2993
    assert(p->mono[i].var != const_idx);
2994

2995
    x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
5,690✔
2996
    if (bvvar_is_const64(vtbl, x)) {
5,690✔
2997
      cnst += p->mono[i].coeff * bvvar_val64(vtbl, x);
6✔
2998
    } else if (u == null_thvar) {
5,684✔
2999
      u = x;
5,402✔
3000
      *a0 = p->mono[i].coeff;
5,402✔
3001
    } else if (u == x) {
282✔
3002
      // two terms of p have the same root u
3003
      *a0 = norm64(*a0 + p->mono[i].coeff, nbits);
×
3004
    } else {
3005
      // p has more than one non-constant term
3006
      return false;
282✔
3007
    }
3008
    i ++;
5,408✔
3009
  }
3010

3011
  // store the result
3012
  *c0 = norm64(cnst, nbits);
5,126✔
3013
  *t = u;
5,126✔
3014

3015
  return true;
5,126✔
3016
}
3017

3018

3019
/*
3020
 * Same thing for p with large coefficients
3021
 */
3022
static bool bvpoly_is_simple(bv_solver_t *solver, bvpoly_t *p, bvconstant_t *c0, bvconstant_t *a0, thvar_t *t) {
145✔
3023
  bv_vartable_t *vtbl;
3024
  uint32_t i, n, nbits, w;
3025
  thvar_t x, u;
3026

3027
  vtbl = &solver->vtbl;
145✔
3028

3029
  n = p->nterms;
145✔
3030
  nbits = p->bitsize;
145✔
3031
  w = p->width;
145✔
3032
  u = null_thvar;
145✔
3033

3034
  i = 0;
145✔
3035

3036
  // c0 := 0 (also make sure c0 has the right size)
3037
  bvconstant_set_all_zero(c0, nbits);
145✔
3038

3039
  // deal with the constant of p if any
3040
  if (p->mono[0].var == const_idx) {
145✔
3041
    bvconst_set(c0->data, w, p->mono[0].coeff);
130✔
3042
    i ++;
130✔
3043
  }
3044

3045
  // check the rest of p
3046
  while (i < n) {
290✔
3047
    assert(p->mono[i].var != const_idx);
3048

3049
    x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
152✔
3050
    if (bvvar_is_const(vtbl, x)) {
152✔
3051
      bvconst_addmul(c0->data, w, p->mono[i].coeff, bvvar_val(vtbl, x));
1✔
3052
    } else if (u == null_thvar) {
151✔
3053
      u = x;
144✔
3054
      bvconstant_copy(a0, nbits, p->mono[i].coeff);
144✔
3055
    } else if (u == x) {
7✔
3056
      assert(a0->bitsize == nbits);
3057
      bvconst_add(a0->data, a0->width, p->mono[i].coeff);
×
3058
      bvconstant_normalize(a0);
×
3059
    } else {
3060
      // p has more than one non-constant term
3061
      return false;
7✔
3062
    }
3063

3064
    i++;
145✔
3065
  }
3066

3067
  bvconstant_normalize(c0);
138✔
3068
  *t = u;
138✔
3069

3070
  return true;
138✔
3071
}
3072

3073

3074

3075
/*********************
3076
 *  EQUALITY CHECKS  *
3077
 ********************/
3078

3079
/*
3080
 * Attempt to simplify (b == 0) to (t == u):
3081
 * - if b is of the form t - u = 0, store t in *vx and u in *vy
3082
 * - if b is of the form t = 0, store t in *vx and zero in *vy
3083
 * - otherwise, leave *vx and *vy unchanged
3084
 * - b is not normalized when this is called
3085
 */
3086
static void simplify_buffer64_eq(bv_solver_t *solver, bvpoly_buffer_t *b, thvar_t *vx, thvar_t *vy) {
225,581✔
3087
  uint64_t a0, a1;
3088
  uint32_t n, nbits;
3089
  thvar_t x, y;
3090

3091
  normalize_bvpoly_buffer(b);
225,581✔
3092
  n = bvpoly_buffer_num_terms(b);
225,581✔
3093
  nbits = bvpoly_buffer_bitsize(b);
225,581✔
3094

3095
  assert(1 <= nbits && nbits <= 64);
3096

3097
  if (n == 2) {
225,581✔
3098
    a0 = bvpoly_buffer_coeff64(b, 0);
211,307✔
3099
    a1 = bvpoly_buffer_coeff64(b, 1);
211,307✔
3100
    x = bvpoly_buffer_var(b, 0);
211,307✔
3101
    y = bvpoly_buffer_var(b, 1);
211,307✔
3102
    if (x == const_idx) {
211,307✔
3103
      if (a1 == 1) {
5,009✔
3104
        // b is a0 + y so (b == 0) iff (y = -a0)
3105
        *vx = y;
870✔
3106
        *vy = get_opp_bvconst64(solver, a0, nbits);
870✔
3107
      } else if (a1 == mask64(nbits)) {
4,139✔
3108
        // b is a0 - y
3109
        *vx = y;
18✔
3110
        *vy = get_bvconst64(&solver->vtbl, nbits, a0);
18✔
3111
      }
3112
    } else if ((a0 == 1 && a1 == mask64(nbits)) || (a1 == 1 && a0 == mask64(nbits))) {
206,298✔
3113
      assert(x != const_idx && y != const_idx);
3114
      *vx = x;
206,231✔
3115
      *vy = y;
206,231✔
3116
    }
3117
  } else if (n == 1) {
14,274✔
3118
    a0 = bvpoly_buffer_coeff64(b, 0);
31✔
3119
    x = bvpoly_buffer_var(b, 0);
31✔
3120
    // we check whether x != const_idx to be safe
3121
    if (x != const_idx && (a0 == 1 || a0 == mask64(nbits))) {
31✔
3122
      *vx = bvpoly_buffer_var(b, 0);
20✔
3123
      *vy = get_zero(solver, nbits);
20✔
3124
    }
3125
  }
3126
}
225,581✔
3127

3128

3129
static void simplify_buffer_eq(bv_solver_t *solver, bvpoly_buffer_t *b, thvar_t *vx, thvar_t *vy) {
187✔
3130
  uint32_t *a0, *a1;
3131
  uint32_t n, nbits, w;
3132
  thvar_t x, y;
3133

3134
  normalize_bvpoly_buffer(b);
187✔
3135
  n = bvpoly_buffer_num_terms(b);
187✔
3136
  nbits = bvpoly_buffer_bitsize(b);
187✔
3137
  w = bvpoly_buffer_width(b);
187✔
3138

3139
  assert(nbits > 64);
3140

3141
  if (n == 2) {
187✔
3142
    a0 = bvpoly_buffer_coeff(b, 0);
141✔
3143
    a1 = bvpoly_buffer_coeff(b, 1);
141✔
3144
    x = bvpoly_buffer_var(b, 0);
141✔
3145
    y = bvpoly_buffer_var(b, 1);
141✔
3146
    if (x == const_idx) {
141✔
3147
      if (bvconst_is_one(a1, w)) {
129✔
3148
        // p is a0 + y
3149
        *vx = y;
122✔
3150
        *vy = get_opp_bvconst(solver, a0, nbits);
122✔
3151
      } else if (bvconst_is_minus_one(a1, nbits)) {
7✔
3152
        // p is a0 - y
3153
        *vx = y;
6✔
3154
        *vy = get_bvconst(&solver->vtbl, nbits, a0);
6✔
3155
      }
3156
    } else if ((bvconst_is_one(a0, w) && bvconst_is_minus_one(a1, nbits)) ||
23✔
3157
               (bvconst_is_one(a1, w) && bvconst_is_minus_one(a0, nbits))) {
13✔
3158
      assert(x != const_idx && y != const_idx);
3159
      *vx = x;
3✔
3160
      *vy = y;
3✔
3161
    }
3162
  } else if (n == 1) {
46✔
3163
    a0 = bvpoly_buffer_coeff(b, 0);
3✔
3164
    x = bvpoly_buffer_var(b, 0);
3✔
3165
    if (x != const_idx &&
6✔
3166
        (bvconst_is_one(a0, w) || bvconst_is_minus_one(a0, nbits))) {
6✔
3167
      *vx = bvpoly_buffer_var(b, 0);
1✔
3168
      *vy = get_zero(solver, nbits);
1✔
3169
    }
3170
  }
3171
}
187✔
3172

3173

3174
/*
3175
 * Attempt to simplify an equality between two polynomials.
3176
 * Rewrite (p = q) to (p - q) = 0. If p - q is of the
3177
 * form t - u then t is stored into *vx and u is stored in *vy.
3178
 * Otherwise, *vx and *vy are left unchanged.
3179
 */
3180
static void simplify_bvpoly64_eq(bv_solver_t *solver, bvpoly64_t *p, bvpoly64_t *q, thvar_t *vx, thvar_t *vy) {
214,670✔
3181
  bvpoly_buffer_t *b;
3182
  uint32_t n, m;
3183

3184
  assert(p->bitsize == q->bitsize);
3185

3186
  n = p->nterms;
214,670✔
3187
  m = q->nterms;
214,670✔
3188

3189
  if (n <= m+2 && m <= n+2) {
214,670✔
3190
    b = &solver->buffer;
214,666✔
3191
    reset_bvpoly_buffer(b, p->bitsize);
214,666✔
3192
    bvpoly_buffer_add_poly64(b, p);
214,666✔
3193
    bvpoly_buffer_sub_poly64(b, q);
214,666✔
3194
    simplify_buffer64_eq(solver, b, vx, vy);
214,666✔
3195
  }
3196
}
214,670✔
3197

3198
// same thing: large coefficients
3199
static void simplify_bvpoly_eq(bv_solver_t *solver, bvpoly_t *p, bvpoly_t *q, thvar_t *vx, thvar_t *vy) {
6✔
3200
  bvpoly_buffer_t *b;
3201
  uint32_t n, m;
3202

3203
  assert(p->bitsize == q->bitsize);
3204

3205
  n = p->nterms;
6✔
3206
  m = q->nterms;
6✔
3207

3208
  if (n <= m+2 && m <= n+2) {
6✔
3209
    b = &solver->buffer;
6✔
3210
    reset_bvpoly_buffer(b, p->bitsize);
6✔
3211
    bvpoly_buffer_add_poly(b, p);
6✔
3212
    bvpoly_buffer_sub_poly(b, q);
6✔
3213
    simplify_buffer_eq(solver, b, vx, vy);
6✔
3214
  }
3215
}
6✔
3216

3217

3218
/*
3219
 * Attempt to simplify an equality between a polynomial p and a constant c
3220
 * - if (p - c) == 0 is of the form (t - u) == 0, then store t in *vx and u in *vy
3221
 * - otherwise leave *vx and *vy unchanged.
3222
 */
3223
static void simplify_bvpoly64_eq_const(bv_solver_t *solver, bvpoly64_t *p, thvar_t c, thvar_t *vx, thvar_t *vy) {
5,270✔
3224
  bvpoly_buffer_t *b;
3225

3226
  assert(bvvar_is_const64(&solver->vtbl, c) && p->bitsize == bvvar_bitsize(&solver->vtbl, c));
3227

3228
  if (p->nterms <= 3) {
5,270✔
3229
    b = &solver->buffer;
5,126✔
3230
    reset_bvpoly_buffer(b, p->bitsize);
5,126✔
3231
    bvpoly_buffer_add_poly64(b, p);
5,126✔
3232
    bvpoly_buffer_sub_const64(b, bvvar_val64(&solver->vtbl, c));
5,126✔
3233
    simplify_buffer64_eq(solver, b, vx, vy);
5,126✔
3234
  }
3235
}
5,270✔
3236

3237
static void simplify_bvpoly_eq_const(bv_solver_t *solver, bvpoly_t *p, thvar_t c, thvar_t *vx, thvar_t *vy) {
135✔
3238
  bvpoly_buffer_t *b;
3239

3240
  assert(bvvar_is_const(&solver->vtbl, c) && p->bitsize == bvvar_bitsize(&solver->vtbl, c));
3241

3242
  if (p->nterms <= 3) {
135✔
3243
    b = &solver->buffer;
135✔
3244
    reset_bvpoly_buffer(b, p->bitsize);
135✔
3245
    bvpoly_buffer_add_poly(b, p);
135✔
3246
    bvpoly_buffer_sub_constant(b, bvvar_val(&solver->vtbl, c));
135✔
3247
    simplify_buffer_eq(solver, b, vx, vy);
135✔
3248
  }
3249
}
135✔
3250

3251

3252
/*
3253
 * Attempt to simplify an equality between p and a term t
3254
 * - t is not a constant
3255
 * - as before, store the result in *vx and *vy
3256
 */
3257
static void simplify_bvpoly64_eq_term(bv_solver_t *solver, bvpoly64_t *p, thvar_t t, thvar_t *vx, thvar_t *vy) {
5,794✔
3258
  bvpoly_buffer_t *b;
3259

3260
  assert(p->bitsize == bvvar_bitsize(&solver->vtbl, t));
3261

3262
  if (p->nterms <= 3) {
5,794✔
3263
    b = &solver->buffer;
5,789✔
3264
    reset_bvpoly_buffer(b, p->bitsize);
5,789✔
3265
    bvpoly_buffer_add_poly64(b, p);
5,789✔
3266
    bvpoly_buffer_sub_var(b, t);
5,789✔
3267
    simplify_buffer64_eq(solver, b, vx, vy);
5,789✔
3268
  }
3269
}
5,794✔
3270

3271
static void simplify_bvpoly_eq_term(bv_solver_t *solver, bvpoly_t *p, thvar_t t, thvar_t *vx, thvar_t *vy) {
47✔
3272
  bvpoly_buffer_t *b;
3273

3274
  assert(p->bitsize == bvvar_bitsize(&solver->vtbl, t));
3275

3276
  if (p->nterms <= 3) {
47✔
3277
    b = &solver->buffer;
46✔
3278
    reset_bvpoly_buffer(b, p->bitsize);
46✔
3279
    bvpoly_buffer_add_poly(b, p);
46✔
3280
    bvpoly_buffer_sub_var(b, t);
46✔
3281
    simplify_buffer_eq(solver, b, vx, vy);
46✔
3282
  }
3283
}
47✔
3284

3285

3286
/*
3287
 * Attempt to simplify (eq x y) to an equivalent equality (eq x' y')
3288
 * - on entry, x and y must be stored in *vx and *vy
3289
 * - x and y must be root in solver->mtbl
3290
 * - on exit, the simplified form is stored in *vx and *vy
3291
 * - return true if the equality was simplified (i.e. if *vx != x or *vy != y)
3292
 */
3293
static bool simplify_eq(bv_solver_t *solver, thvar_t *vx, thvar_t *vy) {
904,427✔
3294
  bv_vartable_t *vtbl;
3295
  thvar_t x, y;
3296
  bvvar_tag_t tag_x, tag_y;
3297

3298
  x = *vx;
904,427✔
3299
  y = *vy;
904,427✔
3300

3301
  assert(x != y && mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
3302

3303
  vtbl = &solver->vtbl;
904,427✔
3304

3305
  tag_x = bvvar_tag(vtbl, x);
904,427✔
3306
  tag_y = bvvar_tag(vtbl, y);
904,427✔
3307

3308
  if (tag_x == tag_y) {
904,427✔
3309
    if (tag_x == BVTAG_POLY64) {
786,583✔
3310
      simplify_bvpoly64_eq(solver, bvvar_poly64_def(vtbl, x), bvvar_poly64_def(vtbl, y), vx, vy);
214,670✔
3311
    } else if (tag_x == BVTAG_POLY) {
571,913✔
3312
      simplify_bvpoly_eq(solver, bvvar_poly_def(vtbl, x), bvvar_poly_def(vtbl, y), vx, vy);
6✔
3313
    }
3314
  } else if (tag_x == BVTAG_POLY64) {
117,844✔
3315
    if (tag_y == BVTAG_CONST64) {
5,336✔
3316
      simplify_bvpoly64_eq_const(solver, bvvar_poly64_def(vtbl, x), y, vx, vy);
4,475✔
3317
    } else {
3318
      simplify_bvpoly64_eq_term(solver, bvvar_poly64_def(vtbl, x), y, vx, vy);
861✔
3319
    }
3320
  } else if (tag_y == BVTAG_POLY64) {
112,508✔
3321
    if (tag_x == BVTAG_CONST64) {
5,728✔
3322
      simplify_bvpoly64_eq_const(solver, bvvar_poly64_def(vtbl, y), x, vx, vy);
795✔
3323
    } else {
3324
      simplify_bvpoly64_eq_term(solver, bvvar_poly64_def(vtbl, y), x, vx, vy);
4,933✔
3325
    }
3326
  } else if (tag_x == BVTAG_POLY) {
106,780✔
3327
    if (tag_y == BVTAG_CONST) {
158✔
3328
      simplify_bvpoly_eq_const(solver, bvvar_poly_def(vtbl, x), y, vx, vy);
135✔
3329
    } else {
3330
      simplify_bvpoly_eq_term(solver, bvvar_poly_def(vtbl, x), y, vx, vy);
23✔
3331
    }
3332
  } else if (tag_y == BVTAG_POLY) {
106,622✔
3333
    if (tag_x == BVTAG_CONST64) {
24✔
3334
      simplify_bvpoly_eq_const(solver, bvvar_poly_def(vtbl, y), x, vx, vy);
×
3335
    } else {
3336
      simplify_bvpoly_eq_term(solver, bvvar_poly_def(vtbl, y), x, vx, vy);
24✔
3337
    }
3338
  }
3339

3340

3341
  if (x != *vx || y != *vy) {
904,427✔
3342
#if 0
3343
    printf("---> bv simplify (bveq u!%"PRId32" u!%"PRId32")\n", x, y);
3344
    printf("     ");
3345
    print_bv_solver_vardef(stdout, solver, x);
3346
    printf("     ");
3347
    print_bv_solver_vardef(stdout, solver, y);
3348
    printf("     simplified to (bveq u!%"PRId32" u!%"PRId32")\n", *vx, *vy);
3349
    if (is_constant(&solver->vtbl, *vx)) {
3350
      printf("     ");
3351
      print_bv_solver_vardef(stdout, solver, *vx);
3352
    }
3353
    if (is_constant(&solver->vtbl, *vy)) {
3354
      printf("     ");
3355
      print_bv_solver_vardef(stdout, solver, *vy);
3356
    }
3357
    printf("\n");
3358
#endif
3359
    *vx = mtbl_get_root(&solver->mtbl, *vx);
207,271✔
3360
    *vy = mtbl_get_root(&solver->mtbl, *vy);
207,271✔
3361

3362
    return true;
207,271✔
3363
  }
3364

3365
  return false;
697,156✔
3366
}
3367

3368

3369
/*
3370
 * Check whether two variables x and y are equal
3371
 * - x and y must be the roots of their equivalence class in the merge table
3372
 */
3373
static inline bool equal_bvvar(bv_solver_t *solver, thvar_t x, thvar_t y) {
1,011,470✔
3374
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
3375
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
3376
  return x == y;
1,011,470✔
3377
}
3378

3379

3380

3381

3382
/*******************
3383
 *  INEQUALITIES   *
3384
 ******************/
3385

3386
/*
3387
 * BOUNDS FOR BIT ARRAYS
3388
 */
3389

3390
/*
3391
 * Number of significant bits in a
3392
 * - a is an array of n literals
3393
 * - this searches for the largest m such that a[m-2] /= a[n-1]
3394
 *
3395
 * This is used to deal with sign-extension. If a is equal to
3396
 * (sign-extend k b) where b has m bits, then this function returns m
3397
 * (or something smaller than m).
3398
 */
3399
static uint32_t bitarray_num_significant_bits(literal_t *a, uint32_t n) {
3,155✔
3400
  literal_t sign;
3401

3402
  assert(0 < n);
3403

3404
  n --;
3,155✔
3405
  sign = a[n]; // sign bit
3,155✔
3406
  while (n > 0) {
37,654✔
3407
    if (a[n - 1] != sign) break;
36,942✔
3408
    n --;
34,499✔
3409
  }
3410
  return n + 1;
3,155✔
3411
}
3412

3413

3414
/*
3415
 * Compute a lower and upper bound on a bitarray a
3416
 * - n = number of bits in a. n must be no more than 64
3417
 * - the bounds are returned in intv
3418
 * - both are normalized modulo 2^n
3419
 */
3420
static void bitarray_bounds_unsigned64(literal_t *a, uint32_t n, bv64_interval_t *intv) {
4,517✔
3421
  uint64_t low, high;
3422
  uint32_t i;
3423

3424
  assert(0 < n && n <= 64);
3425
  low = 0;
4,517✔
3426
  high = mask64(n);    // all bits equal to 1
4,517✔
3427
  for (i=0; i<n; i++) {
96,884✔
3428
    if (a[i] == false_literal) {
92,367✔
3429
      high = clr_bit64(high, i);
22,599✔
3430
    } else if (a[i] == true_literal) {
69,768✔
3431
      low = set_bit64(low, i);
491✔
3432
    }
3433
  }
3434

3435
  assert(low <= high && low == norm64(low, n) && high == norm64(high, n));
3436

3437
  intv->low = low;
4,517✔
3438
  intv->high = high;
4,517✔
3439
  intv->nbits = n;
4,517✔
3440
}
4,517✔
3441

3442

3443
/*
3444
 * Bounds on a, when interpreted as a sign integer in 2s complement representation.
3445
 * This checks whether a is of the form (sign-extend ... b) to get more
3446
 * precise bounds.  (cf. term_utils.c for more details).
3447
 */
3448
static void bitarray_bounds_signed64(literal_t *a, uint32_t n, bv64_interval_t *intv) {
2,677✔
3449
  uint64_t low, high;
3450
  uint32_t i, m;
3451

3452
  assert(0 < n && n <= 64);
3453

3454
  low = 0;
2,677✔
3455
  high = mask64(n);   // all bits equal to 1
2,677✔
3456

3457
  m = bitarray_num_significant_bits(a, n);
2,677✔
3458
  assert(0 < m && m <= n);
3459

3460
  for (i=0; i<m-1; i++) {
23,992✔
3461
    if (a[i] == false_literal) {
21,315✔
3462
      high = clr_bit64(high, i);
670✔
3463
    } else if (a[i] == true_literal) {
20,645✔
3464
      low = set_bit64(low, i);
199✔
3465
    }
3466
  }
3467

3468
  // All the bits from m-1 to n-1 are the same; they are equal to a[n-1].
3469
  if (a[n-1] != true_literal) { // the sign bit may be 0
2,677✔
3470
    for (i=m-1; i<n; i++) {
18,698✔
3471
      high = clr_bit64(high, i);
16,066✔
3472
    }
3473
  }
3474
  if (a[n-1] != false_literal) { // the sign bit may be 1
2,677✔
3475
    for (i=m-1; i<n; i++) {
11,430✔
3476
      low = set_bit64(low, i);
9,505✔
3477
    }
3478
  }
3479

3480
  assert(signed64_ge(high, low, n) && low == norm64(low, n) && high == norm64(high, n));
3481

3482
  intv->low = low;
2,677✔
3483
  intv->high = high;
2,677✔
3484
  intv->nbits = n;
2,677✔
3485
}
2,677✔
3486

3487

3488
/*
3489
 * Lower/upper bounds for a bit array of more than 64bits
3490
 * - both are normalized modulo 2^n and stored in intv
3491
 */
3492
static void bitarray_bounds_unsigned(literal_t *a, uint32_t n, bv_interval_t *intv) {
404✔
3493
  uint32_t i;
3494

3495
  assert(n > 64);
3496

3497
  bv_triv_interval_u(intv, n); // intv->low = 0b00..0, intv->high = 0b111..1
404✔
3498
  for (i=0; i<n; i++) {
45,450✔
3499
    if (a[i] == true_literal) {
45,046✔
3500
      bvconst_set_bit(intv->low, i);
804✔
3501
    } else if (a[i] == false_literal) {
44,242✔
3502
      bvconst_clr_bit(intv->high, i);
12,001✔
3503
    }
3504
  }
3505

3506
  assert(bvconst_is_normalized(intv->low, n) && 
3507
         bvconst_is_normalized(intv->high, n) &&
3508
         bvconst_le(intv->low, intv->high, n));
3509
}
404✔
3510

3511
/*
3512
 * Same for a interpreted as a signed integer.
3513
 */
3514
static void bitarray_bounds_signed(literal_t *a, uint32_t n, bv_interval_t *intv) {
478✔
3515
  uint32_t i, m;
3516

3517
  assert(n > 64);
3518

3519
  bv_triv_interval_s(intv, n); // intv->low = 0b100000, intv->high = 0b011111
478✔
3520

3521
  m = bitarray_num_significant_bits(a, n);
478✔
3522
  assert(0 < m && m <= n);
3523

3524
  for (i=0; i<m-1; i++) {
31,047✔
3525
    if (a[i] == true_literal) {
30,569✔
3526
      bvconst_set_bit(intv->low, i);
454✔
3527
    } else if (a[i] == false_literal) {
30,115✔
3528
      bvconst_clr_bit(intv->high, i);
2,086✔
3529
    }
3530
  }
3531

3532
  // All the bits from m-1 to n-1 are the same; they are equal to a[n-1].
3533
  if (a[n-1] != true_literal) { // the sign bit may be 0
478✔
3534
    for (i=m-1; i<n; i++) {
20,512✔
3535
      bvconst_clr_bit(intv->high, i);
20,048✔
3536
    }
3537
  }
3538
  if (a[n-1] != false_literal) { // the sign bit may be 1
478✔
3539
    for (i=m-1; i<n; i++) {
11,022✔
3540
      bvconst_set_bit(intv->low, i);
10,708✔
3541
    }
3542
  }
3543

3544
  assert(bvconst_is_normalized(intv->low, n) && 
3545
         bvconst_is_normalized(intv->high, n) &&
3546
         bvconst_sle(intv->low, intv->high, n));
3547
}
478✔
3548

3549

3550
/*
3551
 * GENERAL CASE
3552
 */
3553

3554
/*
3555
 * Recursive computation of bounds on a variable x
3556
 * - d = limit on recursion depth
3557
 * - n = number of bits in x
3558
 */
3559
static void bvvar_bounds_u64(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv64_interval_t *intv);
3560
static void bvvar_bounds_s64(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv64_interval_t *intv);
3561
static void bvvar_bounds_u(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv_interval_t *intv);
3562
static void bvvar_bounds_s(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv_interval_t *intv);
3563

3564

3565
/*
3566
 * Bounds on polynomials (unsigned)
3567
 * - d = recursion limit
3568
 */
3569
static void bvpoly64_bounds_u(bv_solver_t *solver, bvpoly64_t *p, uint32_t d, bv64_interval_t *intv) {
1,982✔
3570
  bv64_interval_t aux;
3571
  uint32_t i, n, nbits;
3572
  thvar_t x;
3573

3574
  n = p->nterms;
1,982✔
3575
  nbits = p->bitsize;
1,982✔
3576
  i = 0;
1,982✔
3577

3578
  // constant term if any
3579
  if (p->mono[i].var == const_idx) {
1,982✔
3580
    bv64_point_interval(intv, p->mono[i].coeff, nbits);
1,658✔
3581
    i ++;
1,658✔
3582
  } else {
3583
    bv64_zero_interval(intv, nbits);
324✔
3584
  }
3585

3586
  while (i < n) {
3,027✔
3587
    x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
2,741✔
3588
    bvvar_bounds_u64(solver, x, nbits, d, &aux);
2,741✔
3589
    bv64_interval_addmul_u(intv, &aux, p->mono[i].coeff);
2,741✔
3590
    if (bv64_interval_is_triv_u(intv)) break;
2,741✔
3591
    i ++;
1,045✔
3592
  }
3593
}
1,982✔
3594

3595
// signed bounds
3596
static void bvpoly64_bounds_s(bv_solver_t *solver, bvpoly64_t *p, uint32_t d, bv64_interval_t *intv) {
727✔
3597
  bv64_interval_t aux;
3598
  uint32_t i, n, nbits;
3599
  thvar_t x;
3600

3601
  n = p->nterms;
727✔
3602
  nbits = p->bitsize;
727✔
3603
  i = 0;
727✔
3604

3605
  // constant term
3606
  if (p->mono[i].var == const_idx) {
727✔
3607
    bv64_point_interval(intv, p->mono[i].coeff, nbits);
442✔
3608
    i ++;
442✔
3609
  } else {
3610
    bv64_zero_interval(intv, nbits);
285✔
3611
  }
3612

3613
  while (i < n) {
810✔
3614
    x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
752✔
3615
    bvvar_bounds_s64(solver, x, nbits, d, &aux);
752✔
3616
    bv64_interval_addmul_s(intv, &aux, p->mono[i].coeff);
752✔
3617
    if (bv64_interval_is_triv_s(intv)) break;
752✔
3618
    i ++;
83✔
3619
  }
3620
}
727✔
3621

3622

3623
/*
3624
 * Bounds on polynomials (more than 64bits)
3625
 * - d = recursion limit
3626
 * - intv = where the bounds are stored
3627
 * - solver->intv_stack must be allocated before this is called
3628
 */
3629
static void bvpoly_bounds_u(bv_solver_t *solver, bvpoly_t *p, uint32_t d, bv_interval_t *intv) {
59✔
3630
  bv_interval_t *aux;
3631
  bv_aux_buffers_t *buffers;
3632
  uint32_t i, n, nbits;
3633
  thvar_t x;
3634

3635
  n = p->nterms;
59✔
3636
  nbits = p->bitsize;
59✔
3637

3638
  aux = get_bv_interval(&solver->intv_stack);
59✔
3639
  if (aux == NULL) {
59✔
3640
    // no buffer available: return [0b000.., 0b11...]
3641
    bv_triv_interval_u(intv, n);
×
3642
  } else {
3643

3644
    buffers = get_bv_aux_buffers(&solver->intv_stack);
59✔
3645

3646
    i = 0;
59✔
3647
    if (p->mono[i].var == const_idx) {
59✔
3648
      bv_point_interval(intv, p->mono[i].coeff, nbits);
16✔
3649
      i ++;
16✔
3650
    } else {
3651
      bv_zero_interval(intv, nbits);
43✔
3652
    }
3653

3654
    while (i < n) {
66✔
3655
      x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
61✔
3656
      bvvar_bounds_u(solver, x, nbits, d, aux);
61✔
3657
      bv_interval_addmul_u(intv, aux, p->mono[i].coeff, buffers);
61✔
3658
      if (bv_interval_is_triv_u(intv)) break;
61✔
3659
      i ++;
7✔
3660
    }
3661

3662
    // cleanup
3663
    release_bv_interval(&solver->intv_stack);
59✔
3664
  }
3665
}
59✔
3666

3667
// signed bounds
3668
static void bvpoly_bounds_s(bv_solver_t *solver, bvpoly_t *p, uint32_t d, bv_interval_t *intv) {
62✔
3669
  bv_interval_t *aux;
3670
  bv_aux_buffers_t *buffers;
3671
  uint32_t i, n, nbits;
3672
  thvar_t x;
3673

3674
  n = p->nterms;
62✔
3675
  nbits = p->bitsize;
62✔
3676

3677
  aux = get_bv_interval(&solver->intv_stack);
62✔
3678
  if (aux == NULL) {
62✔
3679
    // no buffer available: return [0b100.., 0b011...]
3680
    bv_triv_interval_s(intv, n);
×
3681
  } else {
3682

3683
    buffers = get_bv_aux_buffers(&solver->intv_stack);
62✔
3684

3685
    i = 0;
62✔
3686
    if (p->mono[i].var == const_idx) {
62✔
3687
      bv_point_interval(intv, p->mono[i].coeff, nbits);
16✔
3688
      i ++;
16✔
3689
    } else {
3690
      bv_zero_interval(intv, nbits);
46✔
3691
    }
3692

3693
    while (i < n) {
85✔
3694
      x = mtbl_get_root(&solver->mtbl, p->mono[i].var);
66✔
3695
      bvvar_bounds_s(solver, x, nbits, d, aux);
66✔
3696
      bv_interval_addmul_s(intv, aux, p->mono[i].coeff, buffers);
66✔
3697
      if (bv_interval_is_triv_s(intv)) break;
66✔
3698
      i ++;
23✔
3699
    }
3700

3701
    // cleanup
3702
    release_bv_interval(&solver->intv_stack);
62✔
3703
  }
3704
}
62✔
3705

3706

3707
/*
3708
 * Lower/upper bounds on (bvurem x y)
3709
 * - x is in op[0]
3710
 * - y is in op[1]
3711
 * - n = number of bits in x and y
3712
 */
3713
static void bvurem64_bounds_u(bv_solver_t *solver, thvar_t op[2], uint32_t n, bv64_interval_t *intv) {
211✔
3714
  bv_vartable_t *vtbl;
3715
  uint64_t b;
3716
  thvar_t y;
3717

3718
  assert(1 <= n && n <= 64);
3719

3720
  // store default bounds: improve the upper bound if y is a constant
3721
  bv64_triv_interval_u(intv, n);
211✔
3722

3723
  vtbl = &solver->vtbl;
211✔
3724
  y = op[1];
211✔
3725
  if (bvvar_is_const64(vtbl, y)) {
211✔
3726
    b = bvvar_val64(vtbl, y);
33✔
3727
    if (b != 0) {
33✔
3728
      // 0 <= (bvurem x y) <= b-1
3729
      intv->high = norm64(b-1, n);
33✔
3730
    }
3731
  }
3732
}
211✔
3733

3734
static void bvurem_bounds_u(bv_solver_t *solver, thvar_t op[2], uint32_t n, bv_interval_t *intv) {
21✔
3735
  bv_vartable_t *vtbl;
3736
  uint32_t *b;
3737
  uint32_t k;
3738
  thvar_t y;
3739

3740
  assert(n > 64);
3741

3742
  bv_triv_interval_u(intv, n);
21✔
3743
  vtbl = &solver->vtbl;
21✔
3744
  y = op[1];
21✔
3745
  if (bvvar_is_const(vtbl, y)) {
21✔
3746
    k = (n + 31) >> 5;
5✔
3747
    b = bvvar_val(vtbl, y);
5✔
3748
    if (bvconst_is_nonzero(b, k)) {
5✔
3749
      // 0 <= (bvurem x y) <= b-1
3750
      bvconst_set(intv->high, k, b);
5✔
3751
      bvconst_sub_one(intv->high, k);
5✔
3752
      assert(bvconst_is_normalized(intv->high, n));
3753
    }
3754
  }
3755
}
21✔
3756

3757

3758
/*
3759
 * Lower/upper bounds on (bvsrem x y) or (bvsmod x y)
3760
 * - x is in op[0]
3761
 * - y is in op[1]
3762
 * - n = number of bits in x and y
3763
 */
3764
static void bvsrem64_bounds_s(bv_solver_t *solver, thvar_t op[2], uint32_t n, bv64_interval_t *intv) {
199✔
3765
  bv_vartable_t *vtbl;
3766
  uint64_t b;
3767
  thvar_t y;
3768

3769
  assert(1 <= n && n <= 64);
3770

3771
  // store default bounds: improve the upper bound if y is a constant
3772
  bv64_triv_interval_s(intv, n);
199✔
3773

3774
  vtbl = &solver->vtbl;
199✔
3775
  y = op[1];
199✔
3776
  if (bvvar_is_const64(vtbl, y)) {
199✔
3777
    b = bvvar_val64(vtbl, y);
31✔
3778
    if (is_neg64(b, n)) {
31✔
3779
      // b < 0 so b + 1 <= (bvsrem x y) <= - b - 1
3780
      intv->low = norm64(b + 1, n);
24✔
3781
      intv->high = norm64(-b -1, n);
24✔
3782
    } else if (b != 0) {
7✔
3783
      // b > 0 so -b+1 <= (bvsrem x y) <= b-1
3784
      intv->low = norm64(-b+1, n);
7✔
3785
      intv->high = norm64(b-1, n);
7✔
3786
    }
3787
    assert(bv64_interval_is_normalized(intv) && signed64_le(intv->low, intv->high, n));
3788
  }
3789
}
199✔
3790

3791
static void bvsrem_bounds_s(bv_solver_t *solver, thvar_t op[2], uint32_t n, bv_interval_t *intv) {
41✔
3792
  bv_vartable_t *vtbl;
3793
  uint32_t *b;
3794
  uint32_t k;
3795
  thvar_t y;
3796

3797
  assert(n > 64);
3798

3799
  bv_triv_interval_s(intv, n);
41✔
3800
  vtbl = &solver->vtbl;
41✔
3801
  y = op[1];
41✔
3802
  if (bvvar_is_const(vtbl, y)) {
41✔
3803
    k = (n + 31) >> 5;
9✔
3804
    b = bvvar_val(vtbl, y);
9✔
3805
    if (bvconst_is_nonzero(b, k)) {
9✔
3806
      if (bvconst_tst_bit(b, n-1)) {
9✔
3807
        // negative divider
3808
        // b + 1 <= (bvsrem x y) <= -(b+1)
3809
        bvconst_set(intv->low, k, b);
6✔
3810
        bvconst_add_one(intv->low, k);
6✔
3811
        bvconst_normalize(intv->low, n); // b+1 needs normalizing if b is -1
6✔
3812
        bvconst_set(intv->high, k, intv->low);
6✔
3813
        bvconst_negate(intv->high, k);
6✔
3814
        bvconst_normalize(intv->high, n);
6✔
3815
      } else {
3816
        // positive divider
3817
        // -(b-1) <= (bvsrem x y) <= b-1
3818
        bvconst_set(intv->high, k, b);
3✔
3819
        bvconst_sub_one(intv->high, k);
3✔
3820
        assert(bvconst_is_normalized(intv->high, n));
3821
        bvconst_set(intv->low, k, intv->high);
3✔
3822
        bvconst_negate(intv->low, k);
3✔
3823
        bvconst_normalize(intv->low, n);
3✔
3824
      }
3825
    }
3826
    assert(bv_interval_is_normalized(intv) && bvconst_sle(intv->low, intv->high, n));
3827
  }
3828
}
41✔
3829

3830

3831
/*
3832
 * Lower/upper bound for a bitvector variable x
3833
 * - n = bitsize of x: must be between 1 and 64
3834
 */
3835
static void bvvar_bounds_u64(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv64_interval_t *intv) {
10,773✔
3836
  bv_vartable_t *vtbl;
3837
  bvvar_tag_t tag_x;
3838
  uint64_t c;
3839

3840
  vtbl = &solver->vtbl;
10,773✔
3841

3842
  assert(valid_bvvar(vtbl, x) && n == bvvar_bitsize(vtbl, x) && 1 <= n && n <= 64);
3843

3844
  tag_x = bvvar_tag(vtbl, x);
10,773✔
3845

3846
  if (tag_x == BVTAG_CONST64) {
10,773✔
3847
    bv64_point_interval(intv, bvvar_val64(vtbl, x), n);
1,946✔
3848
    return;
1,946✔
3849
  }
3850

3851
  if (tag_x == BVTAG_BIT_ARRAY) {
8,827✔
3852
    bitarray_bounds_unsigned64(bvvar_bvarray_def(vtbl, x), n, intv);
4,517✔
3853
  } else if (tag_x == BVTAG_POLY64 && d>0) {
4,310✔
3854
    bvpoly64_bounds_u(solver, bvvar_poly64_def(vtbl, x), d-1, intv);
1,982✔
3855
  } else if (tag_x == BVTAG_UREM) {
2,328✔
3856
    bvurem64_bounds_u(solver, bvvar_binop(vtbl, x), n, intv);
211✔
3857
  } else {
3858
    // default bounds
3859
    bv64_triv_interval_u(intv, n);
2,117✔
3860
  }
3861

3862

3863
  /*
3864
   * Check for better bounds in the bound queue
3865
   *
3866
   * Note: if an asserted lower bound on c is greater than intv->high
3867
   * then the constraints are unsat (but this will be detected later).
3868
   */
3869
  if (bvvar_has_lower_bound64(solver, x, &c) && c > intv->low && c <= intv->high) {
8,827✔
3870
    intv->low = c;
264✔
3871
  }
3872
  if (bvvar_has_upper_bound64(solver, x, &c) && c < intv->high && c >= intv->low) {
8,827✔
3873
    intv->high = c;
598✔
3874
  }
3875

3876
  assert(bv64_interval_is_normalized(intv) && intv->low <= intv->high);
3877
}
3878

3879

3880
/*
3881
 * Same thing for bitvectors interpreted as signed integers.
3882
 */
3883
static void bvvar_bounds_s64(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv64_interval_t *intv) {
9,074✔
3884
  bv_vartable_t *vtbl;
3885
  bvvar_tag_t tag_x;
3886
  uint64_t c;
3887

3888
  vtbl = &solver->vtbl;
9,074✔
3889

3890
  assert(valid_bvvar(vtbl, x) && n == bvvar_bitsize(vtbl, x) && 1 <= n && n <= 64);
3891

3892
  tag_x = bvvar_tag(vtbl, x);
9,074✔
3893

3894
  if (tag_x == BVTAG_CONST64) {
9,074✔
3895
    bv64_point_interval(intv, bvvar_val64(vtbl, x), n);
1,369✔
3896
    return;
1,369✔
3897
  }
3898

3899
  if (tag_x == BVTAG_BIT_ARRAY) {
7,705✔
3900
    bitarray_bounds_signed64(bvvar_bvarray_def(vtbl, x), n, intv);
2,677✔
3901
  } else if (tag_x == BVTAG_POLY64 && d>0) {
5,028✔
3902
    bvpoly64_bounds_s(solver, bvvar_poly64_def(vtbl, x), d-1, intv);
727✔
3903
  } else if (tag_x == BVTAG_SREM || tag_x == BVTAG_SMOD) {
4,301✔
3904
    bvsrem64_bounds_s(solver, bvvar_binop(vtbl, x), n, intv);
199✔
3905
  } else {
3906
    // default bounds
3907
    bv64_triv_interval_s(intv, n);
4,102✔
3908
  }
3909

3910
  /*
3911
   * Check for better bounds in the queue
3912
   */
3913
  if (bvvar_has_signed_lower_bound64(solver, x, &c) && signed64_gt(c, intv->low, n) &&
7,868✔
3914
      signed64_le(c, intv->high, n)) {
163✔
3915
    intv->low = c;
163✔
3916
  }
3917
  if (bvvar_has_signed_upper_bound64(solver, x, &c) && signed64_lt(c, intv->high, n) &&
7,722✔
3918
      signed64_ge(c, intv->low, n)) {
17✔
3919
    intv->high = c;
17✔
3920
  }
3921

3922
  assert(bv64_interval_is_normalized(intv) && signed64_le(intv->low, intv->high, n));
3923
}
3924

3925

3926
/*
3927
 * Lower/upper bound for a bitvector variable x
3928
 * - n = bitsize of x: must be more than 64
3929
 * - the result is stored in intv
3930
 */
3931
static void bvvar_bounds_u(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv_interval_t *intv) {
765✔
3932
  bv_vartable_t *vtbl;
3933
  bvconstant_t *c;
3934
  bvvar_tag_t tag_x;
3935

3936
  vtbl = &solver->vtbl;
765✔
3937

3938
  assert(valid_bvvar(vtbl, x) && n == bvvar_bitsize(vtbl, x) && 64 < n);
3939

3940
  tag_x = bvvar_tag(vtbl, x);
765✔
3941

3942
  if (tag_x == BVTAG_CONST) {
765✔
3943
    bv_point_interval(intv, bvvar_val(vtbl, x), n);
96✔
3944
    return;
96✔
3945
  }
3946

3947
  if (tag_x == BVTAG_BIT_ARRAY) {
669✔
3948
    bitarray_bounds_unsigned(bvvar_bvarray_def(vtbl, x), n, intv);
404✔
3949
  } else if (tag_x == BVTAG_POLY && d > 0) {
265✔
3950
    bvpoly_bounds_u(solver, bvvar_poly_def(vtbl, x), d-1, intv);
59✔
3951
  } else if (tag_x == BVTAG_UREM) {
206✔
3952
    bvurem_bounds_u(solver, bvvar_binop(vtbl, x), n, intv);
21✔
3953
  } else {
3954
    // default bounds
3955
    bv_triv_interval_u(intv, n);
185✔
3956
  }
3957

3958
  /*
3959
   * Check for better bounds in the queue
3960
   */
3961
  c = &solver->aux1;
669✔
3962

3963
  if (bvvar_has_lower_bound(solver, x, n, c) &&
670✔
3964
      bvconst_gt(c->data, intv->low, n) &&
2✔
3965
      bvconst_le(c->data, intv->high, n)) {
1✔
3966
    // c: lower bound on x with c <= intv->high and c > intv->low
3967
    // replace intv->low by c
3968
    assert(bvconstant_is_normalized(c));
3969
    bvconst_set(intv->low, c->width, c->data);
1✔
3970
  }
3971

3972
  if (bvvar_has_upper_bound(solver, x, n, c) &&
669✔
3973
      bvconst_lt(c->data, intv->high, n) &&
×
3974
      bvconst_ge(c->data, intv->low, n)) {
×
3975
    // c: upper bound on x with c >= intv->low and c < intv->high
3976
    // replace intv->high by c
3977
    assert(bvconstant_is_normalized(c));
3978
    bvconst_set(intv->high, c->width, c->data);
×
3979
  }
3980

3981
  assert(bv_interval_is_normalized(intv) && bvconst_le(intv->low, intv->high, n));
3982
}
3983

3984
static void bvvar_bounds_s(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t d, bv_interval_t *intv) {
1,010✔
3985
  bv_vartable_t *vtbl;
3986
  bvconstant_t *c;
3987
  bvvar_tag_t tag_x;
3988

3989
  vtbl = &solver->vtbl;
1,010✔
3990

3991
  assert(valid_bvvar(vtbl, x) && n == bvvar_bitsize(vtbl, x) && 64 < n);
3992

3993
  tag_x = bvvar_tag(vtbl, x);
1,010✔
3994

3995
  if (tag_x == BVTAG_CONST) {
1,010✔
3996
    bv_point_interval(intv, bvvar_val(vtbl, x), n);
226✔
3997
    return;
226✔
3998
  }
3999

4000
  if (tag_x == BVTAG_BIT_ARRAY) {
784✔
4001
    bitarray_bounds_signed(bvvar_bvarray_def(vtbl, x), n, intv);
478✔
4002
  } else if (tag_x == BVTAG_POLY && d > 0) {
306✔
4003
    bvpoly_bounds_s(solver, bvvar_poly_def(vtbl, x), d-1, intv);
62✔
4004
  } else if (tag_x == BVTAG_SREM || tag_x == BVTAG_SMOD) {
244✔
4005
    bvsrem_bounds_s(solver, bvvar_binop(vtbl, x), n, intv);
41✔
4006
  } else {
4007
    // default bounds
4008
    bv_triv_interval_s(intv, n);
203✔
4009
  }
4010

4011
  /*
4012
   * Check for better bounds in the queue
4013
   */
4014
  c = &solver->aux1;
784✔
4015

4016
  if (bvvar_has_signed_lower_bound(solver, x, n, c) &&
787✔
4017
      bvconst_sgt(c->data, intv->low, n) &&
6✔
4018
      bvconst_sle(c->data, intv->high, n)) {
3✔
4019
    // c: lower bound on x with c <= intv->high and c > intv->low
4020
    // replace intv->low by c
4021
    assert(bvconstant_is_normalized(c));
4022
    bvconst_set(intv->low, c->width, c->data);
3✔
4023
  }
4024

4025
  if (bvvar_has_signed_upper_bound(solver, x, n, c) &&
784✔
4026
      bvconst_slt(c->data, intv->high, n) &&
×
4027
      bvconst_sge(c->data, intv->low, n)) {
×
4028
    // c: upper bound on x with c >= intv->low and c < intv->high
4029
    // replace intv->high by c
4030
    assert(bvconstant_is_normalized(c));
4031
    bvconst_set(intv->high, c->width, c->data);
×
4032
  }
4033

4034
  assert(bv_interval_is_normalized(intv) && bvconst_sle(intv->low, intv->high, n));
4035
}
4036

4037

4038
/*
4039
 * SIMPLIFY INEQUALITIES
4040
 */
4041

4042
/*
4043
 * Three possible codes returned by the  'check_bvuge' and 'check_bvsge' functions
4044
 * - the order matters: we want BVTEST_FALSE = 0 = false and BVTEST_TRUE = 1 = true
4045
 */
4046
typedef enum {
4047
  BVTEST_FALSE = 0,
4048
  BVTEST_TRUE,
4049
  BVTEST_UNKNOWN,
4050
} bvtest_code_t;
4051

4052

4053
#define MAX_RECUR_DEPTH 4
4054

4055
/*
4056
 * Check whether (x >= y) simplifies (unsigned)
4057
 * - n = number of bits in x and y
4058
 * - both x and y must be 64bits or less
4059
 */
4060
static bvtest_code_t check_bvuge64_core(bv_solver_t *solver, thvar_t x, thvar_t y, uint32_t n) {
3,408✔
4061
  bv64_interval_t intv_x, intv_y;
4062

4063
  bvvar_bounds_u64(solver, x, n, MAX_RECUR_DEPTH, &intv_x);  // intv_x.low <= x <= intv_x.high
3,408✔
4064
  bvvar_bounds_u64(solver, y, n, MAX_RECUR_DEPTH, &intv_y);  // intv_y.low <= y <= intv_y.high
3,408✔
4065

4066
  if (intv_x.low >= intv_y.high) {
3,408✔
4067
    return BVTEST_TRUE;
270✔
4068
  }
4069

4070
  if (intv_x.high < intv_y.low) {
3,138✔
4071
    return BVTEST_FALSE;
183✔
4072
  }
4073

4074
  return BVTEST_UNKNOWN;
2,955✔
4075
}
4076

4077

4078
/*
4079
 * Check whether (x >= y) simplifies (unsigned)
4080
 * - n = number of bits in x and y
4081
 * - both x and y must be more than 64bits
4082
 */
4083
static bvtest_code_t check_bvuge_core(bv_solver_t *solver, thvar_t x, thvar_t y, uint32_t n) {
341✔
4084
  bv_interval_t *bounds_x, *bounds_y;
4085

4086
  // prepare interval stack
4087
  alloc_bv_interval_stack(&solver->intv_stack);
341✔
4088
  bounds_x = get_bv_interval(&solver->intv_stack);
341✔
4089
  bounds_y = get_bv_interval(&solver->intv_stack);
341✔
4090

4091
  assert(bounds_x != NULL && bounds_y != NULL);
4092

4093
  bvvar_bounds_u(solver, x, n, MAX_RECUR_DEPTH, bounds_x);  // bounds_x.low <= x <= bounds_x.high
341✔
4094
  bvvar_bounds_u(solver, y, n, MAX_RECUR_DEPTH, bounds_y);  // bounds_y.low <= y <= bounds_y.high
341✔
4095

4096

4097
  /*
4098
   * hack: empty the interval stack here
4099
   * bounds_x and bounds_y are still good pointers in stack->data
4100
   */
4101
  assert(solver->intv_stack.top == 2);
4102
  release_all_bv_intervals(&solver->intv_stack);
341✔
4103

4104
  if (bvconst_ge(bounds_x->low, bounds_y->high, n)) {
341✔
4105
    return BVTEST_TRUE;
24✔
4106
  }
4107

4108
  if (bvconst_lt(bounds_x->high, bounds_y->low, n)) {
317✔
4109
    return BVTEST_FALSE;
4✔
4110
  }
4111

4112
  return BVTEST_UNKNOWN;
313✔
4113
}
4114

4115

4116
/*
4117
 * Check whether (x >= y) simplifies (unsigned)
4118
 * - x and y must be roots in the merge table
4119
 * - Return BVTEST_FALSE if (x > y) is known to hold
4120
 * - return BVTEST_TRUE  if (x >= y) is known to hold
4121
 * - return BVTEST_UNKNOWN otherwise
4122
 */
4123
static bvtest_code_t check_bvuge(bv_solver_t *solver, thvar_t x, thvar_t y) {
3,777✔
4124
  uint32_t n;
4125
  bvtest_code_t code;
4126

4127
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
4128
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
4129

4130
  if (x == y) return BVTEST_TRUE;
3,777✔
4131

4132
  n = bvvar_bitsize(&solver->vtbl, x);
3,749✔
4133

4134
  if (n <= 64) {
3,749✔
4135
    code = check_bvuge64_core(solver, x, y, n);
3,408✔
4136
  } else {
4137
    code = check_bvuge_core(solver, x, y, n);
341✔
4138
  }
4139

4140
  return code;
3,749✔
4141
}
4142

4143

4144
/*
4145
 * Check whether (x >= y) simplifies (signed comparison)
4146
 * - n = number of bits in x and y
4147
 * - both x and y must be 64 bits or less
4148
 */
4149
static bvtest_code_t check_bvsge64_core(bv_solver_t *solver, thvar_t x, thvar_t y, uint32_t n) {
3,555✔
4150
  bv64_interval_t intv_x, intv_y;
4151

4152
  bvvar_bounds_s64(solver, x, n, MAX_RECUR_DEPTH, &intv_x);  // intv_x.low <= x <= intv_x.high
3,555✔
4153
  bvvar_bounds_s64(solver, y, n, MAX_RECUR_DEPTH, &intv_y);  // intv_y.low <= y <= intv_y.high
3,555✔
4154

4155
  if (signed64_ge(intv_x.low, intv_y.high, n)) { // lx >= uy
3,555✔
4156
    return BVTEST_TRUE;
90✔
4157
  }
4158

4159
  if (signed64_lt(intv_x.high, intv_y.low, n)) { // ux < ly
3,465✔
4160
    return BVTEST_FALSE;
43✔
4161
  }
4162

4163
  return BVTEST_UNKNOWN;
3,422✔
4164
}
4165

4166

4167
/*
4168
 * Check whether (x >= y) simplifies (signed comparison)
4169
 * - n = number of bits in x and y
4170
 * - both x and y must be more than 64 bits
4171
 */
4172
static bvtest_code_t check_bvsge_core(bv_solver_t *solver, thvar_t x, thvar_t y, uint32_t n) {
461✔
4173
  bv_interval_t *bounds_x, *bounds_y;
4174

4175
  // prepare interval stack
4176
  alloc_bv_interval_stack(&solver->intv_stack);
461✔
4177
  bounds_x = get_bv_interval(&solver->intv_stack);
461✔
4178
  bounds_y = get_bv_interval(&solver->intv_stack);
461✔
4179

4180
  assert(bounds_x != NULL && bounds_y != NULL);
4181

4182
  bvvar_bounds_s(solver, x, n, MAX_RECUR_DEPTH, bounds_x);  // bounds_x.low <= x <= bounds_x.high
461✔
4183
  bvvar_bounds_s(solver, y, n, MAX_RECUR_DEPTH, bounds_y);  // bounds_y.low <= y <= bounds_y.high
461✔
4184

4185
  /*
4186
   * hack: empty the interval stack here
4187
   * bounds_x and bounds_y are still good pointers in stack->data
4188
   */
4189
  assert(solver->intv_stack.top == 2);
4190
  release_all_bv_intervals(&solver->intv_stack);
461✔
4191

4192
  if (bvconst_sge(bounds_x->low, bounds_y->high, n)) {
461✔
4193
    return BVTEST_TRUE;
16✔
4194
  }
4195

4196
  if (bvconst_slt(bounds_x->high, bounds_y->low, n)) {
445✔
4197
    return BVTEST_FALSE;
11✔
4198
  }
4199

4200
  return BVTEST_UNKNOWN;
434✔
4201
}
4202

4203

4204
/*
4205
 * Check whether (x <= y) simplifies (signed)
4206
 * - x and y must be roots in the merge table
4207
 * - return BVTEST_FALSE if (x > y) is known to hold
4208
 * - return BVTEST_TRUE  if (x >= y) is known to hold
4209
 * - return BVTEST_UNKNOWN otherwise
4210
 */
4211
static bvtest_code_t check_bvsge(bv_solver_t *solver, thvar_t x, thvar_t y) {
4,030✔
4212
  uint32_t n;
4213
  bvtest_code_t code;
4214

4215
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
4216
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
4217

4218
  if (x == y) return BVTEST_TRUE;
4,030✔
4219

4220
  n = bvvar_bitsize(&solver->vtbl, x);
4,016✔
4221

4222
  if (n <= 64) {
4,016✔
4223
    code = check_bvsge64_core(solver, x, y, n);
3,555✔
4224
  } else {
4225
    code = check_bvsge_core(solver, x, y, n);
461✔
4226
  }
4227

4228
  return code;
4,016✔
4229
}
4230

4231

4232
/*
4233
 * Check whether (x >= y) simplifies to (y == x)
4234
 * - x and y must be roots in the merge table
4235
 * - returns true if (y >= x) has been asserted as an axiom
4236
 */
4237
static bool bvuge_simplifies_to_bveq(bv_solver_t *solver, thvar_t x, thvar_t y) {
1,000✔
4238
  bvatm_t *a;
4239
  int32_t i;
4240

4241
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
4242
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
4243

4244
  i = find_bvuge_atom(&solver->atbl, y, x); // atom (bvuge y x)
1,000✔
4245
  if (i >= 0) {
1,000✔
4246
    a = bvatom_desc(&solver->atbl, i);
6✔
4247
    return lit_is_true(solver->core, a->lit); // check whether (bvuge y x) is true 
6✔
4248
  }
4249
  return false;
994✔
4250
}
4251

4252

4253
// same thing for signed comparison
4254
static bool bvsge_simplifies_to_bveq(bv_solver_t *solver, thvar_t x, thvar_t y) {
388✔
4255
  bvatm_t *a;
4256
  int32_t i;
4257

4258
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
4259
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
4260

4261
  i = find_bvsge_atom(&solver->atbl, y, x); // atom (bvsge y x)
388✔
4262
  if (i >= 0) {
388✔
4263
    a = bvatom_desc(&solver->atbl, i);
×
4264
    return lit_is_true(solver->core, a->lit); // check whether (bvsge y x) is true 
×
4265
  }
4266
  return false;  
388✔
4267
}
4268

4269

4270

4271
/************************
4272
 *  DISEQUALITY CHECKS  *
4273
 ***********************/
4274

4275
/*
4276
 * Check whether two bitarrays a and b are distinct
4277
 * - n = size of both arrays
4278
 * - return true if a and b can't be equal, false if we don't know
4279
 * - for now, this returns true if there's an
4280
 *   index i such that a[i] = not b[i]
4281
 */
4282
static bool diseq_bitarrays(literal_t *a, literal_t *b, uint32_t n) {
140,826✔
4283
  uint32_t i;
4284

4285
  for (i=0; i<n; i++) {
1,286,438✔
4286
    if (opposite(a[i], b[i])) {
1,145,614✔
4287
      return true;
2✔
4288
    }
4289
  }
4290

4291
  return false;
140,824✔
4292
}
4293

4294

4295
/*
4296
 * Check whether bit array a and small constant c must differ.
4297
 * - n = number of bits in a (and c)
4298
 */
4299
static bool diseq_bitarray_const64(literal_t *a, uint64_t c, uint32_t n) {
2,350✔
4300
  uint32_t i;
4301

4302
  assert(n <= 64);
4303

4304
  /*
4305
   * We use the fact that true_literal = 0 and false_literal = 1
4306
   * So (bit i of c) == a[i] implies a != c
4307
   */
4308
  assert(true_literal == 0 && false_literal == 1);
4309

4310
  for (i=0; i<n; i++) {
36,632✔
4311
    if (((int32_t) (c & 1)) == a[i]) {
34,805✔
4312
      return true;
523✔
4313
    }
4314
    c >>= 1;
34,282✔
4315
  }
4316

4317
  return false;
1,827✔
4318
}
4319

4320

4321
/*
4322
 * Same thing for a constant c with more than 64bits
4323
 */
4324
static bool diseq_bitarray_const(literal_t *a, uint32_t *c, uint32_t n) {
424✔
4325
  uint32_t i;
4326

4327
  assert(n >= 64);
4328

4329
  /*
4330
   * Same trick as above:
4331
   * - bvconst_tst_bit(c, i) = bit i of c = either 0 or 1
4332
   */
4333
  assert(true_literal == 0 && false_literal == 1);
4334

4335
  for (i=0; i<n; i++) {
53,924✔
4336
    if (bvconst_tst_bit(c, i) == a[i]) {
53,512✔
4337
      return true;
12✔
4338
    }
4339
  }
4340

4341
  return false;
412✔
4342
}
4343

4344

4345
/*
4346
 * Check whether x and constant c can't be equal
4347
 * - n = number of bits
4348
 * - d = recursion limit
4349
 */
4350
static bool diseq_bvvar_const64(bv_solver_t *solver, thvar_t x, uint64_t c, uint32_t n, uint32_t d) {
15,225✔
4351
  bv_vartable_t *vtbl;
4352
  uint64_t c0, a0;
4353
  thvar_t t;
4354

4355
  assert(bvvar_bitsize(&solver->vtbl, x) == n && 1 <= n && n <= 64);
4356
  assert(c == norm64(c, n));
4357

4358
  vtbl = &solver->vtbl;
15,225✔
4359

4360
  while (d > 0) {
16,218✔
4361
    /*
4362
     * In this loop, we rewrite (x != c) to
4363
     * true or false, or to an equivalent disequality (x' != c')
4364
     */
4365

4366
    // in bvpoly64_is_simple, we follow the roots
4367
    // this could cause looping so we force exit when d == 0
4368
    d --;
16,212✔
4369

4370
    // x should be a root in mtbl
4371
    assert(x == mtbl_get_root(&solver->mtbl, x));
4372

4373
    switch (bvvar_tag(vtbl, x)) {
16,212✔
4374
    case BVTAG_CONST64:
204✔
4375
      return bvvar_val64(vtbl, x) != c;
204✔
4376

4377
    case BVTAG_BIT_ARRAY:
2,350✔
4378
      return diseq_bitarray_const64(bvvar_bvarray_def(vtbl, x), c, n);
2,350✔
4379

4380
    case BVTAG_POLY64:
5,408✔
4381
      if (bvpoly64_is_simple(solver, bvvar_poly64_def(vtbl, x), &c0, &a0, &t)) {
5,408✔
4382
        if (t == null_thvar || a0 == 0) {
5,126✔
4383
          // x is equal to c0
4384
          return (c0 != c);
6✔
4385
        } else if (a0 == 1) {
5,120✔
4386
          // x is equal to c0 + t
4387
          // so (x != c) is equivalent to (t != c - c0);
4388
          x = t;
962✔
4389
          c = norm64(c - c0, n);
962✔
4390
          continue;
962✔
4391
        } else if (a0 == mask64(n)) { // a0 = -1
4,158✔
4392
          // x is equal to c0 - t
4393
          // so (x != c) is equivalent to t != c0 - c
4394
          x = t;
31✔
4395
          c = norm64(c0 - c, n);
31✔
4396
          continue;
31✔
4397
        }
4398
      }
4399

4400
      /*
4401
       * Fall through intended: if x is a poly of the wrong form
4402
       */
4403
    default:
4404
      return false;
12,659✔
4405
    }
4406
  }
4407

4408
  // default answer if d == 0: don't know
4409
  return false;
6✔
4410
}
4411

4412

4413
/*
4414
 * Same thing for size > 64
4415
 * - the function uses aux2 and aux3 as buffers so c must not be one of them
4416
 */
4417
static bool diseq_bvvar_const(bv_solver_t *solver, thvar_t x, bvconstant_t *c, uint32_t n, uint32_t d) {
565✔
4418
  bv_vartable_t *vtbl;
4419
  bvconstant_t *c0, *a0;
4420
  thvar_t t;
4421

4422
  assert(bvvar_bitsize(&solver->vtbl, x) == n && n > 64);
4423
  assert(c->bitsize == n &&  bvconstant_is_normalized(c));
4424
  assert(c != &solver->aux2 && c != &solver->aux3);
4425

4426
  vtbl = &solver->vtbl;
565✔
4427

4428
  while (d > 0) {
700✔
4429
    /*
4430
     * In this loop, we rewrite (x != c) to
4431
     * true or false, or to an equivalent disequality (x' != c')
4432
     */
4433

4434
    d --;
700✔
4435

4436
    // x should be a root in mtbl
4437
    assert(x == mtbl_get_root(&solver->mtbl, x));
4438

4439
    switch (bvvar_tag(vtbl, x)) {
700✔
4440
    case BVTAG_CONST:
25✔
4441
      return bvconst_neq(bvvar_val(vtbl, x), c->data, c->width);
25✔
4442

4443
    case BVTAG_BIT_ARRAY:
424✔
4444
      return diseq_bitarray_const(bvvar_bvarray_def(vtbl, x), c->data, n);
424✔
4445

4446
    case BVTAG_POLY:
145✔
4447
      c0 = &solver->aux2;
145✔
4448
      a0 = &solver->aux3;
145✔
4449
      if (bvpoly_is_simple(solver, bvvar_poly_def(vtbl, x), c0, a0, &t)) {
145✔
4450
        assert(c0->bitsize == n && bvconstant_is_normalized(c0));
4451
        assert(t == null_thvar || (a0->bitsize == n && bvconstant_is_normalized(a0)));
4452

4453
        if (t == null_thvar || bvconstant_is_zero(a0)) {
138✔
4454
          // x is equal to c0
4455
          return bvconst_neq(c0->data, c->data, c->width);
1✔
4456
        } else if (bvconstant_is_one(a0)) {
137✔
4457
          // x is equal to c0 + t
4458
          // so (x != c) is equivalent to (t != c - c0);
4459
          x = t;
128✔
4460
          // compute c := c - c0
4461
          bvconst_sub(c->data, c->width, c0->data);
128✔
4462
          bvconstant_normalize(c);
128✔
4463
          continue;
128✔
4464
        } else if (bvconstant_is_minus_one(a0)) {
9✔
4465
          // x is equal to c0 - t
4466
          // so (x != c) is equivalent to t != c0 - c
4467
          x = t;
7✔
4468
          // compute c:= c0 - c, normalized
4469
          bvconst_sub(c->data, c->width, c0->data);
7✔
4470
          bvconst_negate(c->data, c->width);
7✔
4471
          bvconstant_normalize(c);
7✔
4472
          continue;
7✔
4473
        }
4474
      }
4475

4476
      /*
4477
       * Fall through intended: if x is a poly of the wrong form
4478
       */
4479
    default:
4480
      return false;
115✔
4481
    }
4482

4483
  }
4484

4485
  // default answer if d == 0: don't know
4486
  return false;
×
4487
}
4488

4489

4490
/*
4491
 * Recursion limit for diseq checks
4492
 */
4493
#define MAX_DISEQ_RECUR_DEPTH 4
4494

4495
/*
4496
 * Top-level disequality check
4497
 * - x and y must be roots of their equivalence class in the merge table
4498
 */
4499
static bool diseq_bvvar(bv_solver_t *solver, thvar_t x, thvar_t y) {
571,054✔
4500
  bv_vartable_t *vtbl;
4501
  bvconstant_t *c;
4502
  bvvar_tag_t tag_x, tag_y;
4503
  uint32_t n;
4504

4505
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
4506
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
4507

4508
  if (x == y) return false;
571,054✔
4509

4510
  vtbl = &solver->vtbl;
571,054✔
4511
  tag_x = bvvar_tag(vtbl, x);
571,054✔
4512
  tag_y = bvvar_tag(vtbl, y);
571,054✔
4513

4514
  n = bvvar_bitsize(vtbl, x);
571,054✔
4515
  if (n <= 64) {
571,054✔
4516
    if (tag_x == BVTAG_CONST64) {
570,126✔
4517
      return diseq_bvvar_const64(solver, y, bvvar_val64(vtbl, x), n, MAX_DISEQ_RECUR_DEPTH);
6,404✔
4518
    }
4519

4520
    if (tag_y == BVTAG_CONST64) {
563,722✔
4521
      return diseq_bvvar_const64(solver, x, bvvar_val64(vtbl, y), n, MAX_DISEQ_RECUR_DEPTH);
8,821✔
4522
    }
4523

4524
    if (tag_x == BVTAG_POLY64 && tag_y == BVTAG_POLY64) {
554,901✔
4525
      return disequal_bvpoly64(bvvar_poly64_def(vtbl, x), bvvar_poly64_def(vtbl, y));
109,116✔
4526
    }
4527

4528
    if (tag_x == BVTAG_BIT_ARRAY && tag_y == BVTAG_BIT_ARRAY) {
445,785✔
4529
      return diseq_bitarrays(bvvar_bvarray_def(vtbl, x), bvvar_bvarray_def(vtbl, y), n);
140,739✔
4530
    }
4531

4532
    if (tag_x == BVTAG_POLY64 && tag_y != BVTAG_CONST64) {
305,046✔
4533
      return bvpoly64_is_const_plus_var(bvvar_poly64_def(vtbl, x), y);
712✔
4534
    }
4535

4536
    if (tag_y == BVTAG_POLY64 && tag_x != BVTAG_CONST64) {
304,334✔
4537
      return bvpoly64_is_const_plus_var(bvvar_poly64_def(vtbl, y), x);
2,837✔
4538
    }
4539

4540
  } else {
4541

4542
    // More than 64bits
4543
    if (tag_x == BVTAG_CONST) {
928✔
4544
      c = &solver->aux1;
163✔
4545
      bvconstant_copy(c, n, bvvar_val(vtbl, x));
163✔
4546
      return diseq_bvvar_const(solver, y, c, n, MAX_DISEQ_RECUR_DEPTH);
163✔
4547
    }
4548

4549
    if (tag_y == BVTAG_CONST) {
765✔
4550
      c = &solver->aux1;
402✔
4551
      bvconstant_copy(c, n, bvvar_val(vtbl, y));
402✔
4552
      return diseq_bvvar_const(solver, x, c, n, MAX_DISEQ_RECUR_DEPTH);
402✔
4553
    }
4554

4555
    if (tag_x == BVTAG_POLY && tag_y == BVTAG_POLY) {
363✔
4556
      return disequal_bvpoly(bvvar_poly_def(vtbl, x), bvvar_poly_def(vtbl, y));
6✔
4557
    }
4558

4559
    if (tag_x == BVTAG_BIT_ARRAY && tag_y == BVTAG_BIT_ARRAY) {
357✔
4560
      return diseq_bitarrays(bvvar_bvarray_def(vtbl, x), bvvar_bvarray_def(vtbl, y), n);
87✔
4561
    }
4562

4563
    if (tag_x == BVTAG_POLY && tag_y != BVTAG_CONST) {
270✔
4564
      return bvpoly_is_const_plus_var(bvvar_poly_def(vtbl, x), y);
24✔
4565
    }
4566

4567
    if (tag_y == BVTAG_POLY && tag_x != BVTAG_CONST) {
246✔
4568
      return bvpoly_is_const_plus_var(bvvar_poly_def(vtbl, y), x);
15✔
4569
    }
4570

4571
  }
4572

4573
  return false;
301,728✔
4574
}
4575

4576

4577

4578
/*
4579
 * PROVISIONAL: MORE DISEQUALITY CHECKS
4580
 */
4581

4582
/*
4583
 * Check disequalities using asserted bounds
4584
 * - x and y are variables
4585
 * - n = number of bits
4586
 * - return true if x and y
4587
 */
4588
static bool diseq_bvvar_by_bounds64(bv_solver_t *solver, thvar_t x, thvar_t y, uint32_t n) {
608✔
4589
  bv64_interval_t intv_x, intv_y;
4590

4591
  assert(1 <= n && n <= 64);
4592

4593
  bvvar_bounds_u64(solver, x, n, MAX_RECUR_DEPTH, &intv_x);  // intv_x.low <= x <= intv_x.high
608✔
4594
  bvvar_bounds_u64(solver, y, n, MAX_RECUR_DEPTH, &intv_y);  // intv_y.low <= y <= intv_y.high
608✔
4595
  if (intv_x.high < intv_y.low || intv_y.high < intv_x.low) {
608✔
4596
    // the internals [intv_x.low, intv_x.high] and [intv_y.low, intv_y.high] are disjoint
4597
    return true;
2✔
4598
  }
4599

4600
  // Try signed intervals
4601
  bvvar_bounds_s64(solver, x, n, MAX_RECUR_DEPTH, &intv_x);  // intv_x.low <= x <= intv_x.high
606✔
4602
  bvvar_bounds_s64(solver, y, n, MAX_RECUR_DEPTH, &intv_y);  // intv_y.low <= y <= intv_y.high
606✔
4603

4604
  if (signed64_lt(intv_x.high, intv_y.low, n) || signed64_lt(intv_y.high, intv_x.low, n)) {
606✔
4605
    return true;
4✔
4606
  }
4607

4608
  return false;
602✔
4609
}
4610

4611

4612
static bool diseq_bvvar_by_bounds(bv_solver_t *solver, thvar_t x, thvar_t y, uint32_t n) {
11✔
4613
  bv_interval_t *bounds_x, *bounds_y;
4614
  bool result;
4615

4616
  // prepare interval stack
4617
  alloc_bv_interval_stack(&solver->intv_stack);
11✔
4618
  bounds_x = get_bv_interval(&solver->intv_stack);
11✔
4619
  bounds_y = get_bv_interval(&solver->intv_stack);
11✔
4620

4621
  assert(bounds_x != NULL && bounds_y != NULL);
4622

4623
  bvvar_bounds_u(solver, x, n, MAX_RECUR_DEPTH, bounds_x);  // bounds_x.low <= x <= bounds_x.high
11✔
4624
  bvvar_bounds_u(solver, y, n, MAX_RECUR_DEPTH, bounds_y);  // bounds_y.low <= y <= bounds_y.high
11✔
4625

4626
  if (bvconst_lt(bounds_x->high, bounds_y->low, n) || bvconst_lt(bounds_y->high, bounds_x->low, n)) {
11✔
4627
    result = true;
×
4628
  } else {
4629
    // Try signed intervals
4630
    bvvar_bounds_s(solver, x, n, MAX_RECUR_DEPTH, bounds_x);  // bounds_x.low <= x <= bounds_x.high
11✔
4631
    bvvar_bounds_s(solver, y, n, MAX_RECUR_DEPTH, bounds_y);  // bounds_y.low <= y <= bounds_y.high
11✔
4632

4633
    result = bvconst_slt(bounds_x->high, bounds_y->low, n) || bvconst_slt(bounds_y->high, bounds_x->low, n);
11✔
4634
  }
4635

4636
  release_all_bv_intervals(&solver->intv_stack);
11✔
4637

4638
  return result;
11✔
4639
}
4640

4641

4642
static bool bounds_imply_diseq(bv_solver_t *solver, thvar_t x, thvar_t y) {
619✔
4643
  uint32_t n;
4644

4645
  assert(bvvar_bitsize(&solver->vtbl, x) == bvvar_bitsize(&solver->vtbl, y));
4646
  assert(mtbl_is_root(&solver->mtbl, x) && mtbl_is_root(&solver->mtbl, y));
4647

4648
  n = bvvar_bitsize(&solver->vtbl, x);
619✔
4649
  if (n <= 64) {
619✔
4650
    return diseq_bvvar_by_bounds64(solver, x, y, n);
608✔
4651
  } else {
4652
    return diseq_bvvar_by_bounds(solver, x, y, n);
11✔
4653
  }
4654
}
4655

4656

4657

4658
/*****************************************
4659
 *  SIMPLIFICATION + TERM CONSTRUCTION   *
4660
 ****************************************/
4661

4662
/*
4663
 * Add a * x to buffer b
4664
 * - replace x by its value if it's a constant
4665
 * - also replace x by its root value if the root is a constant
4666
 * - b, a, and x must all have the same bitsize
4667
 */
4668
static void bvbuffer_add_mono64(bv_solver_t *solver, bvpoly_buffer_t *b, thvar_t x, uint64_t a) {
16,404✔
4669
  bv_vartable_t *vtbl;
4670
  thvar_t y;
4671

4672
  vtbl = &solver->vtbl;
16,404✔
4673
  y = bvvar_root_if_const64(solver, x);
16,404✔
4674
  if (bvvar_is_const64(vtbl, y)) {
16,404✔
4675
    bvpoly_buffer_add_const64(b, a * bvvar_val64(vtbl, y));
1,149✔
4676
  } else {
4677
    bvpoly_buffer_add_mono64(b, y, a);
15,255✔
4678
  }
4679
}
16,404✔
4680

4681
// same thing for bitsize > 64
4682
static void bvbuffer_add_mono(bv_solver_t *solver, bvpoly_buffer_t *b, thvar_t x, uint32_t *a) {
661✔
4683
  bv_vartable_t *vtbl;
4684
  thvar_t y;
4685

4686
  vtbl = &solver->vtbl;
661✔
4687
  y = bvvar_root_if_const(solver, x);
661✔
4688
  if (bvvar_is_const(vtbl, y)) {
661✔
4689
    // add const_idx * a * value of y
4690
    bvpoly_buffer_addmul_monomial(b, const_idx, a, bvvar_val(vtbl, y));
17✔
4691
  } else {
4692
    bvpoly_buffer_add_monomial(b, y, a);
644✔
4693
  }
4694
}
661✔
4695

4696

4697
/*
4698
 * Check whether a polynomial (after expansion) is equal to a constant or
4699
 * an existing variable.
4700
 * - the expanded poly is stored in *b (as a list of monomials)
4701
 * - b must be normalized
4702
 * - return null_thvar (i.e., -1) if there's no simplification
4703
 */
4704
static thvar_t simplify_expanded_poly(bv_solver_t *solver, bvarith_buffer_t *b) {
623✔
4705
  bv_vartable_t *vtbl;
4706
  uint32_t n, nbits;
4707
  bvmlist_t *m;
4708
  pprod_t *r;
4709
  thvar_t x;
4710

4711
  vtbl = &solver->vtbl;
623✔
4712
  n = bvarith_buffer_size(b);
623✔
4713
  nbits = bvarith_buffer_bitsize(b);
623✔
4714

4715
  x = null_thvar;
623✔
4716
  if (n == 0) {
623✔
4717
    bvconstant_set_all_zero(&solver->aux1, nbits);
×
4718
    x = get_bvconst(vtbl, nbits, solver->aux1.data);
×
4719

4720
  } else if (n == 1) {
623✔
4721
    m = b->list; // unique monomial of b
51✔
4722
    r = m->prod; // power product in this monomial
51✔
4723
    if (r == empty_pp) {
51✔
4724
      // b is a constant
4725
      x = get_bvconst(vtbl, nbits, m->coeff);
×
4726
    } else if (pp_is_var(r) && bvconst_is_one(m->coeff, (nbits + 31) >> 5)) {
51✔
4727
      // b is 1 * x for some x
4728
      x = var_of_pp(r);
1✔
4729
    }
4730
  }
4731

4732
  return x;
623✔
4733
}
4734

4735

4736
/*
4737
 * Same thing for a 64bit polynomial
4738
 */
4739
static thvar_t simplify_expanded_poly64(bv_solver_t *solver, bvarith64_buffer_t *b) {
12,740✔
4740
  bv_vartable_t *vtbl;
4741
  uint32_t n, nbits;
4742
  bvmlist64_t *m;
4743
  pprod_t *r;
4744
  thvar_t x;
4745

4746
  vtbl = &solver->vtbl;
12,740✔
4747
  n = bvarith64_buffer_size(b);
12,740✔
4748
  nbits = bvarith64_buffer_bitsize(b);
12,740✔
4749

4750
  x = null_thvar;
12,740✔
4751
  if (n == 0) {
12,740✔
4752
    x = get_bvconst64(vtbl, nbits, 0);
1✔
4753

4754
  } else if (n == 1) {
12,739✔
4755
    m = b->list; // unique monomial of b
8,993✔
4756
    r = m->prod; // power product in this monomial
8,993✔
4757
    if (r == empty_pp) {
8,993✔
4758
      // b is a constant
4759
      x = get_bvconst64(vtbl, nbits, m->coeff);
1✔
4760
    } else if (pp_is_var(r) && m->coeff == 1) {
8,992✔
4761
      // b is 1 * x for some x
4762
      x = var_of_pp(r);
1✔
4763
    }
4764
  }
4765

4766
  return x;
12,740✔
4767
}
4768

4769

4770
/*
4771
 * Build the variable for a polynomial stored in buffer
4772
 */
4773
static thvar_t map_bvpoly(bv_solver_t *solver, bvpoly_buffer_t *b) {
607✔
4774
  bv_vartable_t *vtbl;
4775
  bvexp_table_t *etbl;
4776
  bvarith_buffer_t *eb;
4777
  thvar_t x;
4778
  uint32_t n, nbits, h;
4779

4780
  vtbl = &solver->vtbl;
607✔
4781

4782
  n = bvpoly_buffer_num_terms(b);
607✔
4783
  nbits = bvpoly_buffer_bitsize(b);
607✔
4784

4785
  /*
4786
   * Check whether p is a constant or of the form 1. x
4787
   */
4788
  if (n == 0) {
607✔
4789
    // return the constant 0b000...0
4790
    bvconstant_set_all_zero(&solver->aux1, nbits);
1✔
4791
    x = get_bvconst(vtbl, nbits, solver->aux1.data);
1✔
4792
    return x;
1✔
4793
  }
4794

4795
  if (n == 1) {
606✔
4796
    x = bvpoly_buffer_var(b, 0);
33✔
4797
    if (x == const_idx) {
33✔
4798
      // p is a constant
4799
      x = get_bvconst(vtbl, nbits, bvpoly_buffer_coeff(b, 0));
6✔
4800
      return x;
6✔
4801
    }
4802

4803
    if (bvconst_is_one(bvpoly_buffer_coeff(b, 0), (nbits + 31) >> 5)) {
27✔
4804
      // p is equal to 1 . x
4805
      return x;
×
4806
    }
4807
  }
4808

4809

4810
  /*
4811
   * Expand p then check whether the expanded form is equal to a constant
4812
   * or an existing variable
4813
   */
4814
  etbl = &solver->etbl;
600✔
4815
  eb = &solver->exp_buffer;
600✔
4816
  expand_bvpoly(etbl, eb, b);
600✔
4817
  x = simplify_expanded_poly(solver, eb);
600✔
4818

4819
  if (x < 0) {
600✔
4820
    // no simplification: check for an existing variable with
4821
    // the same expanded form
4822
    h = hash_bvmlist(eb->list, nbits);
599✔
4823
    x = bvexp_table_find(etbl, eb, h);
599✔
4824
    if (x < 0) {
599✔
4825
      // not in the etbl
4826
      x = get_bvpoly(vtbl, b);
598✔
4827
      bvexp_table_add(etbl, x, eb, h);  // store x and its expansion in etbl
598✔
4828
    }
4829
  }
4830

4831
  return x;
600✔
4832
}
4833

4834

4835
/*
4836
 * Same thing for a polynomial with 64bit coefficients
4837
 */
4838
static thvar_t map_bvpoly64(bv_solver_t *solver, bvpoly_buffer_t *b) {
12,399✔
4839
  bv_vartable_t *vtbl;
4840
  bvexp_table_t *etbl;
4841
  bvarith64_buffer_t *eb;
4842
  thvar_t x;
4843
  uint32_t n, nbits, h;
4844

4845
  vtbl = &solver->vtbl;
12,399✔
4846

4847
  n = bvpoly_buffer_num_terms(b);
12,399✔
4848
  nbits = bvpoly_buffer_bitsize(b);
12,399✔
4849

4850
  if (n == 0) {
12,399✔
4851
    // return the constant 0b000 ..0
4852
    x = get_bvconst64(vtbl, nbits, 0);
3✔
4853
    return x;
3✔
4854
  }
4855

4856
  if (n == 1) {
12,396✔
4857
    x = bvpoly_buffer_var(b, 0);
8,655✔
4858
    if (x == const_idx) {
8,655✔
4859
      // constant
4860
      x = get_bvconst64(vtbl, nbits, bvpoly_buffer_coeff64(b, 0));
201✔
4861
      return x;
201✔
4862
    }
4863

4864
    if (bvpoly_buffer_coeff64(b, 0) == 1) {
8,454✔
4865
      return x;
10✔
4866
    }
4867
  }
4868

4869
  // expand p
4870
  etbl = &solver->etbl;
12,185✔
4871
  eb = &solver->exp64_buffer;
12,185✔
4872
  expand_bvpoly64(etbl, eb, b);
12,185✔
4873

4874
  // check whether the expanded form simplifies to a constant
4875
  // or a single variable
4876
  x = simplify_expanded_poly64(solver, eb);
12,185✔
4877

4878
  if (x < 0) {
12,185✔
4879
    h = hash_bvmlist64(eb->list, nbits);
12,182✔
4880
    x = bvexp_table_find64(etbl, eb, h);
12,182✔
4881
    if (x < 0) {
12,182✔
4882
      // nothing equal to p in etbl
4883
      x = get_bvpoly64(vtbl, b);
12,168✔
4884
      bvexp_table_add64(etbl, x, eb, h);
12,168✔
4885
    }
4886
  }
4887

4888
  return x;
12,185✔
4889
}
4890

4891

4892

4893
/*
4894
 * Build the term c * x (as a polynomial)
4895
 * - nbits = number of bits in c and x
4896
 */
4897
static thvar_t make_mono64(bv_solver_t *solver, uint32_t nbits, uint64_t c, thvar_t x) {
9✔
4898
  bvpoly_buffer_t *b;
4899

4900
  b = &solver->buffer;
9✔
4901
  reset_bvpoly_buffer(b, nbits);
9✔
4902
  bvpoly_buffer_add_mono64(b, x, c);
9✔
4903

4904
  return get_bvpoly64(&solver->vtbl, b);
9✔
4905
}
4906

4907

4908
/*
4909
 * Convert power-product p to a variable
4910
 * - nbits = number of bits
4911
 */
4912
static thvar_t make_bvpprod(bv_vartable_t *vtbl, uint32_t nbits, pp_buffer_t *p) {
575✔
4913
  thvar_t x;
4914

4915
  if (p->len == 1 && p->prod[0].exp == 1) {
575✔
4916
    x = p->prod[0].var;
9✔
4917
  } else {
4918
    x = get_bvpprod(vtbl, nbits, p);
566✔
4919
  }
4920

4921
  return x;
575✔
4922
}
4923

4924

4925
/*
4926
 * Build the term (c * p)
4927
 * - c is a 64bit constants
4928
 * - p is a power product
4929
 * - nbits = number of bits in c (and in all variables of p)
4930
 */
4931
static thvar_t map_const64_times_product(bv_solver_t *solver, uint32_t nbits, pp_buffer_t *p, uint64_t c) {
558✔
4932
  bv_vartable_t *vtbl;
4933
  bvexp_table_t *etbl;
4934
  bvarith64_buffer_t *eb;
4935
  thvar_t x;
4936
  uint32_t h;
4937

4938
  assert(c == norm64(c, nbits));
4939

4940
  vtbl = &solver->vtbl;
558✔
4941

4942
  if (c == 0 || p->len == 0) {
558✔
4943
    // constant
4944
    x = get_bvconst64(vtbl, nbits, c);
×
4945
    return x;
×
4946
  }
4947

4948
  if (p->len == 1 && p->prod[0].exp == 1 && c == 1) {
558✔
4949
    // monomial 1 * x
4950
    x = p->prod[0].var;
3✔
4951
    return x;
3✔
4952
  }
4953

4954

4955
  /*
4956
   * Try expanded form
4957
   */
4958
  etbl = &solver->etbl;
555✔
4959
  eb = &solver->exp64_buffer;
555✔
4960
  expand_bvpprod64(etbl, eb, p, nbits, c);
555✔
4961
  x = simplify_expanded_poly64(solver, eb);
555✔
4962

4963
  if (x < 0) {
555✔
4964
    h = hash_bvmlist64(eb->list, nbits);
555✔
4965
    x = bvexp_table_find64(etbl, eb, h);
555✔
4966

4967
    if (x < 0) {
555✔
4968
      // not found in etbl: build c * p
4969
      x = make_bvpprod(vtbl, nbits, p);
552✔
4970
      if (c != 1) {
552✔
4971
        x = make_mono64(solver, nbits, c, x);
9✔
4972
      }
4973
      bvexp_table_add64(etbl, x, eb, h);
552✔
4974
    }
4975
  }
4976

4977
  return x;
555✔
4978
}
4979

4980

4981
/*
4982
 * Build the term c * x (as a polynomial)
4983
 * - nbits = number of bits in c and x (nbits > 64)
4984
 * - c must be normalized
4985
 */
4986
static thvar_t make_mono(bv_solver_t *solver, uint32_t nbits, uint32_t *c, thvar_t x) {
2✔
4987
  bvpoly_buffer_t *b;
4988

4989
  b = &solver->buffer;
2✔
4990
  reset_bvpoly_buffer(b, nbits);
2✔
4991
  bvpoly_buffer_add_monomial(b, x, c);
2✔
4992

4993
  return get_bvpoly(&solver->vtbl, b);
2✔
4994
}
4995

4996

4997
/*
4998
 * Build the term (c * p)
4999
 * - c is a constants with more than 64bits
5000
 * - p is a power product
5001
 * - nbits = number of bits in c (and in all variables of p)
5002
 */
5003
static thvar_t map_const_times_product(bv_solver_t *solver, uint32_t nbits, pp_buffer_t *p, uint32_t *c) {
25✔
5004
  bv_vartable_t *vtbl;
5005
  bvexp_table_t *etbl;
5006
  bvarith_buffer_t *eb;
5007
  uint32_t w, h;
5008
  thvar_t x;
5009

5010
  vtbl = &solver->vtbl;
25✔
5011
  w = (nbits + 31) >> 5;
25✔
5012

5013
  if (bvconst_is_zero(c, w) || p->len == 0) {
25✔
5014
    x = get_bvconst(vtbl, nbits, c);
1✔
5015
    return x;
1✔
5016
  }
5017

5018
  if (p->len == 1 && p->prod[0].exp == 1 && bvconst_is_one(c, w)) {
24✔
5019
    x = p->prod[0].var;
1✔
5020
    return x;
1✔
5021
  }
5022

5023
  /*
5024
   * Try expanded form
5025
   */
5026
  etbl = &solver->etbl;
23✔
5027
  eb = &solver->exp_buffer;
23✔
5028
  expand_bvpprod(etbl, eb, p, nbits, c);
23✔
5029
  x = simplify_expanded_poly(solver, eb);
23✔
5030

5031
  if (x < 0) {
23✔
5032
    // search for a matching x in etbl
5033
    h = hash_bvmlist(eb->list, nbits);
23✔
5034
    x = bvexp_table_find(etbl, eb, h);
23✔
5035
    if (x < 0) {
23✔
5036
      // not found
5037
      x = make_bvpprod(vtbl, nbits, p);
23✔
5038
      if (!bvconst_is_one(c, w)) {
23✔
5039
        x = make_mono(solver, nbits, c, x);
2✔
5040
      }
5041
      bvexp_table_add(etbl, x, eb, h);
23✔
5042
    }
5043
  }
5044

5045
  return x;
23✔
5046
}
5047

5048

5049
/*
5050
 * Check whether all literals in a[0 ... n-1] are constant
5051
 */
5052
static bool bvarray_is_constant(literal_t *a, uint32_t n) {
18,616✔
5053
  uint32_t i;
5054

5055
  for (i=0; i<n; i++) {
87,186✔
5056
    if (var_of(a[i]) != const_bvar) return false;
86,377✔
5057
  }
5058

5059
  return true;
809✔
5060
}
5061

5062

5063
/*
5064
 * Convert constant array a[0 ... n-1] to a 64bit unsigned integer
5065
 * - a[0] = low order bit
5066
 * - a[n-1] = high order bit
5067
 */
5068
static uint64_t bvarray_to_uint64(literal_t *a, uint32_t n) {
593✔
5069
  uint64_t c;
5070

5071
  assert(1 <= n && n <= 64);
5072
  c = 0;
593✔
5073
  while (n > 0) {
6,412✔
5074
    n --;
5,819✔
5075
    assert(a[n] == true_literal || a[n] == false_literal);
5076
    c = (c << 1) | is_pos(a[n]);
5,819✔
5077
  }
5078

5079
  return c;
593✔
5080
}
5081

5082

5083
/*
5084
 * Convert constant array a[0 ... n-1] to a bitvector constant
5085
 * - copy the result in c
5086
 */
5087
static void bvarray_to_bvconstant(literal_t *a, uint32_t n, bvconstant_t *c) {
216✔
5088
  uint32_t i;
5089

5090
  assert(n > 64);
5091

5092
  bvconstant_set_all_zero(c, n);
216✔
5093
  for (i=0; i<n; i++) {
56,583✔
5094
    assert(a[i] == true_literal || a[i] == false_literal);
5095
    if (a[i] == true_literal) {
56,367✔
5096
      bvconst_set_bit(c->data, i);
4,720✔
5097
    }
5098
  }
5099
}
216✔
5100

5101

5102

5103
/*
5104
 * Bounds on (urem z y): if y != 0 then 0 <= (urem z y) < y
5105
 * - x must be equal to (urem z y) for some z
5106
 */
5107
static void assert_urem_bounds(bv_solver_t *solver, thvar_t x, thvar_t y) {
150✔
5108
  literal_t l0, l1;
5109
  thvar_t zero;
5110
  uint32_t n;
5111

5112
  assert(bvvar_tag(&solver->vtbl, x) == BVTAG_UREM && solver->vtbl.def[x].op[1] == y);
5113

5114
  n = bvvar_bitsize(&solver->vtbl, y);
150✔
5115
  zero = get_zero(solver, n);
150✔
5116
  l0 = bv_solver_create_eq_atom(solver, y, zero); // (y == 0)
150✔
5117
  l1 = bv_solver_create_ge_atom(solver, x, y);    // (bvurem z y) >= y
150✔
5118
  add_binary_clause(solver->core, l0, not(l1));
150✔
5119
}
150✔
5120

5121

5122
/*
5123
 * Bounds on (srem z y) or  (smod z y):
5124
 * - if y > 0 then - y < (srem z y) < y
5125
 * - if y < 0 then   y < (srem z y) < - y
5126
 * Same thing for (smod z y)
5127
 *
5128
 * We don't want to create the term -y so we add only half
5129
 * of these constraints:
5130
 *  y>0 ==> (srem z y) < y
5131
 *  y<0 ==> y < (srem z y)
5132
 */
5133
static void assert_srem_bounds(bv_solver_t *solver, thvar_t x, thvar_t y) {
72✔
5134
  literal_t l0, l1;
5135
  thvar_t zero;
5136
  uint32_t n;
5137

5138
  assert(bvvar_tag(&solver->vtbl, x) == BVTAG_SREM || bvvar_tag(&solver->vtbl, x) == BVTAG_SMOD);
5139
  assert(solver->vtbl.def[x].op[1] == y);
5140

5141
  n = bvvar_bitsize(&solver->vtbl, y);
72✔
5142
  zero = get_zero(solver, n);
72✔
5143

5144
  l0 = bv_solver_create_sge_atom(solver, zero, y); // (y <= 0)
72✔
5145
  l1 = bv_solver_create_sge_atom(solver, x, y);    // (bvsrem z y) >= y
72✔
5146
  add_binary_clause(solver->core, l0, not(l1));    // (y > 0) ==> (bvsrem z y) < y
72✔
5147

5148
  l0 = bv_solver_create_sge_atom(solver, y, zero); // (y >= 0)
72✔
5149
  l1 = bv_solver_create_sge_atom(solver, y, x);    // y >= (bvsrem z y)
72✔
5150
  add_binary_clause(solver->core, l0, not(l1));    // (y < 0) ==> y < (bvsrem z y)
72✔
5151
}
72✔
5152

5153

5154
/*
5155
 * SIMPLIFICATIONS FOR IF-THEN-ELSE TERMS
5156
 */
5157

5158
/*
5159
 * Boolean if-then-else (ite c x y)
5160
 * - c is a literal, x and y are true or false
5161
 */
5162
static literal_t bool_const_ite(literal_t c, bool x, bool y) {
201✔
5163
  if (x == y) {
201✔
5164
    return bool2literal(x);   // (ite c x x) --> x
32✔
5165
  } else if (x) {
169✔
5166
    return c;             // (ite c true false) --> c
42✔
5167
  } else {
5168
    return not(c);        // (ite c false true) --> not(c)
127✔
5169
  }
5170
}
5171

5172
/*
5173
 * Convert (ite c x y) to a bitarray:
5174
 * - n = number of bits
5175
 * - x and y are bitvector constants
5176
 * - c is a literal (other than true_literal and false_literal)
5177
 * - x and y are distinct 
5178
 */
5179
static thvar_t create_ite_const64(bv_solver_t *solver, uint32_t n, literal_t c, uint64_t x, uint64_t y) {
52✔
5180
  ivector_t *v;
5181
  uint32_t i;
5182

5183
  assert(1 <= n && n <= 64 && x == norm64(x, n) && y == norm64(y, n) &&  x != y);
5184
  assert(c != true_literal && c != false_literal);
5185

5186
  v = &solver->aux_vector;
52✔
5187
  ivector_reset(v);
52✔
5188
  for (i=0; i<n; i++) {
253✔
5189
    ivector_push(v, bool_const_ite(c, tst_bit64(x, i), tst_bit64(y, i)));
201✔
5190
  }
5191
  assert(v->size == n && !bvarray_is_constant(v->data, n));
5192
  return get_bvarray(&solver->vtbl, n, v->data);
52✔
5193
}
5194

5195
static thvar_t create_ite_const(bv_solver_t *solver, uint32_t n, literal_t c, const uint32_t *x, const uint32_t *y) {
×
5196
  ivector_t *v;
5197
  uint32_t i;
5198

5199
  assert(n > 64 && bvconst_is_normalized(x, n) && bvconst_is_normalized(y, n));
5200
  assert(c != true_literal && c != false_literal);
5201

5202
  v = &solver->aux_vector;
×
5203
  ivector_reset(v);
×
5204
  for (i=0; i<n; i++) {
×
5205
    ivector_push(v, bool_const_ite(c, bvconst_tst_bit(x, i), bvconst_tst_bit(y, i)));
×
5206
  }
5207
  assert(v->size == n && !bvarray_is_constant(v->data, n));
5208
  return get_bvarray(&solver->vtbl, n, v->data);
×
5209
}
5210

5211

5212
/*
5213
 * Checks whether (ite c x y) simplifies to a literal
5214
 * - c must not be true_literal or false_literal
5215
 * - returns the literal if it does
5216
 * - returns null_literal otherwise
5217
 */
5218
static literal_t try_bool_ite(literal_t c, literal_t x, literal_t y) {
1,689✔
5219
  assert(c != true_literal && c != false_literal);
5220

5221
  // (ite c c y)       --> (ite c true y)
5222
  // (ite c (not c) y) --> (ite c false y)
5223
  if (c == x) { 
1,689✔
5224
    x = true_literal;
×
5225
  } else if (opposite(c, x)) {
1,689✔
5226
    x = false_literal; 
×
5227
  }
5228

5229
  // (ite c x c)       --> (ite c x false)
5230
  // (ite c x (not c)) --> (ite c x true)
5231
  if (c == y) {
1,689✔
5232
    y = false_literal;
1✔
5233
  } else if (opposite(c, y)) {
1,688✔
5234
    y = true_literal;
2✔
5235
  }
5236

5237
  // (ite c x x) --> x
5238
  // (ite c true false) --> c
5239
  // (ite c false true) --> (not c)
5240
  if (x == y) return x;
1,689✔
5241
  if (x == true_literal && y == false_literal) return c;
1,502✔
5242
  if (x == false_literal && y == true_literal) return not(c);
1,502✔
5243

5244
  return null_literal;
1,501✔
5245
}
5246

5247

5248
/*
5249
 * Try to convert (ite c x y) to a bitarray
5250
 * - c is a literal other than true_literal and false_literal
5251
 * - x is a bitvector constant of n bits
5252
 * - y is a bitarray of n bits
5253
 *
5254
 * return null_thvar if this fails, a bitarray variable otherwise
5255
 */
5256
static thvar_t try_ite_const64(bv_solver_t *solver, uint32_t n, literal_t c, uint64_t x, const literal_t *y) {
1,125✔
5257
  ivector_t *v;
5258
  literal_t l;
5259
  uint32_t i;
5260
  thvar_t r;
5261

5262
  assert(1 <= n && n <= 64 && x == norm64(x, n));
5263
  assert(c != true_literal && c != false_literal);
5264

5265
  r = null_thvar;
1,125✔
5266
  v = &solver->aux_vector;  
1,125✔
5267
  ivector_reset(v);
1,125✔
5268
  for (i=0; i<n; i++) {
1,313✔
5269
    l = bool2literal(tst_bit64(x, i));  // i-th bit of x converted to a literal
1,312✔
5270
    l = try_bool_ite(c, l, y[i]);       // l = boolean (ite c x[i] y[i])
1,312✔
5271
    if (l == null_literal) goto done;
1,312✔
5272
    ivector_push(v, l);
188✔
5273
  }
5274
  
5275
  assert(v->size == n);
5276
  // we use bv_solver_create_bvarray here, because v may contain a constant array
5277
  r = bv_solver_create_bvarray(solver, v->data, n);
1✔
5278
  
5279
 done:
1,125✔
5280
  return r;
1,125✔
5281
}
5282

5283
static thvar_t try_ite_const(bv_solver_t *solver, uint32_t n, literal_t c, const uint32_t *x, const literal_t *y) {
355✔
5284
  ivector_t *v;
5285
  literal_t l;
5286
  uint32_t i;
5287
  thvar_t r;
5288

5289
  assert(n > 64 && bvconst_is_normalized(x, n));
5290
  assert(c != true_literal && c != false_literal);
5291

5292
  r = null_thvar;
355✔
5293
  v = &solver->aux_vector;  
355✔
5294
  ivector_reset(v);
355✔
5295
  for (i=0; i<n; i++) {
355✔
5296
    l = bool2literal(bvconst_tst_bit(x, i));   // i-th bit of x, converted to a literal
355✔
5297
    l = try_bool_ite(c, l, y[i]);              // l = boolean (ite c x[i] y[i])
355✔
5298
    if (l == null_literal) goto done;
355✔
5299
    ivector_push(v, l);
×
5300
  }
5301
  
5302
  assert(v->size == n);
5303
  r = bv_solver_create_bvarray(solver, v->data, n);
×
5304
  
5305
 done:
355✔
5306
  return r;
355✔
5307
}
5308

5309

5310
/*
5311
 * Try to convert (ite c x y) to a bitarray
5312
 * - c is a literal other than true_literal and false_literal
5313
 * - x and y are literal arrays of n bits (distinct)
5314
 */
5315
static thvar_t try_ite_bitarrays(bv_solver_t *solver, uint32_t n, literal_t c, const literal_t *x, const literal_t *y) {
22✔
5316
  ivector_t *v;
5317
  literal_t l;
5318
  uint32_t i;
5319
  thvar_t r;
5320

5321
  assert(c != true_literal && c != false_literal);
5322

5323
  r = null_thvar;
22✔
5324
  v = &solver->aux_vector;  
22✔
5325
  ivector_reset(v);
22✔
5326
  for (i=0; i<n; i++) {
22✔
5327
    l = try_bool_ite(c, x[i], y[i]);
22✔
5328
    if (l == null_literal) goto done;
22✔
5329
    ivector_push(v, l);
×
5330
  }
5331
  
5332
  assert(v->size == n);
5333
  r = get_bvarray(&solver->vtbl, n, v->data);
×
5334
  
5335
 done:
22✔
5336
  return r;
22✔
5337
}
5338

5339

5340

5341

5342
/********************************
5343
 *  INTERNALIZATION FUNCTIONS   *
5344
 *******************************/
5345

5346
/*
5347
 * Create a new variable of n bits
5348
 */
5349
thvar_t bv_solver_create_var(bv_solver_t *solver, uint32_t n) {
18,597✔
5350
  assert(n > 0);
5351
  return make_bvvar(&solver->vtbl, n);
18,597✔
5352
}
5353

5354

5355
/*
5356
 * Create a variable equal to constant c
5357
 */
5358
thvar_t bv_solver_create_const(bv_solver_t *solver, bvconst_term_t *c) {
458✔
5359
  return get_bvconst(&solver->vtbl, c->bitsize, c->data);
458✔
5360
}
5361

5362
thvar_t bv_solver_create_const64(bv_solver_t *solver, bvconst64_term_t *c) {
8,512✔
5363
  return get_bvconst64(&solver->vtbl, c->bitsize, c->value);
8,512✔
5364
}
5365

5366
/*
5367
 * Zero constant:
5368
 * - n = number of bits
5369
 */
5370
thvar_t bv_solver_create_zero(bv_solver_t *solver, uint32_t n) {
41✔
5371
  return get_zero(solver, n);
41✔
5372
}
5373

5374

5375

5376
/*
5377
 * Internalize a polynomial p:
5378
 * - map = variable renaming
5379
 *   if p is of the form a_0 t_0 + ... + a_n t_n
5380
 *   then map contains n+1 variables, and map[i] is the internalization of t_i
5381
 * - exception: if t_0 is const_idx then map[0] = null_thvar
5382
 */
5383
thvar_t bv_solver_create_bvpoly(bv_solver_t *solver, bvpoly_t *p, thvar_t *map) {
607✔
5384
  bvpoly_buffer_t *buffer;
5385
  uint32_t i, n, nbits;
5386

5387
  n = p->nterms;
607✔
5388
  nbits = p->bitsize;
607✔
5389
  i = 0;
607✔
5390

5391
  buffer = &solver->buffer;
607✔
5392
  reset_bvpoly_buffer(buffer, nbits);
607✔
5393

5394
  // deal with constant term if any
5395
  if (p->mono[0].var == const_idx) {
607✔
5396
    assert(map[0] == null_thvar);
5397
    bvpoly_buffer_add_constant(buffer, p->mono[i].coeff);
539✔
5398
    i ++;
539✔
5399
  }
5400

5401
  // rest of p
5402
  while (i < n) {
1,268✔
5403
    assert(valid_bvvar(&solver->vtbl, map[i]));
5404
    bvbuffer_add_mono(solver, buffer, map[i], p->mono[i].coeff);
661✔
5405
    i ++;
661✔
5406
  }
5407

5408
  normalize_bvpoly_buffer(buffer);
607✔
5409
  return map_bvpoly(solver, buffer);
607✔
5410
}
5411

5412
// Same thing: coefficients stored as 64bit integers
5413
thvar_t bv_solver_create_bvpoly64(bv_solver_t *solver, bvpoly64_t *p, thvar_t *map) {
12,399✔
5414
  bvpoly_buffer_t *buffer;
5415
  uint32_t i, n, nbits;
5416

5417
  n = p->nterms;
12,399✔
5418
  nbits = p->bitsize;
12,399✔
5419
  i = 0;
12,399✔
5420

5421
  buffer = &solver->buffer;
12,399✔
5422
  reset_bvpoly_buffer(buffer, nbits);
12,399✔
5423

5424
  // deal with constant term if any
5425
  if (p->mono[0].var == const_idx) {
12,399✔
5426
    assert(map[0] == null_thvar);
5427
    bvpoly_buffer_add_const64(buffer, p->mono[i].coeff);
2,801✔
5428
    i ++;
2,801✔
5429
  }
5430

5431
  // rest of p
5432
  while (i < n) {
28,803✔
5433
    assert(valid_bvvar(&solver->vtbl, map[i]));
5434
    bvbuffer_add_mono64(solver, buffer, map[i], p->mono[i].coeff);
16,404✔
5435
    i ++;
16,404✔
5436
  }
5437

5438
  normalize_bvpoly_buffer(buffer);
12,399✔
5439
  return map_bvpoly64(solver, buffer);
12,399✔
5440
}
5441

5442

5443
/*
5444
 * Product p = t_0^d_0 x ... x t_n ^d_n
5445
 * - map = variable renaming: t_i is replaced by map[i]
5446
 */
5447
thvar_t bv_solver_create_pprod(bv_solver_t *solver, pprod_t *p, thvar_t *map) {
583✔
5448
  bv_vartable_t *vtbl;
5449
  pp_buffer_t *buffer;
5450
  uint32_t *a;
5451
  uint64_t c;
5452
  uint32_t i, n, nbits, w;
5453
  thvar_t x;
5454

5455
  vtbl = &solver->vtbl;
583✔
5456
  buffer = &solver->prod_buffer;
583✔
5457
  pp_buffer_reset(buffer);
583✔
5458

5459
  assert(p->len > 0);
5460
  nbits = bvvar_bitsize(vtbl, map[0]);
583✔
5461

5462
  /*
5463
   * We build a term (* constant (x_1 ^ d_1 ... x_k^d_k))
5464
   * by replacing any constant map[i] by its value
5465
   */
5466
  if (nbits <= 64) {
583✔
5467
    c = 1;
558✔
5468
    n = p->len;
558✔
5469
    for (i=0; i<n; i++) {
1,657✔
5470
      x = map[i];
1,099✔
5471
      if (bvvar_is_const64(vtbl, x)) {
1,099✔
5472
        c *= upower64(bvvar_val64(vtbl, x), p->prod[i].exp);
12✔
5473
      } else {
5474
        pp_buffer_mul_varexp(buffer, x, p->prod[i].exp);
1,087✔
5475
      }
5476
    }
5477

5478
    // normalize c then build the term (c * p)
5479
    c = norm64(c, nbits);
558✔
5480
    x = map_const64_times_product(solver, nbits, buffer, c);
558✔
5481

5482
  } else {
5483
    // use aux1 to store the constant
5484
    w = (nbits + 31) >> 5;
25✔
5485
    bvconstant_set_bitsize(&solver->aux1, nbits);
25✔
5486
    a = solver->aux1.data;
25✔
5487
    bvconst_set_one(a, w);
25✔
5488

5489
    n = p->len;
25✔
5490
    for (i=0; i<n; i++) {
67✔
5491
      x = map[i];
42✔
5492
      if (bvvar_is_const(vtbl, x)) {
42✔
5493
        bvconst_mulpower(a, w, bvvar_val(vtbl, x), p->prod[i].exp);
4✔
5494
      } else {
5495
        pp_buffer_mul_varexp(buffer, x, p->prod[i].exp);
38✔
5496
      }
5497
    }
5498

5499
    // normalize a then build the term (a * p)
5500
    bvconst_normalize(a, nbits);
25✔
5501
    x = map_const_times_product(solver, nbits, buffer, a);
25✔
5502
  }
5503

5504
  return x;
583✔
5505
}
5506

5507

5508
/*
5509
 * Internalize the bit array a[0 ... n-1]
5510
 * - each element a[i] is a literal in the core
5511
 */
5512
thvar_t bv_solver_create_bvarray(bv_solver_t *solver, literal_t *a, uint32_t n) {
18,616✔
5513
  bvconstant_t *aux;
5514
  uint64_t c;
5515
  thvar_t x;
5516

5517
  if (bvarray_is_constant(a, n)) {
18,616✔
5518
    if (n <= 64) {
809✔
5519
      c = bvarray_to_uint64(a, n);
593✔
5520
      assert(c == norm64(c, n));
5521
      x = get_bvconst64(&solver->vtbl, n, c);
593✔
5522
    } else {
5523
      aux = &solver->aux1;
216✔
5524
      bvarray_to_bvconstant(a, n, aux);
216✔
5525
      x = get_bvconst(&solver->vtbl, n, aux->data);
216✔
5526
    }
5527
  } else {
5528
    x = get_bvarray(&solver->vtbl, n, a);
17,807✔
5529
  }
5530

5531
  return x;
18,616✔
5532
}
5533

5534

5535

5536
/*
5537
 * Internalization of (ite c x y)
5538
 */
5539
thvar_t bv_solver_create_ite(bv_solver_t *solver, literal_t c, thvar_t x, thvar_t y) {
18,672✔
5540
  bv_vartable_t *vtbl;
5541
  uint32_t n;
5542
  thvar_t aux;
5543
  bvvar_tag_t tagx, tagy;
5544

5545
  vtbl = &solver->vtbl;
18,672✔
5546
  n = bvvar_bitsize(vtbl, x);
18,672✔
5547
  assert(bvvar_bitsize(vtbl, y) == n);
5548

5549
  /// TODO: MORE SIMPLIFICATIONS TO A BIT ARRAY
5550
  /// IF x and y are constants --> convert to an array of Booleans
5551

5552
  /// Other conversions may be possible (as in term_manager.c, mk_bv_ite).
5553

5554
  // Generic simplifications
5555
  if (x == y) return x;
18,672✔
5556
  if (c == true_literal) return x;
18,412✔
5557
  if (c == false_literal) return y;
18,412✔
5558

5559
  // Check whether (ite c x y) simplifies to a bit array
5560
  tagx = bvvar_tag(vtbl, x);
18,412✔
5561
  tagy = bvvar_tag(vtbl, y);
18,412✔
5562
  aux = null_thvar;
18,412✔
5563
  switch (tagx) {
18,412✔
5564
  case BVTAG_CONST64:
15,919✔
5565
    assert(tagy != BVTAG_CONST);
5566
    if (tagy == BVTAG_CONST64) {
15,919✔
5567
      return create_ite_const64(solver, n, c, bvvar_val64(vtbl, x), bvvar_val64(vtbl, y));
52✔
5568
    }
5569
    if (tagy == BVTAG_BIT_ARRAY) {
15,867✔
5570
      aux = try_ite_const64(solver, n, c, bvvar_val64(vtbl, x), bvvar_bvarray_def(vtbl, y));
1,092✔
5571
      if (aux != null_thvar) return aux;
1,092✔
5572
    }
5573
    break;
15,866✔
5574

5575
  case BVTAG_CONST:
421✔
5576
    assert(tagy != BVTAG_CONST64);
5577
    if (tagy == BVTAG_CONST) {
421✔
5578
      return create_ite_const(solver, n, c, bvvar_val(vtbl, x), bvvar_val(vtbl, y));
×
5579
    }
5580
    if (tagy == BVTAG_BIT_ARRAY) {
421✔
5581
      aux = try_ite_const(solver, n, c, bvvar_val(vtbl, x), bvvar_bvarray_def(vtbl, y));
354✔
5582
      if (aux != null_thvar) return aux;
354✔
5583
    }
5584
    break;
421✔
5585

5586
  case BVTAG_BIT_ARRAY:
512✔
5587
    if (tagy == BVTAG_CONST64) {
512✔
5588
      aux = try_ite_const64(solver, n, not(c), bvvar_val64(vtbl, y), bvvar_bvarray_def(vtbl, x));
33✔
5589
    } else if (tagy == BVTAG_CONST) {
479✔
5590
      aux = try_ite_const(solver, n, not(c), bvvar_val(vtbl, y), bvvar_bvarray_def(vtbl, x));
1✔
5591
    } else if (tagy == BVTAG_BIT_ARRAY) {
478✔
5592
      aux = try_ite_bitarrays(solver, n, c, bvvar_bvarray_def(vtbl, x), bvvar_bvarray_def(vtbl, y));
22✔
5593
    }
5594
    if (aux != null_thvar) return aux;
512✔
5595
    break;
512✔
5596

5597
  default:
1,560✔
5598
    break;
1,560✔
5599
  }
5600

5601

5602
  /*
5603
   * Normalize: rewrite (ite (not b) x y) to (ite b y x)
5604
   */
5605
  if (is_neg(c)) {
18,359✔
5606
    aux = x; x = y; y = aux;
67✔
5607
    c = not(c);
67✔
5608
  }
5609

5610
  return get_bvite(&solver->vtbl, n, c, x, y);
18,359✔
5611
}
5612

5613

5614
/*
5615
 * Binary operators
5616
 */
5617

5618
/*
5619
 * Quotient x/y: unsigned, rounding toward 0
5620
 * - simplify if x and y are both constants
5621
 */
5622
thvar_t bv_solver_create_bvdiv(bv_solver_t *solver, thvar_t x, thvar_t y) {
96✔
5623
  bv_vartable_t *vtbl;
5624
  bvconstant_t *aux;
5625
  bvvar_tag_t xtag, ytag;
5626
  uint64_t c;
5627
  uint32_t n;
5628

5629
  vtbl = &solver->vtbl;
96✔
5630

5631
  x = mtbl_get_root(&solver->mtbl, x);
96✔
5632
  y = mtbl_get_root(&solver->mtbl, y);
96✔
5633

5634
  n = bvvar_bitsize(vtbl, x);
96✔
5635
  assert(n == bvvar_bitsize(vtbl, y));
5636

5637
  xtag = bvvar_tag(vtbl, x);
96✔
5638
  ytag = bvvar_tag(vtbl, y);
96✔
5639

5640
  // deal with constants
5641
  if (xtag == ytag) {
96✔
5642
    if (xtag == BVTAG_CONST64) {
40✔
5643
      // small constants
5644
      assert(n <= 64);
5645
      c = bvconst64_udiv2z(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
7✔
5646
      return get_bvconst64(vtbl, n, c);
7✔
5647
    }
5648

5649
    if (xtag == BVTAG_CONST) {
33✔
5650
      // large constants
5651
      assert(n > 64);
5652
      aux = &solver->aux1;
×
5653
      bvconstant_set_bitsize(aux, n);
×
5654
      bvconst_udiv2z(aux->data, n, bvvar_val(vtbl, x), bvvar_val(vtbl, y));
×
5655
      bvconstant_normalize(aux);
×
5656
      return get_bvconst(vtbl, n, aux->data);
×
5657
    }
5658
  }
5659

5660
  // no simplification
5661
  return get_bvdiv(vtbl, n, x, y);
89✔
5662
}
5663

5664

5665
/*
5666
 * Remainder of x/y: unsigned division, rounding toward 0
5667
 */
5668
thvar_t bv_solver_create_bvrem(bv_solver_t *solver, thvar_t x, thvar_t y) {
157✔
5669
  bv_vartable_t *vtbl;
5670
  bvconstant_t *aux;
5671
  bvvar_tag_t xtag, ytag;
5672
  uint64_t c;
5673
  uint32_t n;
5674
  thvar_t r;
5675

5676
  vtbl = &solver->vtbl;
157✔
5677

5678
  x = mtbl_get_root(&solver->mtbl, x);
157✔
5679
  y = mtbl_get_root(&solver->mtbl, y);
157✔
5680

5681
  n = bvvar_bitsize(vtbl, x);
157✔
5682
  assert(n == bvvar_bitsize(vtbl, y));
5683

5684
  xtag = bvvar_tag(vtbl, x);
157✔
5685
  ytag = bvvar_tag(vtbl, y);
157✔
5686

5687
  // deal with constants
5688
  if (xtag == ytag) {
157✔
5689
    if (xtag == BVTAG_CONST64) {
35✔
5690
      // small constants
5691
      assert(n <= 64);
5692
      c = bvconst64_urem2z(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
6✔
5693
      return get_bvconst64(vtbl, n, c);
6✔
5694
    }
5695

5696
    if (xtag == BVTAG_CONST) {
29✔
5697
      // large constants
5698
      assert(n > 64);
5699
      aux = &solver->aux1;
1✔
5700
      bvconstant_set_bitsize(aux, n);
1✔
5701
      bvconst_urem2z(aux->data, n, bvvar_val(vtbl, x), bvvar_val(vtbl, y));
1✔
5702
      bvconstant_normalize(aux);
1✔
5703
      return get_bvconst(vtbl, n, aux->data);
1✔
5704
    }
5705
  }
5706

5707
  if (equal_bvvar(solver, x, y)) {
150✔
5708
    // (bvrem x x) == 0 (this holds even if x = 0)
5709
    r = get_zero(solver, n);
×
5710
  } else {
5711
    // no simplification
5712
    r = get_bvrem(&solver->vtbl, n, x, y);
150✔
5713
    assert_urem_bounds(solver, r, y);  // EXPERIMENTAL
150✔
5714
  }
5715

5716
  return r;
150✔
5717
}
5718

5719

5720
/*
5721
 * Quotient x/y: signed division, rounding toward 0
5722
 */
5723
thvar_t bv_solver_create_bvsdiv(bv_solver_t *solver, thvar_t x, thvar_t y) {
87✔
5724
  bv_vartable_t *vtbl;
5725
  bvconstant_t *aux;
5726
  bvvar_tag_t xtag, ytag;
5727
  uint64_t c;
5728
  uint32_t n;
5729

5730
  vtbl = &solver->vtbl;
87✔
5731

5732
  x = mtbl_get_root(&solver->mtbl, x);
87✔
5733
  y = mtbl_get_root(&solver->mtbl, y);
87✔
5734

5735
  n = bvvar_bitsize(vtbl, x);
87✔
5736
  assert(n == bvvar_bitsize(vtbl, y));
5737

5738
  xtag = bvvar_tag(vtbl, x);
87✔
5739
  ytag = bvvar_tag(vtbl, y);
87✔
5740

5741
  // deal with constants
5742
  if (xtag == ytag) {
87✔
5743
    if (xtag == BVTAG_CONST64) {
22✔
5744
      // small constants
5745
      assert(n <= 64);
5746
      c = bvconst64_sdiv2z(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
1✔
5747
      return get_bvconst64(vtbl, n, c);
1✔
5748
    }
5749

5750
    if (xtag == BVTAG_CONST) {
21✔
5751
      // large constants
5752
      assert(n > 64);
5753
      aux = &solver->aux1;
3✔
5754
      bvconstant_set_bitsize(aux, n);
3✔
5755
      bvconst_sdiv2z(aux->data, n, bvvar_val(vtbl, x), bvvar_val(vtbl, y));
3✔
5756
      bvconstant_normalize(aux);
3✔
5757
      return get_bvconst(vtbl, n, aux->data);
3✔
5758
    }
5759
  }
5760

5761
  // no simplification
5762
  return get_bvsdiv(&solver->vtbl, n, x, y);
83✔
5763
}
5764

5765

5766
/*
5767
 * Remainder of x/y: signed division, rounding toward 0
5768
 */
5769
thvar_t bv_solver_create_bvsrem(bv_solver_t *solver, thvar_t x, thvar_t y) {
77✔
5770
  bv_vartable_t *vtbl;
5771
  bvconstant_t *aux;
5772
  bvvar_tag_t xtag, ytag;
5773
  uint64_t c;
5774
  uint32_t n;
5775
  thvar_t r;
5776

5777
  vtbl = &solver->vtbl;
77✔
5778

5779
  x = mtbl_get_root(&solver->mtbl, x);
77✔
5780
  y = mtbl_get_root(&solver->mtbl, y);
77✔
5781

5782
  n = bvvar_bitsize(vtbl, x);
77✔
5783
  assert(n == bvvar_bitsize(vtbl, y));
5784

5785
  xtag = bvvar_tag(vtbl, x);
77✔
5786
  ytag = bvvar_tag(vtbl, y);
77✔
5787

5788
  // deal with constants
5789
  if (xtag == ytag) {
77✔
5790
    if (xtag == BVTAG_CONST64) {
17✔
5791
      // small constants
5792
      assert(n <= 64);
5793
      c = bvconst64_srem2z(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
2✔
5794
      return get_bvconst64(vtbl, n, c);
2✔
5795
    }
5796

5797
    if (xtag == BVTAG_CONST) {
15✔
5798
      // large constants
5799
      assert(n > 64);
5800
      aux = &solver->aux1;
3✔
5801
      bvconstant_set_bitsize(aux, n);
3✔
5802
      bvconst_srem2z(aux->data, n, bvvar_val(vtbl, x), bvvar_val(vtbl, y));
3✔
5803
      bvconstant_normalize(aux);
3✔
5804
      return get_bvconst(vtbl, n, aux->data);
3✔
5805
    }
5806
  }
5807

5808
  if (equal_bvvar(solver, x, y)) {
72✔
5809
    // (bvsrem x x) == 0 (this holds even if x = 0)
5810
    r = get_zero(solver, n);
×
5811
  } else {
5812
    // no simplification
5813
    r = get_bvsrem(&solver->vtbl, n, x, y);
72✔
5814
    assert_srem_bounds(solver, r, y);
72✔
5815
  }
5816

5817
  return r;
72✔
5818
}
5819

5820

5821
/*
5822
 * Remainder in x/y: signed division, rounding toward -infinity
5823
 */
5824
thvar_t bv_solver_create_bvsmod(bv_solver_t *solver, thvar_t x, thvar_t y) {
×
5825
  bv_vartable_t *vtbl;
5826
  bvconstant_t *aux;
5827
  bvvar_tag_t xtag, ytag;
5828
  uint64_t c;
5829
  uint32_t n;
5830
  thvar_t r;
5831

5832
  vtbl = &solver->vtbl;
×
5833

5834
  x = mtbl_get_root(&solver->mtbl, x);
×
5835
  y = mtbl_get_root(&solver->mtbl, y);
×
5836

5837
  n = bvvar_bitsize(vtbl, x);
×
5838
  assert(n == bvvar_bitsize(vtbl, y));
5839

5840
  xtag = bvvar_tag(vtbl, x);
×
5841
  ytag = bvvar_tag(vtbl, y);
×
5842

5843
  // deal with constants
5844
  if (xtag == ytag) {
×
5845
    if (xtag == BVTAG_CONST64) {
×
5846
      // small constants
5847
      assert(n <= 64);
5848
      c = bvconst64_smod2z(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
×
5849
      return get_bvconst64(vtbl, n, c);
×
5850
    }
5851

5852
    if (xtag == BVTAG_CONST) {
×
5853
      // large constants
5854
      assert(n > 64);
5855
      aux = &solver->aux1;
×
5856
      bvconstant_set_bitsize(aux, n);
×
5857
      bvconst_smod2z(aux->data, n, bvvar_val(vtbl, x), bvvar_val(vtbl, y));
×
5858
      bvconstant_normalize(aux);
×
5859
      return get_bvconst(vtbl, n, aux->data);
×
5860
    }
5861
  }
5862

5863
  if (equal_bvvar(solver, x, y)) {
×
5864
    // (bvsmod x x) == 0 (this holds even if x = 0)
5865
    r = get_zero(solver, n);
×
5866
  } else {
5867
    // no simplification
5868
    r = get_bvsmod(&solver->vtbl, n, x, y);
×
5869
    assert_srem_bounds(solver, r, y);
×
5870
  }
5871

5872
  return r;
×
5873
}
5874

5875

5876
/*
5877
 * Left shift, padding with zeros
5878
 */
5879
thvar_t bv_solver_create_bvshl(bv_solver_t *solver, thvar_t x, thvar_t y) {
89✔
5880
  bv_vartable_t *vtbl;
5881
  bvconstant_t *aux;
5882
  bvvar_tag_t xtag, ytag;
5883
  uint32_t n;
5884
  uint64_t c;
5885

5886
  vtbl = &solver->vtbl;
89✔
5887

5888
  x = mtbl_get_root(&solver->mtbl, x);
89✔
5889
  y = mtbl_get_root(&solver->mtbl, y);
89✔
5890

5891
  n = bvvar_bitsize(vtbl, x);
89✔
5892
  assert(bvvar_bitsize(vtbl, y) == n);
5893

5894
  xtag = bvvar_tag(vtbl, x);
89✔
5895
  ytag = bvvar_tag(vtbl, y);
89✔
5896

5897
  // deal with constants
5898
  if (xtag == ytag) {
89✔
5899
    if (xtag == BVTAG_CONST64) {
33✔
5900
      // small constants
5901
      assert(n <= 64);
5902
      c = bvconst64_lshl(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
1✔
5903
      return get_bvconst64(vtbl, n, c);
1✔
5904
    }
5905

5906
    if (xtag == BVTAG_CONST) {
32✔
5907
      assert(n > 64);
5908
      aux = &solver->aux1;
2✔
5909
      bvconstant_set_bitsize(aux, n);
2✔
5910
      bvconst_lshl(aux->data, bvvar_val(vtbl, x), bvvar_val(vtbl, y), n);
2✔
5911
      return get_bvconst(vtbl, n, aux->data);
2✔
5912
    }
5913
  }
5914

5915
  if (bvvar_is_zero(vtbl, x)) {
86✔
5916
    // 0b000..0 unchanged by logical shift
5917
    return x;
×
5918
  }
5919

5920
  return get_bvshl(vtbl, n, x, y);
86✔
5921
}
5922

5923

5924
/*
5925
 * Right shift, padding with zeros
5926
 */
5927
thvar_t bv_solver_create_bvlshr(bv_solver_t *solver, thvar_t x, thvar_t y) {
1,778✔
5928
  bv_vartable_t *vtbl;
5929
  bvconstant_t *aux;
5930
  bvvar_tag_t xtag, ytag;
5931
  uint32_t n;
5932
  uint64_t c;
5933

5934

5935
  vtbl = &solver->vtbl;
1,778✔
5936

5937
  x = mtbl_get_root(&solver->mtbl, x);
1,778✔
5938
  y = mtbl_get_root(&solver->mtbl, y);
1,778✔
5939

5940
  n = bvvar_bitsize(vtbl, x);
1,778✔
5941
  assert(bvvar_bitsize(vtbl, y) == n);
5942

5943
  xtag = bvvar_tag(vtbl, x);
1,778✔
5944
  ytag = bvvar_tag(vtbl, y);
1,778✔
5945

5946
  // deal with constants
5947
  if (xtag == ytag) {
1,778✔
5948
    if (xtag == BVTAG_CONST64) {
32✔
5949
      // small constants
5950
      assert(n <= 64);
5951
      c = bvconst64_lshr(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
3✔
5952
      return get_bvconst64(vtbl, n, c);
3✔
5953
    }
5954

5955
    if (xtag == BVTAG_CONST) {
29✔
5956
      assert(n > 64);
5957
      aux = &solver->aux1;
1✔
5958
      bvconstant_set_bitsize(aux, n);
1✔
5959
      bvconst_lshr(aux->data, bvvar_val(vtbl, x), bvvar_val(vtbl, y), n);
1✔
5960
      return get_bvconst(vtbl, n, aux->data);
1✔
5961
    }
5962
  }
5963

5964
  if (bvvar_is_zero(vtbl, x)) {
1,774✔
5965
    // 0b000..0 unchanged by logical shift
5966
    return x;
2✔
5967
  }
5968

5969
  return get_bvlshr(vtbl, n, x, y);
1,772✔
5970
}
5971

5972

5973
/*
5974
 * Arithmetic right shift
5975
 */
5976
thvar_t bv_solver_create_bvashr(bv_solver_t *solver, thvar_t x, thvar_t y) {
517✔
5977
  bv_vartable_t *vtbl;
5978
  bvconstant_t *aux;
5979
  bvvar_tag_t xtag, ytag;
5980
  uint32_t n;
5981
  uint64_t c;
5982

5983
  vtbl = &solver->vtbl;
517✔
5984

5985
  x = mtbl_get_root(&solver->mtbl, x);
517✔
5986
  y = mtbl_get_root(&solver->mtbl, y);
517✔
5987

5988
  n = bvvar_bitsize(vtbl, x);
517✔
5989
  assert(bvvar_bitsize(vtbl, y) == n);
5990

5991
  xtag = bvvar_tag(vtbl, x);
517✔
5992
  ytag = bvvar_tag(vtbl, y);
517✔
5993

5994
  // deal with constants
5995
  if (xtag == ytag) {
517✔
5996
    if (xtag == BVTAG_CONST64) {
154✔
5997
      // small constants
5998
      assert(n <= 64);
5999
      c = bvconst64_ashr(bvvar_val64(vtbl, x), bvvar_val64(vtbl, y), n);
5✔
6000
      return get_bvconst64(vtbl, n, c);
5✔
6001
    }
6002

6003
    if (xtag == BVTAG_CONST) {
149✔
6004
      assert(n > 64);
6005
      aux = &solver->aux1;
1✔
6006
      bvconstant_set_bitsize(aux, n);
1✔
6007
      bvconst_ashr(aux->data, bvvar_val(vtbl, x), bvvar_val(vtbl, y), n);
1✔
6008
      return get_bvconst(vtbl, n, aux->data);
1✔
6009
    }
6010
  }
6011

6012
  if (bvvar_is_zero(vtbl, x) || bvvar_is_minus_one(vtbl, x)) {
511✔
6013
    // 0b000..0 and 0b11...1 are unchanged by any arithmetic shift
6014
    return x;
×
6015
  }
6016

6017
  return get_bvashr(vtbl, n, x, y);
511✔
6018
}
6019

6020

6021
/*
6022
 * Return the i-th bit of theory variable x as a literal
6023
 */
6024
literal_t bv_solver_select_bit(bv_solver_t *solver, thvar_t x, uint32_t i) {
304,378✔
6025
  bv_vartable_t *vtbl;
6026
  literal_t l;
6027

6028
  assert(valid_bvvar(&solver->vtbl, x) && i < bvvar_bitsize(&solver->vtbl, x));
6029

6030
  // apply substitutions
6031
  x = mtbl_get_root(&solver->mtbl, x);
304,378✔
6032

6033
  vtbl = &solver->vtbl;
304,378✔
6034
  switch (bvvar_tag(vtbl, x)) {
304,378✔
6035
  case BVTAG_CONST64:
890✔
6036
    l = bvconst64_get_bit(vtbl, x, i);
890✔
6037
    break;
890✔
6038

6039
  case BVTAG_CONST:
1,128✔
6040
    l = bvconst_get_bit(vtbl, x, i);
1,128✔
6041
    break;
1,128✔
6042

6043
  case BVTAG_BIT_ARRAY:
264✔
6044
    l = bvarray_get_bit(vtbl, x, i);
264✔
6045
    break;
264✔
6046

6047
  default:
302,096✔
6048
    l = bvvar_get_bit(solver, x, i);
302,096✔
6049
    break;
302,096✔
6050
  }
6051

6052
  return l;
304,378✔
6053
}
6054

6055

6056
/*
6057
 * ATOM CONSTRUCTORS
6058
 */
6059

6060
/*
6061
 * Atom (eq x y): no simplification
6062
 */
6063
static literal_t bv_solver_make_eq_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
5,694✔
6064
  bv_atomtable_t *atbl;
6065
  int32_t i;
6066
  literal_t l;
6067
  bvar_t v;
6068

6069
  atbl = &solver->atbl;
5,694✔
6070
  i = get_bveq_atom(atbl, x, y);
5,694✔
6071
  l = atbl->data[i].lit;
5,694✔
6072

6073
  if (l == null_literal) {
5,694✔
6074
    /*
6075
     * New atom: assign a fresh boolean variable for it
6076
     */
6077
    v = create_boolean_variable(solver->core);
5,486✔
6078
    l = pos_lit(v);
5,486✔
6079
    atbl->data[i].lit = l;
5,486✔
6080
    attach_atom_to_bvar(solver->core, v, bvatom_idx2tagged_ptr(i));
5,486✔
6081
    solver->stats.eq_atoms ++;
5,486✔
6082
  }
6083

6084
  return l;
5,694✔
6085
}
6086

6087

6088
/*
6089
 * Atom (eq x y): try to simplify
6090
 */
6091
literal_t bv_solver_create_eq_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
4,928✔
6092
#if TRACE
6093
  if (bvvar_bitsize(&solver->vtbl, x) == 1) {
6094
    printf("---> create (bveq u!%"PRId32" u!%"PRId32")\n", x, y);
6095
    printf("     ");
6096
    print_bv_solver_vardef(stdout, solver, x);
6097
    printf("     ");
6098
    print_bv_solver_vardef(stdout, solver, y);
6099
  }
6100
#endif
6101
  x = mtbl_get_root(&solver->mtbl, x);
4,928✔
6102
  y = mtbl_get_root(&solver->mtbl, y);
4,928✔
6103

6104
  if (equal_bvvar(solver, x, y)) return true_literal;
4,928✔
6105
  if (diseq_bvvar(solver, x, y)) return false_literal;
4,913✔
6106
  //  if (bounds_imply_diseq(solver, x, y)) return false_literal;
6107

6108
  if (simplify_eq(solver, &x, &y)) {
4,678✔
6109
    if (x == y) return true_literal;
159✔
6110
    if (diseq_bvvar(solver, x, y)) return false_literal;
158✔
6111
    //    if (bounds_imply_diseq(solver, x, y)) return false_literal;
6112
  }
6113

6114
  return bv_solver_make_eq_atom(solver, x, y);
4,674✔
6115
}
6116

6117

6118
/*
6119
 * Create (bvge x y)
6120
 */
6121
static literal_t bv_solver_make_ge_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
3,268✔
6122
  bv_atomtable_t *atbl;
6123
  int32_t i;
6124
  literal_t l;
6125
  bvar_t v;
6126

6127
  atbl = &solver->atbl;
3,268✔
6128
  i = get_bvuge_atom(atbl, x, y);
3,268✔
6129
  l = atbl->data[i].lit;
3,268✔
6130
  if (l == null_literal) {
3,268✔
6131
    /*
6132
     * New atom: assign a fresh boolean variable for it
6133
     */
6134
    v = create_boolean_variable(solver->core);
3,256✔
6135
    l = pos_lit(v);
3,256✔
6136
    atbl->data[i].lit = l;
3,256✔
6137
    attach_atom_to_bvar(solver->core, v, bvatom_idx2tagged_ptr(i));
3,256✔
6138
    solver->stats.ge_atoms ++;
3,256✔
6139
  }
6140

6141
  return l;
3,268✔
6142
}
6143

6144

6145
/*
6146
 * Atom (bvge x y) (unsigned comparison)
6147
 */
6148
literal_t bv_solver_create_ge_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
2,435✔
6149
  literal_t l;
6150

6151
#if TRACE
6152
  if (bvvar_bitsize(&solver->vtbl, x) == 1) {
6153
    printf("---> create (bvge u!%"PRId32" u!%"PRId32")\n", x, y);
6154
    printf("     ");
6155
    print_bv_solver_vardef(stdout, solver, x);
6156
    printf("     ");
6157
    print_bv_solver_vardef(stdout, solver, y);
6158
  }
6159
#endif
6160

6161
  x = mtbl_get_root(&solver->mtbl, x);
2,435✔
6162
  y = mtbl_get_root(&solver->mtbl, y);
2,435✔
6163

6164
  /*
6165
   * Rewrite rules:
6166
   * (bvge 0b000...0 y)  <-->  (bveq 0b000...0 y)
6167
   * (bvge x 0b111...1)  <-->  (bveq x 0b111...1)
6168
   */
6169
  if (bvvar_is_zero(&solver->vtbl, x) ||
4,838✔
6170
      bvvar_is_minus_one(&solver->vtbl, y)) {
2,403✔
6171
    return bv_solver_create_eq_atom(solver, x, y);
101✔
6172
  }
6173

6174
  switch (check_bvuge(solver, x, y)) {
2,334✔
6175
  case BVTEST_FALSE:
23✔
6176
    l = false_literal;
23✔
6177
    break;
23✔
6178

6179
  case BVTEST_TRUE:
95✔
6180
    l = true_literal;
95✔
6181
    break;
95✔
6182

6183
  default:
2,216✔
6184
    l = bv_solver_make_ge_atom(solver, x, y);
2,216✔
6185
    break;
2,216✔
6186
  }
6187

6188
  return l;
2,334✔
6189
}
6190

6191

6192
/*
6193
 * Create (bvsge x y): no simplification
6194
 */
6195
static literal_t bv_solver_make_sge_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
3,856✔
6196
  bv_atomtable_t *atbl;
6197
  int32_t i;
6198
  literal_t l;
6199
  bvar_t v;
6200

6201
  atbl = &solver->atbl;
3,856✔
6202
  i = get_bvsge_atom(atbl, x, y);
3,856✔
6203
  l = atbl->data[i].lit;
3,856✔
6204
  if (l == null_literal) {
3,856✔
6205
    /*
6206
     * New atom: assign a fresh boolean variable for it
6207
     */
6208
    v = create_boolean_variable(solver->core);
3,845✔
6209
    l = pos_lit(v);
3,845✔
6210
    atbl->data[i].lit = l;
3,845✔
6211
    attach_atom_to_bvar(solver->core, v, bvatom_idx2tagged_ptr(i));
3,845✔
6212
    solver->stats.sge_atoms ++;
3,845✔
6213
  }
6214

6215
  return l;
3,856✔
6216
}
6217

6218

6219
/*
6220
 * Atom (bvsge x y) (signed comparison)
6221
 */
6222
literal_t bv_solver_create_sge_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
3,599✔
6223
  literal_t l;
6224

6225
#if TRACE
6226
  if (bvvar_bitsize(&solver->vtbl, x) == 1) {
6227
    printf("---> create (bvsge u!%"PRId32" u!%"PRId32")\n", x, y);
6228
    printf("     ");
6229
    print_bv_solver_vardef(stdout, solver, x);
6230
    printf("     ");
6231
    print_bv_solver_vardef(stdout, solver, y);
6232
  }
6233
#endif
6234

6235
  x = mtbl_get_root(&solver->mtbl, x);
3,599✔
6236
  y = mtbl_get_root(&solver->mtbl, y);
3,599✔
6237

6238
  /*
6239
   * Rewrite rules:
6240
   * (bvsge 0b100...0 y)  <-->  (bveq 0b100...0 y)
6241
   * (bvsge x 0b011...1)  <-->  (bveq x 0b011...1)
6242
   */
6243
  if (bvvar_is_min_signed(&solver->vtbl, x) ||
7,182✔
6244
      bvvar_is_max_signed(&solver->vtbl, y)) {
3,583✔
6245
    return bv_solver_create_eq_atom(solver, x, y);
26✔
6246
  }
6247

6248
  switch (check_bvsge(solver, x, y)) {
3,573✔
6249
  case BVTEST_FALSE:
49✔
6250
    l = false_literal;
49✔
6251
    break;
49✔
6252

6253
  case BVTEST_TRUE:
98✔
6254
    l = true_literal;
98✔
6255
    break;
98✔
6256

6257
  default:
3,426✔
6258
    l = bv_solver_make_sge_atom(solver, x, y);
3,426✔
6259
    break;
3,426✔
6260
  }
6261

6262
  return l;
3,573✔
6263
}
6264

6265

6266

6267
/*
6268
 * ATOM ASSERTIONS
6269
 */
6270

6271
/*
6272
 * Assert (x != y) where y is the constant 0b0000..0
6273
 * - this special case is handled separately since we want to add the
6274
 *   constraint (x != y) to the bound queue (unless it's already there).
6275
 */
6276
static void bv_solver_assert_neq0(bv_solver_t *solver, thvar_t x, thvar_t y) {
927✔
6277
  bv_atomtable_t *atbl;
6278
  int32_t i;
6279
  literal_t l;
6280
  bvar_t v;
6281

6282
  assert(bvvar_is_zero(&solver->vtbl, y));
6283
  atbl = &solver->atbl;
927✔
6284
  i = get_bveq_atom(atbl, x, y);
927✔
6285
  l = atbl->data[i].lit;
927✔
6286
  if (l == null_literal) {
927✔
6287
    /*
6288
     * New atom: (x != 0) can't be in the bound queue
6289
     */
6290
    v = create_boolean_variable(solver->core);
914✔
6291
    l = pos_lit(v);
914✔
6292
    atbl->data[i].lit = l;
914✔
6293
    attach_atom_to_bvar(solver->core, v, bvatom_idx2tagged_ptr(i));
914✔
6294
    push_bvdiseq_bound(solver, x, y);
914✔
6295

6296
  } else if (! bvvar_is_nonzero(solver, x)) {
13✔
6297
    /*
6298
     * The bound (x != 0) is not in the queue yet: add it
6299
     */
6300
    push_bvdiseq_bound(solver, x, y);
5✔
6301
  }
6302

6303
  add_unit_clause(solver->core, not(l));
927✔
6304
}
927✔
6305

6306

6307
/*
6308
 * Assert (x == y) if tt is true
6309
 * assert (x != y) if tt is false
6310
 */
6311
void bv_solver_assert_eq_axiom(bv_solver_t *solver, thvar_t x, thvar_t y, bool tt) {
12,632✔
6312
  literal_t l;
6313

6314
#if TRACE
6315
  if (bvvar_bitsize(&solver->vtbl, x) == 1) {
6316
    printf("---> assert (bveq u!%"PRId32" u!%"PRId32")\n", x, y);
6317
    printf("     ");
6318
    print_bv_solver_vardef(stdout, solver, x);
6319
    printf("     ");
6320
    print_bv_solver_vardef(stdout, solver, y);
6321
  }
6322
#endif
6323

6324
  x = mtbl_get_root(&solver->mtbl, x);
12,632✔
6325
  y = mtbl_get_root(&solver->mtbl, y);
12,632✔
6326

6327
  if (equal_bvvar(solver, x, y)) {
12,632✔
6328
    if (! tt) add_empty_clause(solver->core);     // Contradiction
36✔
6329
    return;
36✔
6330
  }
6331

6332
  //  if (diseq_bvvar(solver, x, y) || bounds_imply_diseq(solver, x, y)) {
6333
  if (diseq_bvvar(solver, x, y)) {
12,596✔
6334
    if (tt) add_empty_clause(solver->core);       // Contradiction
189✔
6335
    return;
189✔
6336
  }
6337

6338
  // try to simplify
6339
  if (simplify_eq(solver, &x, &y)) {
12,407✔
6340
    // simplify may result in x == y
6341
    if (x == y) {
113✔
6342
      if (! tt) add_empty_clause(solver->core);
×
6343
      return;
×
6344
    }
6345

6346
    //    if (diseq_bvvar(solver, x, y) || bounds_imply_diseq(solver, x, y)) {
6347
    if (diseq_bvvar(solver, x, y)) {
113✔
6348
      if (tt) add_empty_clause(solver->core);
4✔
6349
      return;
4✔
6350
    }
6351
  }
6352

6353

6354
  /*
6355
   * No contradiction detected
6356
   */
6357
  if (tt) {
12,403✔
6358
    // x == y: merge the classes of x and y
6359
    bv_solver_merge_vars(solver, x, y);
10,456✔
6360
  } else if (bvvar_is_zero(&solver->vtbl, x)) {
1,947✔
6361
    // y != 0
6362
    bv_solver_assert_neq0(solver, y, x);
200✔
6363
  } else if (bvvar_is_zero(&solver->vtbl, y)) {
1,747✔
6364
    // x != 0
6365
    bv_solver_assert_neq0(solver, x, y);
727✔
6366
  } else {
6367
    // Add the constraint (x != y)
6368
    l = bv_solver_make_eq_atom(solver, x, y);
1,020✔
6369
    add_unit_clause(solver->core, not(l));
1,020✔
6370
  }
6371
}
6372

6373

6374
/*
6375
 * Assert (bvge x y) if tt is true
6376
 * Assert (not (bvge x y)) if tt is false
6377
 */
6378
void bv_solver_assert_ge_axiom(bv_solver_t *solver, thvar_t x, thvar_t y, bool tt) {
1,461✔
6379
  literal_t l;
6380

6381
#if TRACE
6382
  if (bvvar_bitsize(&solver->vtbl, x) == 1) {
6383
    printf("---> assert (bvge u!%"PRId32" u!%"PRId32")\n", x, y);
6384
    printf("     ");
6385
    print_bv_solver_vardef(stdout, solver, x);
6386
    printf("     ");
6387
    print_bv_solver_vardef(stdout, solver, y);
6388
  }
6389
#endif
6390

6391
  x = mtbl_get_root(&solver->mtbl, x);
1,461✔
6392
  y = mtbl_get_root(&solver->mtbl, y);
1,461✔
6393

6394
  /*
6395
   * Rewrite rules:
6396
   * (bvge 0b000...0 y)  <-->  (bveq 0b000...0 y)
6397
   * (bvge x 0b111...1)  <-->  (bveq x 0b111...1)
6398
   *
6399
   * Also if we already have (bvge y x), we can rewrite (bvge x y) to (bveq x y).
6400
   * We do this if tt is true or if introducing (bveq x y) may help.
6401
   */
6402
  if (bvvar_is_zero(&solver->vtbl, x) ||
2,907✔
6403
      bvvar_is_minus_one(&solver->vtbl, y) ||
2,892✔
6404
      (tt && bvuge_simplifies_to_bveq(solver, x, y))) {
1,000✔
6405
    bv_solver_assert_eq_axiom(solver, x, y, tt);
18✔
6406

6407
  } else {
6408
    switch (check_bvuge(solver, x, y)) {
1,443✔
6409
    case BVTEST_FALSE:
164✔
6410
      if (tt) add_empty_clause(solver->core); // x < y holds
164✔
6411
      break;
164✔
6412

6413
    case BVTEST_TRUE:
227✔
6414
      if (!tt) add_empty_clause(solver->core); // x >= y holds
227✔
6415
      break;
227✔
6416

6417
    case BVTEST_UNKNOWN:
1,052✔
6418
      l = bv_solver_make_ge_atom(solver, x, y);
1,052✔
6419
      add_unit_clause(solver->core, signed_literal(l, tt));
1,052✔
6420
      // push the bound into the queue
6421
      if (is_bv_bound_pair(&solver->vtbl, x, y)) {
1,052✔
6422
        push_bvuge_bound(solver, x, y);
659✔
6423
      }
6424
      break;
1,052✔
6425
    }
6426
  }
6427
}
1,461✔
6428

6429

6430
/*
6431
 * Assert (bvsge x y) if tt is true
6432
 * Assert (not (bvsge x y)) if tt is false
6433
 */
6434
void bv_solver_assert_sge_axiom(bv_solver_t *solver, thvar_t x, thvar_t y, bool tt) {
459✔
6435
  literal_t l;
6436

6437
#if TRACE
6438
  if (bvvar_bitsize(&solver->vtbl, x) == 1) {
6439
    printf("---> assert (bvsge u!%"PRId32" u!%"PRId32")\n", x, y);
6440
    printf("     ");
6441
    print_bv_solver_vardef(stdout, solver, x);
6442
    printf("     ");
6443
    print_bv_solver_vardef(stdout, solver, y);
6444
  }
6445
#endif
6446

6447
  x = mtbl_get_root(&solver->mtbl, x);
459✔
6448
  y = mtbl_get_root(&solver->mtbl, y);
459✔
6449

6450
  /*
6451
   * Rewrite rules:
6452
   * (bvsge 0b100...0 y)  <-->  (bveq 0b100...0 y)
6453
   * (bvsge x 0b011...1)  <-->  (bveq x 0b011...1)
6454
   *
6455
   * Also, if we already have (bvsge y x), we can rewrite (bvsge x y) to (bveq x y).
6456
   * We do this if tt is true or if introducing (bveq x y) may help.   
6457
   */
6458
  if (bvvar_is_min_signed(&solver->vtbl, x) ||
916✔
6459
      bvvar_is_max_signed(&solver->vtbl, y) ||
914✔
6460
      (tt && bvsge_simplifies_to_bveq(solver, x, y))) {
388✔
6461
    bv_solver_assert_eq_axiom(solver, x, y, tt);
2✔
6462

6463
  } else {
6464
    switch (check_bvsge(solver, x, y)) {
457✔
6465
    case BVTEST_FALSE:
5✔
6466
      if (tt) add_empty_clause(solver->core); // x < y holds
5✔
6467
      break;
5✔
6468

6469
    case BVTEST_TRUE:
22✔
6470
      if (!tt) add_empty_clause(solver->core); // x >= y holds
22✔
6471
      break;
22✔
6472

6473
    case BVTEST_UNKNOWN:
430✔
6474
      l = bv_solver_make_sge_atom(solver, x, y);
430✔
6475
      add_unit_clause(solver->core, signed_literal(l, tt));
430✔
6476
      // push the bound into the queue
6477
      if (is_bv_bound_pair(&solver->vtbl, x, y)) {
430✔
6478
        push_bvsge_bound(solver, x, y);
353✔
6479
      }
6480
      break;
430✔
6481
    }
6482
  }
6483
}
459✔
6484

6485

6486
/*
6487
 * Assert that bit i of x is equal to tt
6488
 */
6489
void bv_solver_set_bit(bv_solver_t *solver, thvar_t x, uint32_t i, bool tt) {
32,074✔
6490
  literal_t l;
6491

6492
  l = bv_solver_select_bit(solver, x, i);
32,074✔
6493
  add_unit_clause(solver->core, signed_literal(l, tt));
32,074✔
6494
}
32,074✔
6495

6496

6497

6498
/*
6499
 * EGRAPH TERMS
6500
 */
6501

6502
/*
6503
 * Attach egraph term t to variable x
6504
 */
6505
void bv_solver_attach_eterm(bv_solver_t *solver, thvar_t x, eterm_t t) {
9,552✔
6506
  attach_eterm_to_bvvar(&solver->vtbl, x, t);
9,552✔
6507
}
9,552✔
6508

6509

6510
/*
6511
 * Get the egraph term attached to x
6512
 * - return null_eterm if x has no eterm attached
6513
 */
6514
eterm_t bv_solver_eterm_of_var(bv_solver_t *solver, thvar_t x) {
607,639✔
6515
  return bvvar_get_eterm(&solver->vtbl, x);
607,639✔
6516
}
6517

6518

6519

6520
/*
6521
 * COMPILATION RESULTS
6522
 */
6523

6524
/*
6525
 * Get the compilation of variable x
6526
 * - return null_thvar if x is not compiled to anything
6527
 */
6528
thvar_t bv_solver_var_compiles_to(bv_solver_t *solver, thvar_t x) {
×
6529
  bvc_t *c;
6530
  thvar_t y;
6531

6532
  y = null_thvar;
×
6533
  c = solver->compiler;
×
6534
  if (c != NULL) {
×
6535
    y = bvvar_compiles_to(c, x);
×
6536
  }
6537

6538
  return y;
×
6539
}
6540

6541

6542

6543

6544

6545
/*******************************************************
6546
 *  EQUALITIES/DISEQUALITIES RECEIVED FROM THE EGRAPH  *
6547
 ******************************************************/
6548

6549
/*
6550
 * Equality atom created after bitblasting
6551
 */
6552
static literal_t on_the_fly_eq_atom(bv_solver_t *solver, thvar_t x, thvar_t y) {
6,941✔
6553
  bv_atomtable_t *atbl;
6554
  ivector_t *a, *b;
6555
  int32_t i;
6556
  literal_t l, l0;
6557
  bvar_t v;
6558

6559
#if TRACE
6560
  printf("---> on the fly (bveq u!%"PRId32" u!%"PRId32")\n", x, y);
6561
  printf("     ");
6562
  print_bv_solver_vardef(stdout, solver, x);
6563
  printf("     ");
6564
  print_bv_solver_vardef(stdout, solver, y);
6565
#endif
6566

6567
  x = mtbl_get_root(&solver->mtbl, x);
6,941✔
6568
  y = mtbl_get_root(&solver->mtbl, y);
6,941✔
6569

6570
  if (equal_bvvar(solver, x, y)) return true_literal;
6,941✔
6571
  if (diseq_bvvar(solver, x, y)) return false_literal;
6,941✔
6572
  //  if (bounds_imply_diseq(solver, x, y)) return false_literal;
6573

6574
  if (simplify_eq(solver, &x, &y)) {
6,941✔
6575
    if (x == y) return true_literal;
449✔
6576
    if (diseq_bvvar(solver, x, y)) return false_literal;
449✔
6577
    //    if (bounds_imply_diseq(solver, x, y)) return false_literal;
6578
  }
6579

6580
  // check whether (bveq x y) exists already
6581
  atbl = &solver->atbl;
6,941✔
6582
  i = get_bveq_atom(atbl, x, y);
6,941✔
6583
  l = atbl->data[i].lit;
6,941✔
6584
  if (l == null_literal) {
6,941✔
6585
    if (solver->bitblasted) {
6,433✔
6586
      /*
6587
       * After bitblasting
6588
       */
6589
      solver->stats.on_the_fly_atoms ++;
6,433✔
6590

6591
      bv_solver_bitblast_variable(solver, x);
6,433✔
6592
      bv_solver_bitblast_variable(solver, y);
6,433✔
6593
      a = &solver->a_vector;
6,433✔
6594
      b = &solver->b_vector;
6,433✔
6595
      collect_bvvar_literals(solver, x, a);
6,433✔
6596
      collect_bvvar_literals(solver, y, b);
6,433✔
6597
      assert(a->size == b->size && a->size > 0);
6598

6599
      l = bit_blaster_make_bveq(solver->blaster, a->data, b->data, a->size);
6,433✔
6600
      atbl->data[i].lit = l;
6,433✔
6601
      v = var_of(l);
6,433✔
6602
      if (bvar_has_atom(solver->core, v)) {
6,433✔
6603
        // need a fresh variable
6604
        v = create_boolean_variable(solver->core);
9✔
6605
        l0 = pos_lit(v);
9✔
6606
        atbl->data[i].lit = l0;
9✔
6607
        // assert (l == l0) in the core
6608
        bit_blaster_eq(solver->blaster, l, l0);
9✔
6609
        l = l0;
9✔
6610
      }
6611

6612
    } else {
6613
      /*
6614
       * Before bitblasting: assign a fresh variable to the atom
6615
       */
6616
      solver->stats.eq_atoms ++;
×
6617

6618
      v = create_boolean_variable(solver->core);
×
6619
      l = pos_lit(v);
×
6620
      atbl->data[i].lit = l;
×
6621
    }
6622

6623
    attach_atom_to_bvar(solver->core, v, bvatom_idx2tagged_ptr(i));
6,433✔
6624

6625
  }
6626

6627
  return l;
6,941✔
6628
}
6629

6630

6631
/*
6632
 * Return the lemma cache
6633
 * - allocate and initialize it if needed
6634
 */
6635
static cache_t *bv_solver_get_cache(bv_solver_t *solver) {
108,829✔
6636
  cache_t *c;
6637

6638
  c = solver->cache;
108,829✔
6639
  if (c == NULL) {
108,829✔
6640
    c = (cache_t *) safe_malloc(sizeof(cache_t));
35✔
6641
    // initialize then synchronize the cache with
6642
    // the current push/pop level
6643
    init_cache(c);
35✔
6644
    cache_set_level(c, solver->base_level);
35✔
6645
    solver->cache = c;
35✔
6646
  }
6647

6648
  return c;
108,829✔
6649
}
6650

6651

6652
#if 0
6653
/*
6654
 * PROVISIONAL:
6655
 * - try to check whether a bvequiv_lemma is needed
6656
 */
6657
static void diagnose_bvequiv(bv_solver_t *solver, thvar_t x1, thvar_t y1) {
6658
  bv_atomtable_t *atbl;
6659
  ivector_t *a, *b;
6660
  thvar_t x, y;
6661
  int32_t i;
6662
  literal_t l, l1, l2;
6663
  uint32_t j, n;
6664

6665
  x = mtbl_get_root(&solver->mtbl, x1);
6666
  y = mtbl_get_root(&solver->mtbl, y1);
6667

6668
  if (equal_bvvar(solver, x, y)) {
6669
    printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is true (by mtbl_get_root)\n", x1, y1);
6670
    fflush(stdout);
6671
    return;
6672
  }
6673

6674
  if (diseq_bvvar(solver, x, y)) {
6675
    printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is false (by diseq_bvvar)\n", x1, y1);
6676
    fflush(stdout);
6677
    return;
6678
  }
6679

6680
  if (simplify_eq(solver, &x, &y)) {
6681
    if (x == y) {
6682
      printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is true (by simplify_eq)\n", x1, y1);
6683
      fflush(stdout);
6684
      return;
6685
    }
6686
    if (diseq_bvvar(solver, x, y)) {
6687
      printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is false (by diseq_bvvar)\n", x1, y1);
6688
      fflush(stdout);
6689
      return;
6690
    }
6691
  }
6692

6693
  atbl = &solver->atbl;
6694
  i = find_bveq_atom(atbl, x, y);
6695
  if (i >= 0) {
6696
    // the atom exists
6697
    l = atbl->data[i].lit;
6698
    switch (literal_value(solver->core, l)) {
6699
    case VAL_FALSE:
6700
      printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is false (atom set to false)\n", x1, y1);
6701
      fflush(stdout);
6702
      return;
6703

6704
    case VAL_TRUE:
6705
      printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is true (atom set to true)\n", x1, y1);
6706
      fflush(stdout);
6707
      return;
6708

6709
    case VAL_UNDEF_FALSE:
6710
    case VAL_UNDEF_TRUE:
6711
      break;
6712
    }
6713
  }
6714

6715
  if (solver->bitblasted &&
6716
      bvvar_is_bitblasted(&solver->vtbl, x) &&
6717
      bvvar_is_bitblasted(&solver->vtbl, y)) {
6718

6719
    a = &solver->a_vector;
6720
    b = &solver->b_vector;
6721
    collect_bvvar_literals(solver, x, a);
6722
    collect_bvvar_literals(solver, y, b);
6723
    n = a->size;
6724
    assert(b->size == n);
6725

6726
    for (j=0; j<n; j++) {
6727
      l1 = a->data[j];
6728
      l2 = b->data[j];
6729
      if ((literal_value(solver->core, l1) == VAL_FALSE && literal_value(solver->core, l2) == VAL_TRUE)
6730
          || (literal_value(solver->core, l1) == VAL_TRUE && literal_value(solver->core, l2) == VAL_FALSE)) {
6731
        printf("---> BVSOLVER: bvequiv: (bveq u!%"PRId32" u!%"PRId32") is false (bits %"PRIu32" differ)\n", x1, y1, j);
6732
        fflush(stdout);
6733
        return;
6734
      }
6735
    }
6736
  }
6737
}
6738

6739
#endif
6740

6741

6742
/*
6743
 * Check whether the lemma (eq t1 t2) <=> (bveq x1 x2) is redundant.
6744
 * - return true if the atom (bveq x1 x2) exists and is already true
6745
 */
6746
static bool bv_solver_bvequiv_redundant(bv_solver_t *solver, thvar_t x1, thvar_t x2) {
438,608✔
6747
  bv_atomtable_t *atbl;
6748
  thvar_t y1, y2;
6749
  int32_t i;
6750
  literal_t l;
6751

6752
  y1 = mtbl_get_root(&solver->mtbl, x1);
438,608✔
6753
  y2 = mtbl_get_root(&solver->mtbl, x2);
438,608✔
6754

6755
  if (equal_bvvar(solver, y1, y2)) {
438,608✔
6756
    return true;
×
6757
  }
6758

6759
  if (simplify_eq(solver, &y1, &y2)  && y1 == y2) {
438,608✔
6760
    return true;
×
6761
  }
6762

6763
  atbl = &solver->atbl;
438,608✔
6764
  i = find_bveq_atom(atbl, y1, y2);
438,608✔
6765
  if (i >= 0) {
438,608✔
6766
    l = atbl->data[i].lit;
433,964✔
6767
    return literal_value(solver->core, l) == VAL_TRUE;
433,964✔
6768
  }
6769

6770
  return false;
4,644✔
6771
}
6772

6773

6774
#if 0
6775

6776
// DISABLED THIS. DOES NOT SEEM TO HELP
6777

6778
/*
6779
 * Variant of the bvequiv lemma: to avoid creating the egraph atom (eq t1 t2),
6780
 * we can generate the clause (p1 /\ ... /\ p_n => (bveq x1 x2))
6781
 * - where p1 /\ ... /\ p_n is the explanation for (t1 == t2)
6782
 */
6783
static void bv_solver_half_equiv_lemma(bv_solver_t *solver, thvar_t x1, thvar_t x2, eterm_t t1, eterm_t t2) {
6784
  ivector_t *v;
6785
  literal_t l;
6786
  uint32_t i, n;
6787

6788
  l = on_the_fly_eq_atom(solver, x1, x2);
6789
  v = &solver->aux_vector;
6790
  ivector_reset(v);
6791
  egraph_explain_term_eq(solver->egraph, t1, t2, v); // v contains p1 /\ ... /\ p_n
6792

6793
  n = v->size;
6794
  for (i=0; i<n; i++) {
6795
    v->data[i] = not(v->data[i]);
6796
  }
6797
  ivector_push(v, l);
6798
  add_clause(solver->core, v->size, v->data);
6799

6800
  solver->stats.half_equiv_lemmas ++;
6801
}
6802

6803
#endif
6804

6805
/*
6806
 * Create the lemma (eq t1 t2) <=> (bveq x1 x2) if it's not redundant
6807
 * where t1 = egraph term for x1 and t2 = egraph term for x2
6808
 */
6809
static void bv_solver_bvequiv_lemma(bv_solver_t *solver, thvar_t x1, thvar_t x2) {
438,608✔
6810
  bv_vartable_t *vtbl;
6811
  cache_t *cache;
6812
  cache_elem_t *e;
6813
  thvar_t aux;
6814
  eterm_t t1, t2;
6815
  literal_t l, eq;
6816

6817
  vtbl = &solver->vtbl;
438,608✔
6818

6819
  assert(solver->egraph != NULL && x1 != x2 &&
6820
         bvvar_is_bitblasted(vtbl, x1) && bvvar_is_bitblasted(vtbl, x2));
6821

6822
  if (bv_solver_bvequiv_redundant(solver, x1, x2)) {
438,608✔
6823
    return;
329,779✔
6824
  }
6825

6826
  // normalize: we want x1 < x2
6827
  if (x2 < x1) {
108,829✔
6828
    aux = x1, x1 = x2; x2 = aux;
43,851✔
6829
  }
6830

6831

6832
#if TRACE
6833
  t1 = bvvar_get_eterm(vtbl, x1);
6834
  t2 = bvvar_get_eterm(vtbl, x2);
6835
  printf("---> checking bvequiv lemma:\n");
6836
  printf("     x1 = ");
6837
  print_bv_solver_var(stdout, solver, x1);
6838
  printf(", t1 = ");
6839
  print_eterm_id(stdout, t1);
6840
  printf("\n");
6841
  printf("     x2 = ");
6842
  print_bv_solver_var(stdout, solver, x2);
6843
  printf(", t2 = ");
6844
  print_eterm_id(stdout, t2);
6845
  printf("\n");
6846
#endif
6847

6848
  cache = bv_solver_get_cache(solver);
108,829✔
6849
  e = cache_get(cache, BVEQUIV_LEMMA, x1, x2);
108,829✔
6850
  if (e->flag == NEW_CACHE_ELEM) {
108,829✔
6851
    // create the lemma
6852
    e->flag = ACTIVE_BV_LEMMA;
4,740✔
6853

6854
    t1 = bvvar_get_eterm(vtbl, x1);
4,740✔
6855
    t2 = bvvar_get_eterm(vtbl, x2);
4,740✔
6856
    assert(t1 != null_eterm && t2 != null_eterm && t1 != t2);
6857
    eq = egraph_make_simple_eq(solver->egraph, pos_occ(t1), pos_occ(t2));
4,740✔
6858
    l = on_the_fly_eq_atom(solver, x1, x2);
4,740✔
6859

6860
    // add two clauses: (l => eq) and (eq => l)
6861
    add_binary_clause(solver->core, not(l), eq);
4,740✔
6862
    add_binary_clause(solver->core, l, not(eq));
4,740✔
6863

6864
    // update statistics
6865
    solver->stats.equiv_lemmas ++;
4,740✔
6866

6867
#if 0
6868
    printf("---> BVSOLVER: bvequiv lemma for ");
6869
    print_bv_solver_var(stdout, solver, x1);
6870
    printf(" ");
6871
    print_bv_solver_var(stdout, solver, x2);
6872
    printf("\n");
6873
#endif
6874

6875
#if TRACE
6876
    printf("---> bvequiv lemma:\n");
6877
    printf("     x1 = ");
6878
    print_bv_solver_var(stdout, solver, x1);
6879
    printf(", t1 = ");
6880
    print_eterm_id(stdout, t1);
6881
    printf("\n");
6882
    printf("     x2 = ");
6883
    print_bv_solver_var(stdout, solver, x2);
6884
    printf(", t2 = ");
6885
    print_eterm_id(stdout, t2);
6886
    printf("\n");
6887
    printf("     (bveq x1 x2) = ");
6888
    print_literal(stdout, l);
6889
    printf("\n");
6890
    printf("     (eq t1 t2) = ");
6891
    print_literal(stdout, eq);
6892
    printf("\n");
6893
    printf("     ");
6894
    print_bv_solver_vardef(stdout, solver, x1);
6895
    printf("     ");
6896
    print_bv_solver_vardef(stdout, solver, x2);
6897
    printf("     ");
6898
    print_eterm_def(stdout, solver->egraph, t1);
6899
    printf("     ");
6900
    print_eterm_def(stdout, solver->egraph, t2);
6901
    printf("     ");
6902
    print_literal(stdout, eq);
6903
    printf(" := ");
6904
    print_egraph_atom_of_literal(stdout, solver->egraph, eq);
6905
    printf("\n\n");
6906
#endif
6907
  }
6908
}
6909

6910

6911
/*
6912
 * Build the explanation for (x1 == x2) from the Egraph
6913
 * - id = Egraph edge to get the explanation
6914
 * - store the explanation in vector v
6915
 */
6916
static void bv_solver_explain_egraph_eq(bv_solver_t *solver, thvar_t x1, thvar_t x2, int32_t id, ivector_t *v) {
2,767✔
6917
  eterm_t t1, t2;
6918

6919
  assert(v->size == 0);
6920
  t1 = bvvar_get_eterm(&solver->vtbl, x1);
2,767✔
6921
  t2 = bvvar_get_eterm(&solver->vtbl, x2);
2,767✔
6922
  assert(t1 >= 0 && t2 >= 0); // remove a warning
6923
  egraph_explain_term_eq(solver->egraph, t1, t2, id, v);
2,767✔
6924
}
2,767✔
6925

6926

6927
/*
6928
 * Convert an explanation (l1 and ... and ln ==> false)
6929
 * into the clause ((not l1) or  .... (not ln))
6930
 * then add the clause as a theory conflict in the core.
6931
 * - v contains the literals l1 ... ln
6932
 */
6933
static void bv_solver_add_conflict(bv_solver_t *solver, ivector_t *v) {
2,767✔
6934
  uint32_t i, n;
6935
  literal_t *a;
6936

6937
  n = v->size;
2,767✔
6938
  a = v->data;
2,767✔
6939
  for (i=0; i<n; i++) {
10,664✔
6940
    a[i] = not(a[i]);
7,897✔
6941
  }
6942

6943
  ivector_push(v, null_literal); // end marker
2,767✔
6944
  record_theory_conflict(solver->core, v->data);
2,767✔
6945
}
2,767✔
6946

6947

6948
/*
6949
 * Check whether x1 and x2 are distinct in the current assignment
6950
 * - x1 and x2 are two variables attached to egraph terms t1 and t2
6951
 * - the egraph has propagated the equality x1 == x2
6952
 * - id = index of the egraph edge that propagated (x1 == x2)
6953
 * - if (x1 != x2), generate a theory conflict and return true
6954
 * - return false if there's no conflict
6955
 */
6956
static bool bv_solver_bvequiv_conflict(bv_solver_t *solver, thvar_t x1, thvar_t x2, int32_t id) {
441,578✔
6957
  ivector_t *v;
6958
  bv_atomtable_t *atbl;
6959
  ivector_t *a, *b;
6960
  thvar_t y1, y2;
6961
  int32_t i;
6962
  literal_t l, l1, l2;
6963
  uint32_t j, n;
6964

6965
  v = &solver->aux_vector;
441,578✔
6966
  ivector_reset(v);
441,578✔
6967
  y1 = mtbl_get_root(&solver->mtbl, x1);
441,578✔
6968
  y2 = mtbl_get_root(&solver->mtbl, x2);
441,578✔
6969

6970
  if (equal_bvvar(solver, y1, y2)) {
441,578✔
6971
    goto no_conflict;
×
6972
  }
6973

6974
  if (diseq_bvvar(solver, y1, y2)) {
441,578✔
6975
    bv_solver_explain_egraph_eq(solver, x1, x2, id, v);
278✔
6976
    goto conflict;
278✔
6977
  }
6978

6979
  if (simplify_eq(solver, &y1, &y2)) {
441,300✔
6980
    if (equal_bvvar(solver, y1, y2)) {
103,265✔
6981
      goto no_conflict;
×
6982
    }
6983
    if (diseq_bvvar(solver, y1, y2)) {
103,265✔
6984
      bv_solver_explain_egraph_eq(solver, x1, x2, id, v);
1✔
6985
      goto conflict;
1✔
6986
    }
6987
  }
6988

6989
  atbl = &solver->atbl;
441,299✔
6990
  i = find_bveq_atom(atbl, y1, y2);
441,299✔
6991
  if (i >= 0) {
441,299✔
6992
    /*
6993
     * the atom l := (bveq y1 y2) exists, if l is false
6994
     * the conflict is (t1 == t2) and (not l)
6995
     */
6996
    l = atbl->data[i].lit;
434,194✔
6997
    if (literal_value(solver->core, l) == VAL_FALSE) {
434,194✔
6998
      bv_solver_explain_egraph_eq(solver, x1, x2, id, v);
41✔
6999
      ivector_push(v, not(l));
41✔
7000
      goto conflict;
41✔
7001
    }
7002
  }
7003

7004
  if (solver->bitblasted &&
882,516✔
7005
      bvvar_is_bitblasted(&solver->vtbl, y1) &&
882,516✔
7006
      bvvar_is_bitblasted(&solver->vtbl, y2)) {
441,258✔
7007

7008
    a = &solver->a_vector;
441,214✔
7009
    b = &solver->b_vector;
441,214✔
7010
    collect_bvvar_literals(solver, y1, a);
441,214✔
7011
    collect_bvvar_literals(solver, y2, b);
441,214✔
7012
    n = a->size;
441,214✔
7013
    assert(b->size == n);
7014

7015
    for (j=0; j<n; j++) {
9,747,318✔
7016
      l1 = a->data[j];
9,308,551✔
7017
      l2 = b->data[j];
9,308,551✔
7018
      if (literal_value(solver->core, l1) == VAL_FALSE && literal_value(solver->core, l2) == VAL_TRUE) {
9,308,551✔
7019
        bv_solver_explain_egraph_eq(solver, x1, x2, id, v);
1,232✔
7020
        ivector_push(v, not(l1));
1,232✔
7021
        ivector_push(v, l2);
1,232✔
7022
        goto conflict;
1,232✔
7023
      }
7024

7025
      if (literal_value(solver->core, l1) == VAL_TRUE && literal_value(solver->core, l2) == VAL_FALSE) {
9,307,319✔
7026
        bv_solver_explain_egraph_eq(solver, x1, x2, id, v);
1,215✔
7027
        ivector_push(v, l1);
1,215✔
7028
        ivector_push(v, not(l2));
1,215✔
7029
        goto conflict;
1,215✔
7030
      }
7031
    }
7032
  }
7033

7034
 no_conflict:
438,811✔
7035
  return false; // no conflict found
438,811✔
7036

7037
 conflict:
2,767✔
7038
  solver->stats.equiv_conflicts ++;
2,767✔
7039
  bv_solver_add_conflict(solver, v);
2,767✔
7040

7041
  return true;
2,767✔
7042
}
7043

7044

7045

7046
/*
7047
 * Process all assertions in the egraph queue
7048
 * - we do nothing for disequalities or distinct
7049
 * - disequalities are handled lazily in reconcile_model
7050
 * - for all equalities (x == y) in the queue, we create the
7051
 *   lemma (bveq x1 x2) <=> (t1 == t2)
7052
 * - return false if a conflict is detected (and record a theory conflict in the core)
7053
 */
7054
static bool bv_solver_process_egraph_assertions(bv_solver_t *solver) {
247,933✔
7055
  eassertion_t *a, *end;
7056
  bool consistent;
7057

7058
  consistent = true;
247,933✔
7059

7060
  a = eassertion_queue_start(&solver->egraph_queue);
247,933✔
7061
  end = eassertion_queue_end(&solver->egraph_queue);
247,933✔
7062

7063
  // first pass: check for conflicts
7064
  while (a < end) {
686,744✔
7065
    assert(eassertion_get_kind(a) == EGRAPH_VAR_EQ);
7066
    if (bv_solver_bvequiv_conflict(solver, a->var[0], a->var[1], a->id)) {
441,578✔
7067
      consistent = false;
2,767✔
7068
      goto done;
2,767✔
7069
    }
7070
    a = eassertion_next(a);
438,811✔
7071
  }
7072

7073
  // second pass: force equalities
7074
  a = eassertion_queue_start(&solver->egraph_queue);
245,166✔
7075
  while (a < end) {
683,774✔
7076
    bv_solver_bvequiv_lemma(solver, a->var[0], a->var[1]);
438,608✔
7077
    a = eassertion_next(a);
438,608✔
7078
  }
7079

7080
 done:
245,166✔
7081
  reset_eassertion_queue(&solver->egraph_queue);
247,933✔
7082
  return consistent;
247,933✔
7083
}
7084

7085

7086
/*
7087
 * Create a variable after bit-blasting (e.g., a skolem constant created
7088
 * by the egraph + array solver).
7089
 */
7090
thvar_t bv_solver_create_on_the_fly_var(bv_solver_t *solver, uint32_t n) {
6,169✔
7091
  bv_vartable_t *vtbl;
7092
  thvar_t x;
7093

7094
#if TRACE
7095
  printf("---> bv: create_var (%"PRIu32" bits)\n", n);
7096
#endif
7097

7098
  assert(n > 0);
7099
  vtbl = &solver->vtbl;
6,169✔
7100
  x = make_bvvar(vtbl, n);
6,169✔
7101
  if (solver->bitblasted) {
6,169✔
7102
    bv_solver_bitblast_variable(solver, x);
618✔
7103
  }
7104

7105
  return x;
6,169✔
7106
}
7107

7108

7109

7110

7111
/**********************
7112
 *  SOLVER INTERFACE  *
7113
 *********************/
7114

7115
/*
7116
 * New round of assertions (before start_search)
7117
 */
7118
void bv_solver_start_internalization(bv_solver_t *solver) {
166,369✔
7119
  solver->bitblasted = false;
166,369✔
7120
}
166,369✔
7121

7122

7123
/*
7124
 * Prepare for search after internalization
7125
 * - perform bit blasting
7126
 * - if a conflict is detected by bit blasting, add the empty clause
7127
 *   to the smt_core
7128
 */
7129
void bv_solver_start_search(bv_solver_t *solver) {
25,324✔
7130
  bool feasible;
7131

7132
  solver->stats.equiv_lemmas = 0;
25,324✔
7133
  solver->stats.equiv_conflicts = 0;
25,324✔
7134
  solver->stats.half_equiv_lemmas = 0;
25,324✔
7135
  solver->stats.interface_lemmas = 0;
25,324✔
7136

7137
  feasible = bv_solver_bitblast(solver);
25,324✔
7138
  if (! feasible) {
25,324✔
7139
    add_empty_clause(solver->core);
1✔
7140
    return;
1✔
7141
  }
7142

7143
  if (solver->egraph != NULL) {
25,323✔
7144
    propagate_strong_equalities(solver);
12,784✔
7145
  }
7146
}
7147

7148

7149
/*
7150
 * Perform one round of propagation
7151
 * - return false if a conflict was found
7152
 * - return true otherwise
7153
 */
7154
bool bv_solver_propagate(bv_solver_t *solver) {
6,376,586✔
7155
  if (eassertion_queue_is_nonempty(&solver->egraph_queue)) {
6,376,586✔
7156
    assert(solver->bitblasted);
7157
    return bv_solver_process_egraph_assertions(solver);
247,933✔
7158
  }
7159
  return true;
6,128,653✔
7160
}
7161

7162
/*
7163
 * Final check: nothing to do
7164
 */
7165
fcheck_code_t bv_solver_final_check(bv_solver_t *solver) {
24,263✔
7166
  return FCHECK_SAT;
24,263✔
7167
}
7168

7169
// clear: do nothing
7170
void bv_solver_clear(bv_solver_t *solver) {
21,252✔
7171
}
21,252✔
7172

7173
void bv_solver_increase_decision_level(bv_solver_t *solver) {
6,834,378✔
7174
  solver->decision_level ++;
6,834,378✔
7175

7176
#if DUMP
7177
  if (solver->core->stats.decisions == 1) {
7178
    bv_solver_dump_state(solver, "after-bitblasting.dmp");
7179
  }
7180
#endif
7181
}
6,834,378✔
7182

7183
void bv_solver_backtrack(bv_solver_t *solver, uint32_t backlevel) {
123,311✔
7184
  assert(solver->base_level <= backlevel && backlevel < solver->decision_level);
7185
  reset_eassertion_queue(&solver->egraph_queue);
123,311✔
7186
  solver->decision_level = backlevel;
123,311✔
7187
}
123,311✔
7188

7189

7190
/*
7191
 * Assert atom attached to literal l
7192
 * This function is called when l is assigned to true by the core
7193
 * - atom is the atom attached to a boolean variable v = var_of(l)
7194
 * - if l is positive (i.e., pos_lit(v)), assert the atom
7195
 * - if l is negative (i.e., neg_lit(v)), assert its negation
7196
 * Return false if that causes a conflict, true otherwise.
7197
 *
7198
 * Do nothing (although we could try more simplification if
7199
 * this is called before start_search).
7200
 */
7201
bool bv_solver_assert_atom(bv_solver_t *solver, void *a, literal_t l) {
1,251,686✔
7202
  return true;
1,251,686✔
7203
}
7204

7205

7206
/*
7207
 * This function should never be called.
7208
 */
7209
void bv_solver_expand_explanation(bv_solver_t *solver, literal_t l, void *expl, ivector_t *v) {
×
7210
  assert(false);
7211
}
×
7212

7213

7214
/*
7215
 * Support for theory-branching heuristic
7216
 * - we don't do anything
7217
 */
7218
literal_t bv_solver_select_polarity(bv_solver_t *solver, void *a, literal_t l) {
×
7219
  return l;
×
7220
}
7221

7222

7223

7224
/**********************
7225
 *  MAIN OPERATIONS   *
7226
 *********************/
7227

7228
/*
7229
 * Initialize a bit-vector solver
7230
 * - core = the attached smt core
7231
 * - egraph = the attached egraph (or NULL)
7232
 */
7233
void init_bv_solver(bv_solver_t *solver, smt_core_t *core, egraph_t *egraph) {
11,476✔
7234
  solver->core = core;
11,476✔
7235
  solver->egraph = egraph;
11,476✔
7236
  solver->base_level = 0;
11,476✔
7237
  solver->decision_level = 0;
11,476✔
7238
  solver->bitblasted = false;
11,476✔
7239
  solver->bbptr = 0;
11,476✔
7240

7241
  init_bv_vartable(&solver->vtbl);
11,476✔
7242
  init_bv_atomtable(&solver->atbl);
11,476✔
7243
  init_bvexp_table(&solver->etbl, &solver->vtbl);
11,476✔
7244
  init_mtbl(&solver->mtbl);
11,476✔
7245
  init_bv_bound_queue(&solver->bqueue);
11,476✔
7246

7247
  solver->compiler = NULL;
11,476✔
7248
  solver->blaster = NULL;
11,476✔
7249
  solver->remap = NULL;
11,476✔
7250

7251
  init_eassertion_queue(&solver->egraph_queue);
11,476✔
7252
  solver->cache = NULL;
11,476✔
7253

7254
  init_bv_stats(&solver->stats);
11,476✔
7255

7256
  init_bv_queue(&solver->select_queue);
11,476✔
7257
  init_bv_queue(&solver->delayed_mapped);
11,476✔
7258
  init_bv_queue(&solver->delayed_blasted);
11,476✔
7259
  init_bv_trail(&solver->trail_stack);
11,476✔
7260

7261
  init_bvpoly_buffer(&solver->buffer);
11,476✔
7262
  init_pp_buffer(&solver->prod_buffer, 10);
11,476✔
7263
  init_ivector(&solver->aux_vector, 0);
11,476✔
7264
  init_bvconstant(&solver->aux1);
11,476✔
7265
  init_bvconstant(&solver->aux2);
11,476✔
7266
  init_bvconstant(&solver->aux3);
11,476✔
7267
  bvexp_init_buffer(&solver->etbl, &solver->exp_buffer);
11,476✔
7268
  bvexp_init_buffer64(&solver->etbl, &solver->exp64_buffer);
11,476✔
7269
  init_bv_interval_stack(&solver->intv_stack);
11,476✔
7270
  init_ivector(&solver->a_vector, 0);
11,476✔
7271
  init_ivector(&solver->b_vector, 0);
11,476✔
7272

7273
  solver->val_map = NULL;
11,476✔
7274

7275
  solver->env = NULL;
11,476✔
7276
}
11,476✔
7277

7278

7279
/*
7280
 * Attach a jump buffer for exception handling
7281
 */
7282
void bv_solver_init_jmpbuf(bv_solver_t *solver, jmp_buf *buffer) {
11,476✔
7283
  solver->env = buffer;
11,476✔
7284
}
11,476✔
7285

7286

7287
/*
7288
 * Delete solver
7289
 */
7290
void delete_bv_solver(bv_solver_t *solver) {
11,476✔
7291
  // exp buffers must be deleted before etbl
7292
  // and etbl must be deleted before vtbl
7293
  delete_bvarith_buffer(&solver->exp_buffer);
11,476✔
7294
  delete_bvarith64_buffer(&solver->exp64_buffer);
11,476✔
7295

7296
  delete_bvexp_table(&solver->etbl);
11,476✔
7297
  delete_bv_vartable(&solver->vtbl);
11,476✔
7298
  delete_bv_atomtable(&solver->atbl);
11,476✔
7299
  delete_mtbl(&solver->mtbl);
11,476✔
7300
  delete_bv_bound_queue(&solver->bqueue);
11,476✔
7301

7302
  if (solver->compiler != NULL) {
11,476✔
7303
    delete_bv_compiler(solver->compiler);
10,757✔
7304
    safe_free(solver->compiler);
10,757✔
7305
    solver->compiler = NULL;
10,757✔
7306
  }
7307

7308
  if (solver->blaster != NULL) {
11,476✔
7309
    delete_bit_blaster(solver->blaster);
10,757✔
7310
    safe_free(solver->blaster);
10,757✔
7311
    solver->blaster = NULL;
10,757✔
7312
  }
7313

7314
  if (solver->remap != NULL) {
11,476✔
7315
    delete_remap_table(solver->remap);
10,787✔
7316
    safe_free(solver->remap);
10,787✔
7317
    solver->remap = NULL;
10,787✔
7318
  }
7319

7320
  delete_eassertion_queue(&solver->egraph_queue);
11,476✔
7321

7322
  if (solver->cache != NULL) {
11,476✔
7323
    delete_cache(solver->cache);
35✔
7324
    safe_free(solver->cache);
35✔
7325
    solver->cache = NULL;
35✔
7326
  }
7327

7328
  delete_bv_queue(&solver->select_queue);
11,476✔
7329
  delete_bv_queue(&solver->delayed_mapped);
11,476✔
7330
  delete_bv_queue(&solver->delayed_blasted);
11,476✔
7331
  delete_bv_trail(&solver->trail_stack);
11,476✔
7332

7333
  delete_bvpoly_buffer(&solver->buffer);
11,476✔
7334
  delete_pp_buffer(&solver->prod_buffer);
11,476✔
7335
  delete_ivector(&solver->aux_vector);
11,476✔
7336
  delete_bvconstant(&solver->aux1);
11,476✔
7337
  delete_bvconstant(&solver->aux2);
11,476✔
7338
  delete_bvconstant(&solver->aux3);
11,476✔
7339
  delete_bv_interval_stack(&solver->intv_stack);
11,476✔
7340
  delete_ivector(&solver->a_vector);
11,476✔
7341
  delete_ivector(&solver->b_vector);
11,476✔
7342

7343
  if (solver->val_map != NULL) {
11,476✔
7344
    delete_bvconst_hmap(solver->val_map);
×
7345
    safe_free(solver->val_map);
×
7346
    solver->val_map = NULL;
×
7347
  }
7348
}
11,476✔
7349

7350

7351

7352
/********************
7353
 *  PUSH/POP/RESET  *
7354
 *******************/
7355

7356
/*
7357
 * Start a new base level
7358
 */
7359
void bv_solver_push(bv_solver_t *solver) {
6,769✔
7360
  uint32_t na, nv, nb, ns, ndm, ndb, bb;
7361

7362
  assert(solver->decision_level == solver->base_level &&
7363
         all_bvvars_unmarked(solver));
7364

7365
  nv = solver->vtbl.nvars;
6,769✔
7366
  na = solver->atbl.natoms;
6,769✔
7367
  nb = solver->bqueue.top;
6,769✔
7368
  ns = solver->select_queue.top;
6,769✔
7369
  ndm = solver->delayed_mapped.top;
6,769✔
7370
  ndb = solver->delayed_blasted.top;
6,769✔
7371
  bb = solver->bbptr;
6,769✔
7372

7373
  bv_trail_save(&solver->trail_stack, nv, na, nb, ns, ndm, ndb, bb);
6,769✔
7374

7375
  mtbl_push(&solver->mtbl);
6,769✔
7376

7377
  if (solver->compiler != NULL) {
6,769✔
7378
    bv_compiler_push(solver->compiler);
36✔
7379
  }
7380

7381
  if (solver->remap != NULL) {
6,769✔
7382
    remap_table_push(solver->remap);
2,605✔
7383
  }
7384

7385
  if (solver->cache != NULL) {
6,769✔
7386
    cache_push(solver->cache);
1✔
7387
  }
7388

7389
  solver->base_level ++;
6,769✔
7390
  bv_solver_increase_decision_level(solver);
6,769✔
7391
}
6,769✔
7392

7393

7394
/*
7395
 * Remove all eterms whose id >= number of terms in the egraph
7396
 * - if a bitvector variable x is kept after pop but the
7397
 *   eterm[x] is removed from the egraph then we must clear
7398
 *   solver->vtbl.eterm[x]
7399
 */
7400
static void bv_solver_remove_dead_eterms(bv_solver_t *solver) {
37✔
7401
  uint32_t nterms;
7402

7403
  if (solver->egraph != NULL) {
37✔
7404
    nterms = egraph_num_terms(solver->egraph);
26✔
7405
    bv_vartable_remove_eterms(&solver->vtbl, nterms);
26✔
7406
  }
7407
}
37✔
7408

7409

7410
/*
7411
 * Remove the map of variables in the delayed_mapped queue
7412
 * - n = number of variables in the queue at the corresponding push
7413
 */
7414
static void bv_solver_clean_delayed_mapped_vars(bv_solver_t *solver, uint32_t n) {
37✔
7415
  bv_vartable_t *vtbl;
7416
  bv_queue_t *dqueue;
7417
  uint32_t i, top;
7418
  thvar_t x;
7419

7420
  vtbl = &solver->vtbl;
37✔
7421

7422
  dqueue = &solver->delayed_mapped;
37✔
7423
  top = dqueue->top;
37✔
7424
  assert(n <= top);
7425

7426
  for (i=n; i<top; i++) {
47✔
7427
    x = dqueue->data[i];
10✔
7428
    assert(bvvar_is_mapped(vtbl, x));
7429
    bvvar_reset_map(vtbl, x);
10✔
7430
  }
7431
}
37✔
7432

7433

7434
/*
7435
 * Remove the 'bitblasted' mark of variables in the delayed_blasted queue
7436
 * - n = number of variables in the queue at the corresponding push
7437
 */
7438
static void bv_solver_clean_delayed_blasted_vars(bv_solver_t *solver, uint32_t n) {
37✔
7439
  bv_vartable_t *vtbl;
7440
  bv_queue_t *dqueue;
7441
  uint32_t i, top;
7442
  thvar_t x;
7443

7444
  vtbl = &solver->vtbl;
37✔
7445

7446
  dqueue = &solver->delayed_blasted;
37✔
7447
  top = dqueue->top;
37✔
7448
  assert(n <= top);
7449

7450
  for (i=n; i<top; i++) {
49✔
7451
    x = dqueue->data[i];
12✔
7452
    assert(bvvar_is_bitblasted(vtbl, x));
7453
    bvvar_clr_bitblasted(vtbl, x);
12✔
7454
  }
7455
}
37✔
7456

7457

7458

7459
/*
7460
 * Remove the map of variables that will be removed from the select queue
7461
 * - n = number of variables that will remain in the select_queue
7462
 *
7463
 * This is called after bv_solver_clean_delayed_vars
7464
 */
7465
static void bv_solver_clean_select_queue(bv_solver_t *solver, uint32_t n) {
37✔
7466
  bv_vartable_t *vtbl;
7467
  bv_queue_t *squeue;
7468
  uint32_t i, top;
7469
  thvar_t x;
7470

7471
  vtbl = &solver->vtbl;
37✔
7472
  squeue = &solver->select_queue;
37✔
7473
  top = squeue->top;
37✔
7474

7475
  assert(n <= top);
7476
  for (i=n; i<top; i++) {
40✔
7477
    x = squeue->data[i];
3✔
7478
    if (bvvar_is_mapped(vtbl, x)) {
3✔
7479
      bvvar_reset_map(vtbl, x);
3✔
7480
    }
7481
  }
7482
}
37✔
7483

7484

7485

7486
/*
7487
 * Return to the previous base level
7488
 */
7489
void bv_solver_pop(bv_solver_t *solver) {
37✔
7490
  bv_trail_t *top;
7491

7492
  assert(solver->base_level > 0 &&
7493
         solver->base_level == solver->decision_level);
7494

7495
  solver->base_level --;
37✔
7496
  bv_solver_backtrack(solver, solver->base_level);
37✔
7497

7498
  if (solver->remap != NULL) {
37✔
7499
    remap_table_pop(solver->remap);
32✔
7500
  }
7501

7502
  top = bv_trail_top(&solver->trail_stack);
37✔
7503

7504
  if (solver->compiler != NULL) {
37✔
7505
    bv_compiler_pop(solver->compiler, top->nvars);
32✔
7506
  }
7507

7508
  if (solver->cache != NULL) {
37✔
7509
    cache_pop(solver->cache);
×
7510
  }
7511

7512
  assert(all_bvvars_unmarked(solver));
7513

7514
  /*
7515
   * Remove maps and bitblasted marks of delayed variables.
7516
   */
7517
  bv_solver_clean_delayed_mapped_vars(solver, top->ndelayed_mapped);
37✔
7518
  solver->delayed_mapped.top = top->ndelayed_mapped;
37✔
7519
  bv_solver_clean_delayed_blasted_vars(solver, top->ndelayed_blasted);
37✔
7520
  solver->delayed_blasted.top = top->ndelayed_blasted;
37✔
7521

7522
  /*
7523
   * remove vars in the select queue
7524
   */
7525
  bv_solver_clean_select_queue(solver, top->nselects);
37✔
7526
  solver->select_queue.top = top->nselects;
37✔
7527

7528
  // remove the expanded forms
7529
  // must be done before remove the variables form vtbl
7530
  bvexp_table_remove_vars(&solver->etbl, top->nvars);
37✔
7531

7532
  bv_solver_remove_bounds(solver, top->nbounds);
37✔
7533
  bv_vartable_remove_vars(&solver->vtbl, top->nvars);
37✔
7534
  bv_atomtable_remove_atoms(&solver->atbl, top->natoms);
37✔
7535
  bv_solver_remove_dead_eterms(solver);
37✔
7536

7537
  // restore the bitblast pointer
7538
  solver->bbptr = top->nbblasted;
37✔
7539

7540
  mtbl_pop(&solver->mtbl);
37✔
7541

7542
  bv_trail_pop(&solver->trail_stack);
37✔
7543
}
37✔
7544

7545

7546
/*
7547
 * Reset: remove all variables and atoms
7548
 * and reset base_level to 0.
7549
 */
7550
void bv_solver_reset(bv_solver_t *solver) {
1✔
7551
  /*
7552
   * The exp buffers must be deleted first since they use
7553
   * solver->etbl.store/store64, and reset_bvexp_table will reset
7554
   * these two stores. We reconstruct the two buffers after
7555
   * reset_bvexp_table.
7556
   */
7557
  delete_bvarith_buffer(&solver->exp_buffer);
1✔
7558
  delete_bvarith64_buffer(&solver->exp64_buffer);
1✔
7559
  reset_bvexp_table(&solver->etbl);
1✔
7560
  bvexp_init_buffer(&solver->etbl, &solver->exp_buffer);
1✔
7561
  bvexp_init_buffer64(&solver->etbl, &solver->exp64_buffer);
1✔
7562

7563
  reset_bv_vartable(&solver->vtbl);
1✔
7564
  reset_bv_atomtable(&solver->atbl);
1✔
7565
  reset_mtbl(&solver->mtbl);
1✔
7566
  reset_bv_bound_queue(&solver->bqueue);
1✔
7567

7568
  if (solver->compiler != NULL) {
1✔
7569
    delete_bv_compiler(solver->compiler);
1✔
7570
    safe_free(solver->compiler);
1✔
7571
    solver->compiler = NULL;
1✔
7572
  }
7573

7574
  if (solver->blaster != NULL) {
1✔
7575
    delete_bit_blaster(solver->blaster);
1✔
7576
    safe_free(solver->blaster);
1✔
7577
    solver->blaster = NULL;
1✔
7578
  }
7579

7580
  if (solver->remap != NULL) {
1✔
7581
    delete_remap_table(solver->remap);
1✔
7582
    safe_free(solver->remap);
1✔
7583
    solver->remap = NULL;
1✔
7584
  }
7585

7586
  reset_eassertion_queue(&solver->egraph_queue);
1✔
7587

7588
  if (solver->cache != NULL) {
1✔
7589
    delete_cache(solver->cache);
×
7590
    safe_free(solver->cache);
×
7591
    solver->cache = NULL;
×
7592
  }
7593

7594
  reset_bv_stats(&solver->stats);
1✔
7595
  reset_bv_queue(&solver->select_queue);
1✔
7596
  reset_bv_queue(&solver->delayed_mapped);
1✔
7597
  reset_bv_queue(&solver->delayed_blasted);
1✔
7598
  reset_bv_trail(&solver->trail_stack);
1✔
7599

7600
  reset_bvpoly_buffer(&solver->buffer, 32);
1✔
7601
  pp_buffer_reset(&solver->prod_buffer);
1✔
7602
  ivector_reset(&solver->aux_vector);
1✔
7603
  reset_bv_interval_stack(&solver->intv_stack);
1✔
7604
  ivector_reset(&solver->a_vector);
1✔
7605
  ivector_reset(&solver->b_vector);
1✔
7606

7607
  if (solver->val_map != NULL) {
1✔
7608
    delete_bvconst_hmap(solver->val_map);
×
7609
    safe_free(solver->val_map);
×
7610
    solver->val_map = NULL;
×
7611
  }
7612

7613
  solver->base_level = 0;
1✔
7614
  solver->decision_level = 0;
1✔
7615
  solver->bitblasted = false;
1✔
7616
  solver->bbptr = 0;
1✔
7617
}
1✔
7618

7619

7620

7621
/**********************
7622
 *  EGRAPH INTERFACE  *
7623
 *********************/
7624

7625
/*
7626
 * Assertion (eq x y) from the Egraph
7627
 * - process it immediately if we're at the base level
7628
 * - otherwise add it to the egraph assertion queue
7629
 */
7630
void bv_solver_assert_var_eq(bv_solver_t *solver, thvar_t x, thvar_t y, int32_t id) {
446,268✔
7631
  assert(bvvar_has_eterm(&solver->vtbl, x) && bvvar_has_eterm(&solver->vtbl, y));
7632

7633
#if TRACE
7634
  printf("---> bvsolver: received egraph equality: ");
7635
  print_bv_solver_var(stdout, solver, x);
7636
  printf(" = ");
7637
  print_bv_solver_var(stdout, solver, y);
7638
  printf("\n");
7639
#endif
7640

7641
  if (! solver->bitblasted) {
446,268✔
7642
    assert(solver->decision_level == solver->base_level);
7643
    bv_solver_assert_eq_axiom(solver, x, y, true);
2,422✔
7644
  } else {
7645
    eassertion_push_eq(&solver->egraph_queue, x, y, id);
443,846✔
7646
  }
7647
}
446,268✔
7648

7649
/*
7650
 * Assertion (x != y) from the Egraph
7651
 */
7652
void bv_solver_assert_var_diseq(bv_solver_t *solver, thvar_t x, thvar_t y, composite_t *hint) {
1,050,070✔
7653
  assert(bvvar_has_eterm(&solver->vtbl, x) && bvvar_has_eterm(&solver->vtbl, y));
7654

7655
#if TRACE
7656
  printf("---> bvsolver: received egraph disequality: ");
7657
  print_bv_solver_var(stdout, solver, x);
7658
  printf(" != ");
7659
  print_bv_solver_var(stdout, solver, y);
7660
  printf("\n");
7661
#endif
7662

7663
  if (! solver->bitblasted) {
1,050,070✔
7664
    assert(solver->decision_level == solver->base_level);
7665
    bv_solver_assert_eq_axiom(solver, x, y, false);
×
7666
  }
7667
}
1,050,070✔
7668

7669

7670
/*
7671
 * Assert that a[i] != a[j] for all pairs i, j
7672
 */
7673
void bv_solver_assert_var_distinct(bv_solver_t *solver, uint32_t n, thvar_t *a, composite_t *hint) {
×
7674
  uint32_t i, j;
7675
  thvar_t x, y;
7676

7677
  if (! solver->bitblasted) {
×
7678
    assert(solver->decision_level == solver->base_level);
7679

7680
    for (i=0; i<n; i++) {
×
7681
      x = a[i];
×
7682
      assert(bvvar_has_eterm(&solver->vtbl, x));
7683
      for (j=i+1; j<n; j++) {
×
7684
        y = a[j];
×
7685
        bv_solver_assert_eq_axiom(solver, x, y, false);
×
7686
      }
7687
    }
7688
  }
7689
}
×
7690

7691

7692
/*
7693
 * Check whether x and y are distinct at the base level
7694
 */
7695
bool bv_solver_check_disequality(bv_solver_t *solver, thvar_t x, thvar_t y) {
68,278✔
7696
  bv_vartable_t *vtbl;
7697
  ivector_t *a, *b;
7698
  literal_t l;
7699

7700
  vtbl = &solver->vtbl;
68,278✔
7701

7702
  if (solver->bitblasted && bvvar_is_bitblasted(vtbl, x) && bvvar_is_bitblasted(vtbl, y)) {
68,278✔
7703
    // both x and y are already bitblasted
7704
    a = &solver->a_vector;
64,982✔
7705
    b = &solver->b_vector;
64,982✔
7706
    collect_bvvar_literals(solver, x, a);
64,982✔
7707
    collect_bvvar_literals(solver, y, b);
64,982✔
7708
    assert(a->size == b->size && a->size > 0);
7709

7710
    l = bit_blaster_eval_bveq(solver->blaster, a->size, a->data, b->data);
64,982✔
7711

7712
    return (l == false_literal);
64,982✔
7713
  } else {
7714
    x = mtbl_get_root(&solver->mtbl, x);
3,296✔
7715
    y = mtbl_get_root(&solver->mtbl, y);
3,296✔
7716
    if (equal_bvvar(solver, x, y)) return false;
3,296✔
7717
    if (diseq_bvvar(solver, x, y)) return true;
920✔
7718
    if (bounds_imply_diseq(solver, x, y)) return true;
498✔
7719

7720
    if (simplify_eq(solver, &x, &y)) {
493✔
7721
      if (x == y) return false;
121✔
7722
      if (diseq_bvvar(solver, x, y)) return true;
121✔
7723
      if (bounds_imply_diseq(solver, x, y)) return true;
121✔
7724
    }
7725
  }
7726

7727
  return false;
492✔
7728
}
7729

7730
literal_t bv_solver_select_eq_polarity(bv_solver_t *solver, thvar_t x, thvar_t y, literal_t l) {
×
7731
  return l;
×
7732
}
7733

7734

7735
/*
7736
 * Check whether x is a constant
7737
 */
7738
bool bv_solver_var_is_constant(bv_solver_t *solver, thvar_t x) {
85,728✔
7739
  return is_constant(&solver->vtbl, x);
85,728✔
7740
}
7741

7742

7743
/*********************
7744
 *  RECONCILE MODEL  *
7745
 ********************/
7746

7747
/*
7748
 * Check whether x1 and x2 are equal in the model
7749
 * - return false if x1 and x2 have different bitsize
7750
 * - otherwise, check the literal values in the core
7751
 */
7752
static bool bv_solver_var_equal_in_model(bv_solver_t *solver, thvar_t x1, thvar_t x2) {
1,325,467✔
7753
  bv_vartable_t *vtbl;
7754
  remap_table_t *rmap;
7755
  smt_core_t *core;
7756
  literal_t *m1, *m2;
7757
  literal_t s1, s2;
7758
  literal_t l1, l2;
7759
  bval_t v1, v2;
7760
  uint32_t i, n;
7761

7762
  assert(solver->bitblasted);
7763

7764
  vtbl = &solver->vtbl;
1,325,467✔
7765

7766
  n = bvvar_bitsize(vtbl, x1);
1,325,467✔
7767
  if (n != bvvar_bitsize(vtbl, x2)) {
1,325,467✔
7768
    return false;
×
7769
  }
7770

7771
  m1 = bvvar_get_map(vtbl, x1);
1,325,467✔
7772
  m2 = bvvar_get_map(vtbl, x2);
1,325,467✔
7773

7774
  assert(m1 != NULL && m2 != NULL);
7775

7776
  rmap = solver->remap;
1,325,467✔
7777
  core = solver->core;
1,325,467✔
7778

7779
  for (i=0; i<n; i++) {
24,232,013✔
7780
    s1 = m1[i];
23,051,748✔
7781
    s2 = m2[i];
23,051,748✔
7782
    l1 = remap_table_find(rmap, s1);
23,051,748✔
7783
    l2 = remap_table_find(rmap, s2);
23,051,748✔
7784
    assert(l1 != null_literal && l2 != null_literal);
7785
    v1 = literal_value(core, l1);
23,051,748✔
7786
    v2 = literal_value(core, l2);
23,051,748✔
7787
    assert(bval_is_def(v1) && bval_is_def(v2));
7788
    if (v1 != v2) {
23,051,748✔
7789
      return false;
145,202✔
7790
    }
7791
  }
7792

7793
  return true;
1,180,265✔
7794
}
7795

7796

7797
/*
7798
 * 32bit word of x's value formed of bits[k ... k+31]
7799
 * - k must be smaller than x's bit size
7800
 * - if k+31 >= bitsize, then the value is padded with 0s
7801
 */
7802
static uint32_t bvsolver_word_value_in_model(bv_solver_t *solver, thvar_t x, uint32_t k) {
682,194✔
7803
  bv_vartable_t *vtbl;
7804
  remap_table_t *rmap;
7805
  smt_core_t *core;
7806
  literal_t *mx;
7807
  literal_t s, l;
7808
  uint32_t i, n, c;
7809

7810
  assert(solver->bitblasted);
7811

7812
  vtbl = &solver->vtbl;
682,194✔
7813
  rmap = solver->remap;
682,194✔
7814
  core = solver->core;
682,194✔
7815

7816
  n = bvvar_bitsize(vtbl, x);
682,194✔
7817
  mx = bvvar_get_map(vtbl, x);
682,194✔
7818
  assert(mx != NULL && k<n);
7819

7820
  c = 0;
682,194✔
7821

7822
  if (k + 32 <= n) {
682,194✔
7823
    n = k+32;
310,005✔
7824
  }
7825

7826
  for (i=k; i<n; i++) {
13,470,037✔
7827
    s = mx[i];
12,787,843✔
7828
    l = remap_table_find(rmap, s);
12,787,843✔
7829
    assert(l != null_literal && literal_is_assigned(core, l));
7830
    if (literal_value(core, l) == VAL_TRUE) {
12,787,843✔
7831
      c |= 1; // set low-order bit
785,716✔
7832
    }
7833
    c <<= 1;
12,787,843✔
7834
  }
7835

7836
  return c;
682,194✔
7837
}
7838

7839

7840

7841
/*
7842
 * Hash function: if x and y have the same value then hash(x) == hash(y).
7843
 * This is based on Jensen's lookup3 code (public domain).
7844
 */
7845
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
7846

7847
#define mix(a,b,c) \
7848
{ \
7849
  a -= c;  a ^= rot(c, 4);  c += b; \
7850
  b -= a;  b ^= rot(a, 6);  a += c; \
7851
  c -= b;  c ^= rot(b, 8);  b += a; \
7852
  a -= c;  a ^= rot(c,16);  c += b; \
7853
  b -= a;  b ^= rot(a,19);  a += c; \
7854
  c -= b;  c ^= rot(b, 4);  b += a; \
7855
}
7856

7857
#define final(a,b,c) \
7858
{ \
7859
  c ^= b; c -= rot(b,14); \
7860
  a ^= c; a -= rot(c,11); \
7861
  b ^= a; b -= rot(a,25); \
7862
  c ^= b; c -= rot(b,16); \
7863
  a ^= c; a -= rot(c,4);  \
7864
  b ^= a; b -= rot(a,14); \
7865
  c ^= b; c -= rot(b,24); \
7866
}
7867

7868
static uint32_t bvsolver_model_hash(bv_solver_t *solver, thvar_t x) {
678,784✔
7869
  uint32_t k, n;
7870
  uint32_t a, b, c;
7871

7872
  n = bvvar_bitsize(&solver->vtbl, x);
678,784✔
7873
  k = 0;
678,784✔
7874

7875
  a = b = c = 0xdeadbeef + (n << 2);
678,784✔
7876

7877
  while (n > 96) { // more than 3 words
679,738✔
7878
    a += bvsolver_word_value_in_model(solver, x, k);
954✔
7879
    b += bvsolver_word_value_in_model(solver, x, k+32);
954✔
7880
    c += bvsolver_word_value_in_model(solver, x, k+64);
954✔
7881
    mix(a, b, c);
954✔
7882
    n -= 96;
954✔
7883
    k += 96;
954✔
7884
  }
7885

7886
  // last three words
7887
  assert(1 <= n && n <= 96);
7888
  switch ((n+31) >> 5) {
678,784✔
7889
  case 3: c += bvsolver_word_value_in_model(solver, x, k+64);
140✔
7890
  case 2: b += bvsolver_word_value_in_model(solver, x, k+32);
408✔
7891
  case 1: a += bvsolver_word_value_in_model(solver, x, k);
678,784✔
7892
    final(a, b, c);
678,784✔
7893
    break;
678,784✔
7894
  default:
×
7895
    assert(false);
7896
    break;
×
7897
  }
7898

7899
  return c;
678,784✔
7900
}
7901

7902

7903

7904
/*
7905
 * Check whether x is a root variable:
7906
 * - x is root if it has an egraph term t and x is the theory
7907
 *   variable in the class of t.
7908
 */
7909
static bool is_root_var(bv_solver_t *solver, thvar_t x) {
3,975,566✔
7910
  egraph_t *egraph;
7911
  eterm_t t;
7912

7913
  t = bvvar_get_eterm(&solver->vtbl, x);
3,975,566✔
7914
  egraph = solver->egraph;
3,975,566✔
7915
  return (t != null_eterm) &&
7,064,439✔
7916
    (egraph_class_thvar(egraph, egraph_term_class(egraph, t)) == x);
3,088,873✔
7917
}
7918

7919

7920
#if 0
7921

7922
/*
7923
 * For testing: print the parent vectors of all variables in vector v
7924
 */
7925
static void show_parents_of_class(bv_solver_t *solver, int32_t *v) {
7926
  uint32_t i, n;
7927
  int32_t x;
7928
  eterm_t t;
7929

7930
  n = iv_size(v);
7931
  assert(n >= 2);
7932
  for (i=0; i<n; i++) {
7933
    x = v[i];
7934
    t = bvvar_get_eterm(&solver->vtbl, x);
7935
    printf("--- root bvvar = ");
7936
    print_bv_solver_var(stdout, solver, x);
7937
    printf("---\n");
7938
    print_class_of_term(stdout, solver->egraph, t);
7939
    print_parents_of_term(stdout, solver->egraph, t);
7940
  }
7941
}
7942

7943
#endif
7944

7945

7946
/*
7947
 * Heuristic: search for the best interface equality in a class
7948
 * - v = vector
7949
 */
7950
static bool interface_eq_in_class(bv_solver_t *solver, int32_t *v) {
×
7951
  thvar_t x1, x2;
7952
  eterm_t t1, t2;
7953
  literal_t l, eq;
7954

7955
  assert(iv_size(v) >= 2);
7956

7957
  x1 = v[0];
×
7958
  x2 = v[1];
×
7959
  t1 = bvvar_get_eterm(&solver->vtbl, x1);
×
7960
  t2 = bvvar_get_eterm(&solver->vtbl, x2);
×
7961
  assert(t1 != null_eterm && t2 != null_eterm && t1 != t2);
7962
  eq = egraph_make_simple_eq(solver->egraph, pos_occ(t1), pos_occ(t2));
×
7963
  l = on_the_fly_eq_atom(solver, x1, x2);
×
7964

7965
  // add two clauses: (l => eq) and (eq => l)
7966
  add_binary_clause(solver->core, not(l), eq);
×
7967
  add_binary_clause(solver->core, l, not(eq));
×
7968

7969
#if 0
7970
  printf("---> BVSOLVER: interface_eq lemma for ");
7971
  print_bv_solver_var(stdout, solver, x1);
7972
  printf(" ");
7973
  print_bv_solver_var(stdout, solver, x2);
7974
  printf("\n");
7975
#endif
7976

7977
  // update statistics
7978
  solver->stats.interface_lemmas ++;
×
7979

7980
  return true;
×
7981
}
7982

7983

7984
/*
7985
 * Search for inconsistencies between the egraph and the bitvector model
7986
 * - An inconsistency is a pair of bit-vector variables x and y
7987
 *   such that x and y have the same value in the solver but
7988
 *   term_of(x) and term_of(y) are in different classes in the egraph.
7989
 * - To resolve inconsistencies we add the lemma
7990
 *     (bveq x y) <=> (eq term_of(x) term_of(y))
7991
 * - max_eq = bound on the number of lemma instances
7992
 * - Return the number of instances created
7993
 */
7994
uint32_t bv_solver_reconcile_model(bv_solver_t *solver, uint32_t max_eq) {
×
7995
  ipart_t partition;
7996
  uint32_t i, n;
7997
  uint32_t neq;
7998

7999
  assert(max_eq > 0);
8000

8001
#if TRACE
8002
  printf("\n---> bv: reconcile model\n");
8003
  fflush(stdout);
8004
#endif
8005

8006

8007
  /*
8008
   * Build partitions:
8009
   * - two variables x and y are in the same class if both are root
8010
   *   variables and they have the same value in the bit assignment.
8011
   * - i.e., the egraph model says that x != y but the
8012
   *   bitvector model says that x = y
8013
   */
8014
  init_int_partition(&partition, 0, solver, (ipart_hash_fun_t) bvsolver_model_hash,
×
8015
                     (ipart_match_fun_t) bv_solver_var_equal_in_model);
8016

8017
  n = solver->vtbl.nvars;
×
8018
  for (i=1; i<n; i++) {
×
8019
    if (is_root_var(solver, i)) {
×
8020
      int_partition_add(&partition, i);
×
8021
    }
8022
  }
8023

8024
  n = int_partition_nclasses(&partition);
×
8025

8026
#if 0
8027
  for (i=0; i<n; i++) {
8028
    printf("Class %"PRIu32"\n", i);
8029
    show_parents_of_class(solver, partition.classes[i]);
8030
    printf("\n");
8031
  }
8032
#endif
8033

8034
  /*
8035
   * Process the classes: generate the 'best' conflict pairs
8036
   * in each class?
8037
   */
8038
  neq = 0;
×
8039
  for (i=0; i<n; i++) {
×
8040
    if (interface_eq_in_class(solver, partition.classes[i])) {
×
8041
      neq ++;
×
8042
      if (neq == max_eq) break;
×
8043
    }
8044
  }
8045

8046

8047
  delete_int_partition(&partition);
×
8048

8049
  return neq;
×
8050
}
8051

8052

8053

8054

8055
/*
8056
 * REVISED INTERFACE/RECONCILIATION INTERFACE
8057
 */
8058

8059
/*
8060
 * Prepare model and release model: nothing to do
8061
 * - equal_in_model is the same as bv_solver_var_equal_in_model (defined above)
8062
 */
8063
static void bv_solver_prepare_model(bv_solver_t *solver) {
15,446✔
8064
#if 0
8065
  // PROVISIONAL
8066
  free_bool_vars_t fv;
8067
  uint32_t i, n, frees;
8068

8069
  n = solver->core->nvars;
8070
  init_free_bool_vars(&fv, n);
8071
  collect_free_bool_vars(&fv, solver->core);
8072

8073
  frees = 0;
8074
  for (i=0; i<n; i++) {
8075
    frees += fv.free[i];
8076
  }
8077

8078
  printf("Free/total boolean vars: %"PRIu32"/%"PRIu32"\n", frees, n);
8079

8080
  delete_free_bool_vars(&fv);
8081
#endif
8082
}
15,446✔
8083

8084
static void bv_solver_release_model(bv_solver_t *solver) {
15,446✔
8085
}
15,446✔
8086

8087

8088
/*
8089
 * Add the lemma l => x1 != x2
8090
 * - i.e., the clause (not l) or (not (bveq x1 x2))
8091
 * - if equiv is true: can add the reverse implication too?
8092
 */
8093
static void bv_solver_gen_interface_lemma(bv_solver_t *solver, literal_t l, thvar_t x1, thvar_t x2, bool equiv) {
2,201✔
8094
  literal_t eq;
8095

8096
  assert(solver->egraph != NULL && x1 != x2 &&
8097
         bvvar_is_bitblasted(&solver->vtbl, x1) &&
8098
         bvvar_is_bitblasted(&solver->vtbl, x2));
8099

8100
#if 0
8101
  printf("---> BVSOLVER: interface lemma for u!%"PRId32" and u!%"PRId32"\n", x1, x2);
8102
  print_bv_solver_var_litarray(stdout, solver, x1);
8103
  print_bv_solver_var_litarray(stdout, solver, x2);
8104
  printf("\n");
8105
#endif
8106

8107
  eq = on_the_fly_eq_atom(solver, x1, x2);
2,201✔
8108
  add_binary_clause(solver->core, not(l), not(eq));  // l => not eq
2,201✔
8109
  if (equiv) {
2,201✔
8110
    add_binary_clause(solver->core, l, eq);   // not l => eq
2,201✔
8111
  }
8112

8113
  solver->stats.interface_lemmas ++;
2,201✔
8114

8115
#if TRACE
8116
  printf("---> Bv solver: reconciliation lemma for u!%"PRId32" /= u!%"PRId32" ----\n", x1, x2);
8117
  printf("     Antecedent:\n");
8118
  printf("     ");
8119
  print_literal(stdout, l);
8120
  printf(" := ");
8121
  print_egraph_atom_of_literal(stdout, solver->egraph, l);
8122
  printf("\n");
8123
  printf("     (bveq u!%"PRId32" u!%"PRId32") = ", x1, x2);
8124
  print_literal(stdout, eq);
8125
  printf("\n");
8126
  printf("     Clause: (OR ");
8127
  print_literal(stdout, not(l));
8128
  printf(" ");
8129
  print_literal(stdout, not(eq));
8130
  printf(")\n\n");
8131
#endif
8132
}
2,201✔
8133

8134

8135
/*
8136
 * Build the model partition and return it
8137
 */
8138
static ipart_t *bv_solver_build_model_partition(bv_solver_t *solver) {
15,446✔
8139
  ipart_t *partition;
8140
  uint32_t i, n;
8141

8142
  partition = (ipart_t *) safe_malloc(sizeof(ipart_t));
15,446✔
8143
  init_int_partition(partition, 0, solver, (ipart_hash_fun_t) bvsolver_model_hash,
15,446✔
8144
                     (ipart_match_fun_t) bv_solver_var_equal_in_model);
8145

8146
  n = solver->vtbl.nvars;
15,446✔
8147
  for (i=1; i<n; i++) {
3,991,012✔
8148
    if (is_root_var(solver, i)) {
3,975,566✔
8149
      int_partition_add(partition, i);
678,784✔
8150
    }
8151
  }
8152

8153
  return partition;
15,446✔
8154
}
8155

8156

8157
/*
8158
 * Delete the partition
8159
 */
8160
static void bv_solver_release_model_partition(bv_solver_t *solver, ipart_t *p) {
15,446✔
8161
  delete_int_partition(p);
15,446✔
8162
  safe_free(p);
15,446✔
8163
}
15,446✔
8164

8165

8166

8167
/************************
8168
 *  MODEL CONSTRUCTION  *
8169
 ***********************/
8170

8171
/*
8172
 * Interface function: nothing to do
8173
 */
8174
void bv_solver_build_model(bv_solver_t *solver) {
21,399✔
8175
  // do nothing
8176
}
21,399✔
8177

8178

8179
/*
8180
 * Get the internal val_map
8181
 * - allocate and initialize it if needed
8182
 */
8183
static bvconst_hmap_t *bv_solver_get_val_map(bv_solver_t *solver) {
13✔
8184
  bvconst_hmap_t *tmp;
8185

8186
  tmp = solver->val_map;
13✔
8187
  if (tmp == NULL) {
13✔
8188
    tmp = (bvconst_hmap_t *) safe_malloc(sizeof(bvconst_hmap_t));
6✔
8189
    init_bvconst_hmap(tmp, 0); // default size?
6✔
8190
    solver->val_map = tmp;
6✔
8191
  }
8192

8193
  return tmp;
13✔
8194
}
8195

8196

8197
/*
8198
 * Copy the value of x in c:
8199
 * - x must be marked as bitblasted
8200
 * - the value is read from the SAT solver assignment
8201
 * - return true if the value is available/false otherwise
8202
 */
8203
static bool get_bitblasted_var_value(bv_solver_t *solver, thvar_t x, uint32_t *c) {
19,210✔
8204
  bv_vartable_t *vtbl;
8205
  remap_table_t *rmap;
8206
  literal_t *mx;
8207
  uint32_t i, n;
8208
  literal_t s, l;
8209

8210
  vtbl = &solver->vtbl;
19,210✔
8211
  rmap = solver->remap;
19,210✔
8212

8213
  n = bvvar_bitsize(vtbl, x);
19,210✔
8214

8215
  assert(bvvar_is_bitblasted(vtbl, x));
8216

8217
  mx = bvvar_get_map(vtbl, x);
19,210✔
8218
  assert(mx != NULL && rmap != NULL);
8219

8220
  for (i=0; i<n; i++) {
261,423✔
8221
    s = mx[i];
242,213✔
8222
    l = remap_table_find(rmap, s);
242,213✔
8223
    if (l == null_literal) return false;
242,213✔
8224

8225
    switch (literal_value(solver->core, l)) {
242,213✔
8226
    case VAL_FALSE:
133,674✔
8227
      bvconst_clr_bit(c, i);
133,674✔
8228
      break;
133,674✔
8229

8230
    case VAL_TRUE:
108,539✔
8231
      bvconst_set_bit(c, i);
108,539✔
8232
      break;
108,539✔
8233

8234
    case VAL_UNDEF_FALSE:
×
8235
    case VAL_UNDEF_TRUE:
8236
      return false;
×
8237
    }
8238
  }
8239

8240
  bvconst_normalize(c, n);
19,210✔
8241

8242
  return true;
19,210✔
8243
}
8244

8245

8246
/*
8247
 * Copy the value of bit-array a[0 ... n-1] into c
8248
 * - return true if all literals have a value in the sat solver
8249
 * - return false otherwise
8250
 */
8251
static bool get_bvarray_value(bv_solver_t *solver, literal_t *a, uint32_t n, uint32_t *c) {
1✔
8252
  uint32_t i;
8253

8254
  for (i=0; i<n; i++) {
2✔
8255
    switch (literal_value(solver->core, a[i])) {
1✔
8256
    case VAL_FALSE:
1✔
8257
      bvconst_clr_bit(c, i);
1✔
8258
      break;
1✔
8259

8260
    case VAL_TRUE:
×
8261
      bvconst_set_bit(c, i);
×
8262
      break;
×
8263

8264
    case VAL_UNDEF_FALSE:
×
8265
    case VAL_UNDEF_TRUE:
8266
      return false;
×
8267
    }
8268
  }
8269

8270
  bvconst_normalize(c, n);
1✔
8271

8272
  return true;
1✔
8273
}
8274

8275

8276

8277
/*
8278
 * Copy a 64bit constant into word array c
8279
 * - c is large enough for n bits
8280
 */
8281
static void copy_constant64(uint32_t *c, uint64_t a, uint32_t n) {
11✔
8282
  assert(1 <= n && n <= 64 && a == norm64(a, n));
8283

8284
  c[0] = (uint32_t) (a & 0xFFFFFFFF);
11✔
8285
  if (n > 32) {
11✔
8286
    c[1] = (uint32_t) (a >> 32);
6✔
8287
  }
8288
}
11✔
8289

8290

8291
/*
8292
 * Same thing for a constant of more than 32 bits
8293
 */
8294
static void copy_constant(uint32_t *c, uint32_t *a, uint32_t n) {
×
8295
  uint32_t k;
8296

8297
  assert(n > 64 && bvconst_is_normalized(a, n));
8298

8299
  k = (n + 31) >> 5;
×
8300
  bvconst_set(c, k, a);
×
8301
  assert(bvconst_is_normalized(c, n));
8302
}
×
8303

8304

8305
/*
8306
 * Convert word array c to a 64bit constant
8307
 * - n = number of bits in c
8308
 */
8309
static uint64_t convert_to64(uint32_t *c, uint32_t n) {
24✔
8310
  uint64_t a;
8311

8312
  assert(1 <= n && n <= 64);
8313

8314
  a = c[0];
24✔
8315
  if (n > 32) {
24✔
8316
    a |= ((uint64_t) c[1]) << 32;
19✔
8317
  }
8318

8319
  assert(a == norm64(a, n));
8320

8321
  return a;
24✔
8322
}
8323

8324

8325

8326
/*
8327
 * Get the value of x in the current Boolean assignment
8328
 * - if x is bitblasted, get it from the pseudo-map of x
8329
 * - otherwise, compute it from x's definition
8330
 *   then store the value in the internal val_map
8331
 * - make a copy in vector c:
8332
 *   c must be an array of k 32bit words where k = ceil(nbits of x/32)
8333
 *
8334
 * - return true if the value can be computed, false otherwise
8335
 */
8336
static bool bv_solver_get_variable_value(bv_solver_t *solver, thvar_t x, uint32_t *c);
8337

8338

8339
/*
8340
 * Get the value of x, store the opposite  in c
8341
 * - n = number of bits
8342
 * - return true if found, false otherwise
8343
 */
8344
static bool bv_solver_neg_value(bv_solver_t *solver, thvar_t x, uint32_t n, uint32_t *c) {
×
8345
  uint32_t aux[4];
8346
  uint32_t *a;
8347
  uint32_t k;
8348
  bool found;
8349

8350
  k = (n + 31) >> 5;
×
8351
  a = aux;
×
8352
  if (k > 4) {
×
8353
    a = (uint32_t *) safe_malloc(k * sizeof(uint32_t));
×
8354
  }
8355

8356
  found = bv_solver_get_variable_value(solver, x, c);
×
8357
  if (found) {
×
8358
    bvconst_negate2(c, k, a);
×
8359
    bvconst_normalize(c, n);
×
8360
  }
8361

8362
  if (k > 4) {
×
8363
    safe_free(a);
×
8364
  }
8365

8366
  return found;
×
8367
}
8368

8369

8370
/*
8371
 * Get the values of x[0] and x[1] the apply op to this pair of values
8372
 * - store the result in c
8373
 * - n = number of bits in x[0] and x[1]
8374
 */
8375
static bool bv_solver_binop_value(bv_solver_t *solver, bvvar_tag_t op, thvar_t x[2], uint32_t n, uint32_t *c) {
×
8376
  uint32_t aux1[4];
8377
  uint32_t aux2[4];
8378
  uint32_t *a1, *a2;
8379
  uint32_t k;
8380
  bool found;
8381

8382

8383
  k = (n + 31) >> 5;
×
8384
  a1 = aux1;
×
8385
  a2 = aux2;
×
8386
  if (k >4) {
×
8387
    a1 = (uint32_t *) safe_malloc(k * sizeof(uint32_t));
×
8388
    a2 = (uint32_t *) safe_malloc(k * sizeof(uint32_t));
×
8389
  }
8390

8391
  found = bv_solver_get_variable_value(solver, x[0], a1)
×
8392
    && bv_solver_get_variable_value(solver, x[1], a2);
×
8393

8394
  if (found) {
×
8395
    switch (op) {
×
8396
    case BVTAG_UDIV:
×
8397
      bvconst_udiv2z(c, n, a1, a2);
×
8398
      break;
×
8399

8400
    case BVTAG_UREM:
×
8401
      bvconst_urem2z(c, n, a1, a2);
×
8402
      break;
×
8403

8404
    case BVTAG_SDIV:
×
8405
      bvconst_sdiv2z(c, n, a1, a2);
×
8406
      break;
×
8407

8408
    case BVTAG_SREM:
×
8409
      bvconst_srem2z(c, n, a1, a2);
×
8410
      break;
×
8411

8412
    case BVTAG_SMOD:
×
8413
      bvconst_smod2z(c, n, a1, a2);
×
8414
      break;
×
8415

8416
    case BVTAG_SHL:
×
8417
      bvconst_lshl(c, a1, a2, n);
×
8418
      break;
×
8419

8420
    case BVTAG_LSHR:
×
8421
      bvconst_lshr(c, a1, a2, n);
×
8422
      break;
×
8423

8424
    case BVTAG_ASHR:
×
8425
      bvconst_ashr(c, a1, a2, n);
×
8426
      break;
×
8427

8428
    case BVTAG_ADD:
×
8429
      bvconst_add2(c, k, a1, a2);
×
8430
      break;
×
8431

8432
    case BVTAG_SUB:
×
8433
      bvconst_sub2(c, k, a1, a2);
×
8434
      break;
×
8435

8436
    case BVTAG_MUL:
×
8437
      bvconst_mul2(c, k, a1, a2);
×
8438
      break;
×
8439

8440
    default:
×
8441
      assert(false);
8442
      break;
×
8443
    }
8444

8445
    bvconst_normalize(c, n);
×
8446
  }
8447

8448

8449
  if (k > 4) {
×
8450
    safe_free(a1);
×
8451
    safe_free(a2);
×
8452
  }
8453

8454
  return found;
×
8455
}
8456

8457

8458

8459
/*
8460
 * Evaluate polynomial p
8461
 * - store the result in c
8462
 * - n = number of bits
8463
 */
8464
static bool bv_solver_poly64_value(bv_solver_t *solver, bvpoly64_t *p, uint32_t n, uint32_t *c) {
7✔
8465
  uint32_t aux[2];
8466
  uint64_t a, b;
8467
  uint32_t i, nterms;
8468
  bool found;
8469

8470
  assert(1 <= n && n <= 64 && n == p->bitsize && p->nterms > 0);
8471

8472
  nterms = p->nterms;
7✔
8473

8474
  i = 0;
7✔
8475
  a = 0;
7✔
8476
  if (p->mono[0].var == 0) {
7✔
8477
    a = p->mono[0].coeff;
1✔
8478
    i = 1;
1✔
8479
  }
8480

8481
  aux[0] = 0;
7✔
8482
  aux[1] = 0;
7✔
8483

8484
  found = true;
7✔
8485

8486
  while (i < nterms) {
20✔
8487
    found = bv_solver_get_variable_value(solver, p->mono[i].var, aux);
13✔
8488
    if (!found) goto done;
13✔
8489
    assert(bvconst_is_normalized(aux, n));
8490
    b = convert_to64(aux, n);
13✔
8491
    a += p->mono[i].coeff * b;
13✔
8492
    i ++;
13✔
8493
  }
8494

8495
  assert(found);
8496

8497
  a = norm64(a, n);
7✔
8498
  copy_constant64(c, a, n);
7✔
8499

8500
  assert(bvconst_is_normalized(c, n));
8501

8502
 done:
7✔
8503
  return found;
7✔
8504
}
8505

8506

8507
static bool bv_solver_poly_value(bv_solver_t *solver, bvpoly_t *p, uint32_t n, uint32_t *c) {
×
8508
  uint32_t aux[4];
8509
  uint32_t *a;
8510
  uint32_t k, i, nterms;
8511
  bool found;
8512

8513
  assert(64 < n && n == p->bitsize && p->nterms > 0);
8514

8515
  nterms = p->nterms;
×
8516

8517
  k = (n + 31) >> 5;
×
8518
  a = aux;
×
8519
  if (k > 4) {
×
8520
    a = (uint32_t *) safe_malloc(k * sizeof(uint32_t));
×
8521
  }
8522

8523
  i = 0;
×
8524
  bvconst_clear(c, k);
×
8525
  if (p->mono[0].var == const_idx) {
×
8526
    bvconst_set(c, k, p->mono[0].coeff);
×
8527
    i = 1;
×
8528
  }
8529

8530
  found = true;
×
8531

8532
  while (i < nterms) {
×
8533
    found = bv_solver_get_variable_value(solver, p->mono[i].var, a);
×
8534
    if (!found) goto done;
×
8535
    assert(bvconst_is_normalized(a, n));
8536
    bvconst_addmul(c, k, a, p->mono[i].coeff);
×
8537
    i ++;
×
8538
  }
8539

8540
  assert(found);
8541
  bvconst_normalize(c, n);
×
8542

8543
 done:
×
8544
  if (k > 4) {
×
8545
    safe_free(a);
×
8546
  }
8547

8548
  return found;
×
8549
}
8550

8551

8552

8553
/*
8554
 * Evaluate power-product p
8555
 */
8556
static bool bv_solver_pprod_value(bv_solver_t *solver, pprod_t *p, uint32_t n, uint32_t *c) {
1✔
8557
  uint32_t aux[4];
8558
  uint32_t *a;
8559
  uint32_t k, i, nterms;
8560
  bool found;
8561

8562
  nterms = p->len;
1✔
8563

8564
  k = (n + 31) >> 5;
1✔
8565
  a = aux;
1✔
8566
  if (k > 4) {
1✔
8567
    a = (uint32_t *) safe_malloc(k * sizeof(uint32_t));
×
8568
  }
8569

8570
  found = true;
1✔
8571
  bvconst_set_one(c, k);
1✔
8572
  for (i=0; i<nterms; i++) {
3✔
8573
    found = bv_solver_get_variable_value(solver, p->prod[i].var, a);
2✔
8574
    if (!found) goto done;
2✔
8575
    assert(bvconst_is_normalized(a, n));
8576
    bvconst_mulpower(c, k, a, p->prod[i].exp);
2✔
8577
  }
8578

8579
  assert(found);
8580
  bvconst_normalize(c, n);
1✔
8581

8582
 done:
1✔
8583
  if (k > 4) {
1✔
8584
    safe_free(a);
×
8585
  }
8586

8587
  return found;
1✔
8588
}
8589

8590

8591

8592

8593
/*
8594
 * Compute the value of x based on its definition
8595
 * - check the val_map first: if x's value is in the map return it
8596
 * - otherwise, compute if then add it to the val_map
8597
 *
8598
 * - return true if the value can be computed/false otherwise
8599
 */
8600
static bool bv_solver_compute_var_value(bv_solver_t *solver, thvar_t x, uint32_t *c) {
13✔
8601
  bv_vartable_t *vtbl;
8602
  bvconst_hmap_t *val_map;
8603
  bvconst_hmap_rec_t *r;
8604
  uint32_t n;
8605
  bvvar_tag_t op;
8606
  bool found;
8607

8608
  vtbl = &solver->vtbl;
13✔
8609
  val_map = bv_solver_get_val_map(solver);
13✔
8610

8611
  n = bvvar_bitsize(vtbl, x);
13✔
8612
  r = bvconst_hmap_find(val_map, x);
13✔
8613

8614
  if (r != NULL) {
13✔
8615
    // found value in val_map
8616
    assert(r->key == x && r->nbits == n && n>0);
8617
    if (n <= 64) {
2✔
8618
      copy_constant64(c, r->val.c, n);
2✔
8619
    } else {
8620
      copy_constant(c, r->val.p, n);
×
8621
    }
8622
    return true;
2✔
8623
  }
8624

8625

8626
  /*
8627
   * Compute the value
8628
   */
8629
  found = false; // stop GCC warning
11✔
8630

8631
  op = bvvar_tag(vtbl, x);
11✔
8632
  switch (op) {
11✔
8633
  case BVTAG_VAR:
×
8634
    // assign 0b000... as default value
8635
    bvconst_clear(c, (n + 31) >> 5);
×
8636
    found = true;
×
8637
    break;
×
8638

8639
  case BVTAG_CONST64:
2✔
8640
    copy_constant64(c, bvvar_val64(vtbl, x), n);
2✔
8641
    found = true;
2✔
8642
    break;
2✔
8643

8644
  case BVTAG_CONST:
×
8645
    copy_constant(c, bvvar_val(vtbl, x), n);
×
8646
    found = true;
×
8647
    break;
×
8648

8649
  case BVTAG_BIT_ARRAY:
1✔
8650
    found = get_bvarray_value(solver, bvvar_bvarray_def(vtbl, x), n, c);
1✔
8651
    break;
1✔
8652

8653
  case BVTAG_POLY64:
7✔
8654
    found = bv_solver_poly64_value(solver, bvvar_poly64_def(vtbl, x), n, c);
7✔
8655
    break;
7✔
8656

8657
  case BVTAG_POLY:
×
8658
    found = bv_solver_poly_value(solver, bvvar_poly_def(vtbl, x), n, c);
×
8659
    break;
×
8660

8661
  case BVTAG_PPROD:
1✔
8662
    found = bv_solver_pprod_value(solver, bvvar_pprod_def(vtbl, x), n, c);
1✔
8663
    break;
1✔
8664

8665
  case BVTAG_ITE:
×
8666
    found = false;
×
8667
    break;
×
8668

8669
  case BVTAG_UDIV:
×
8670
  case BVTAG_UREM:
8671
  case BVTAG_SDIV:
8672
  case BVTAG_SREM:
8673
  case BVTAG_SMOD:
8674
  case BVTAG_SHL:
8675
  case BVTAG_LSHR:
8676
  case BVTAG_ASHR:
8677
  case BVTAG_ADD:
8678
  case BVTAG_SUB:
8679
  case BVTAG_MUL:
8680
    found = bv_solver_binop_value(solver, op, bvvar_binop(vtbl, x), n, c);
×
8681
    break;
×
8682

8683
  case BVTAG_NEG:
×
8684
    found = bv_solver_neg_value(solver, bvvar_binop(vtbl, x)[0], n, c);
×
8685
    break;
×
8686
  }
8687

8688
  if (found) {
11✔
8689
    // store the value in val_map
8690
    if (n <= 64) {
11✔
8691
      bvconst_hmap_set_val64(val_map, x, convert_to64(c, n), n);
11✔
8692
    } else {
8693
      bvconst_hmap_set_val(val_map, x, c, n);
×
8694
    }
8695
  }
8696

8697
  return found;
11✔
8698
}
8699

8700

8701
static bool bv_solver_get_variable_value(bv_solver_t *solver, thvar_t x, uint32_t *c) {
19,223✔
8702
  if (bvvar_is_bitblasted(&solver->vtbl, x)) {
19,223✔
8703
    return get_bitblasted_var_value(solver, x, c);
19,210✔
8704
  } else {
8705
    return bv_solver_compute_var_value(solver, x, c);
13✔
8706
  }
8707
}
8708

8709

8710

8711
/*
8712
 * Copy the value assigned to x in the model into buffer c
8713
 * - return true if the value is available
8714
 * - return false if the solver has no model
8715
 */
8716
bool bv_solver_value_in_model(bv_solver_t *solver, thvar_t x, bvconstant_t *c) {
19,208✔
8717
  uint32_t n;
8718
  bool found;
8719

8720
  n = bvvar_bitsize(&solver->vtbl, x);
19,208✔
8721
  assert(n > 0);
8722

8723
  bvconstant_set_bitsize(c, n);
19,208✔
8724
  found = bv_solver_get_variable_value(solver, x, c->data);
19,208✔
8725
  assert(!found || bvconst_is_normalized(c->data, n));
8726

8727
  return found;
19,208✔
8728
}
8729

8730

8731

8732
/*
8733
 * Delete whatever is used to store the model
8734
 */
8735
void bv_solver_free_model(bv_solver_t *solver) {
21,399✔
8736
  if (solver->val_map != NULL) {
21,399✔
8737
    delete_bvconst_hmap(solver->val_map);
6✔
8738
    safe_free(solver->val_map);
6✔
8739
    solver->val_map = NULL;
6✔
8740
  }
8741
}
21,399✔
8742

8743

8744

8745

8746

8747

8748
/*******************************
8749
 *  INTERNALIZATION INTERFACE  *
8750
 ******************************/
8751

8752
static bv_interface_t bv_solver_context = {
8753
  (create_bv_var_fun_t) bv_solver_create_var,
8754
  (create_bv_const_fun_t) bv_solver_create_const,
8755
  (create_bv64_const_fun_t) bv_solver_create_const64,
8756
  (create_bv_zero_fun_t) bv_solver_create_zero,
8757
  (create_bv_poly_fun_t) bv_solver_create_bvpoly,
8758
  (create_bv64_poly_fun_t) bv_solver_create_bvpoly64,
8759
  (create_bv_pprod_fun_t) bv_solver_create_pprod,
8760
  (create_bv_array_fun_t) bv_solver_create_bvarray,
8761
  (create_bv_ite_fun_t) bv_solver_create_ite,
8762
  (create_bv_binop_fun_t) bv_solver_create_bvdiv,
8763
  (create_bv_binop_fun_t) bv_solver_create_bvrem,
8764
  (create_bv_binop_fun_t) bv_solver_create_bvsdiv,
8765
  (create_bv_binop_fun_t) bv_solver_create_bvsrem,
8766
  (create_bv_binop_fun_t) bv_solver_create_bvsmod,
8767
  (create_bv_binop_fun_t) bv_solver_create_bvshl,
8768
  (create_bv_binop_fun_t) bv_solver_create_bvlshr,
8769
  (create_bv_binop_fun_t) bv_solver_create_bvashr,
8770

8771
  (select_bit_fun_t) bv_solver_select_bit,
8772
  (create_bv_atom_fun_t) bv_solver_create_eq_atom,
8773
  (create_bv_atom_fun_t) bv_solver_create_ge_atom,
8774
  (create_bv_atom_fun_t) bv_solver_create_sge_atom,
8775

8776
  (assert_bv_axiom_fun_t) bv_solver_assert_eq_axiom,
8777
  (assert_bv_axiom_fun_t) bv_solver_assert_ge_axiom,
8778
  (assert_bv_axiom_fun_t) bv_solver_assert_sge_axiom,
8779
  (set_bit_fun_t) bv_solver_set_bit,
8780

8781
  (attach_eterm_fun_t) bv_solver_attach_eterm,
8782
  (eterm_of_var_fun_t) bv_solver_eterm_of_var,
8783

8784
  (build_model_fun_t) bv_solver_build_model,
8785
  (free_model_fun_t) bv_solver_free_model,
8786
  (bv_val_in_model_fun_t) bv_solver_value_in_model,
8787
};
8788

8789

8790
/*
8791
 * Return the interface descriptor
8792
 */
8793
bv_interface_t *bv_solver_bv_interface(bv_solver_t *solver) {
11,476✔
8794
  return &bv_solver_context;
11,476✔
8795
}
8796

8797

8798

8799
/********************************
8800
 *  SMT AND CONTROL INTERFACES  *
8801
 *******************************/
8802

8803
static th_ctrl_interface_t bv_solver_control = {
8804
  (start_intern_fun_t) bv_solver_start_internalization,
8805
  (start_fun_t) bv_solver_start_search,
8806
  (propagate_fun_t) bv_solver_propagate,
8807
  (final_check_fun_t) bv_solver_final_check,
8808
  (increase_level_fun_t) bv_solver_increase_decision_level,
8809
  (backtrack_fun_t) bv_solver_backtrack,
8810
  (push_fun_t) bv_solver_push,
8811
  (pop_fun_t) bv_solver_pop,
8812
  (reset_fun_t) bv_solver_reset,
8813
  (clear_fun_t) bv_solver_clear,
8814
};
8815

8816
static th_smt_interface_t bv_solver_smt = {
8817
  (assert_fun_t) bv_solver_assert_atom,
8818
  (expand_expl_fun_t) bv_solver_expand_explanation,
8819
  (select_pol_fun_t) bv_solver_select_polarity,
8820
  NULL,
8821
  NULL,
8822
};
8823

8824

8825
/*
8826
 * Get the control and smt interfaces
8827
 */
8828
th_ctrl_interface_t *bv_solver_ctrl_interface(bv_solver_t *solver) {
11,476✔
8829
  return &bv_solver_control;
11,476✔
8830
}
8831

8832
th_smt_interface_t *bv_solver_smt_interface(bv_solver_t *solver) {
11,476✔
8833
  return &bv_solver_smt;
11,476✔
8834
}
8835

8836

8837

8838
/*********************************************
8839
 *  SATELLITE SOLVER INTERFACE (FOR EGRAPH)  *
8840
 ********************************************/
8841

8842
static th_egraph_interface_t bv_solver_egraph = {
8843
  (assert_eq_fun_t) bv_solver_assert_var_eq,
8844
  (assert_diseq_fun_t) bv_solver_assert_var_diseq,
8845
  (assert_distinct_fun_t) bv_solver_assert_var_distinct,
8846
  (check_diseq_fun_t) bv_solver_check_disequality,
8847
  (is_constant_fun_t) bv_solver_var_is_constant,
8848
  (expand_eq_exp_fun_t) bv_solver_expand_th_explanation,
8849
  (reconcile_model_fun_t) bv_solver_reconcile_model,
8850
  (prepare_model_fun_t) bv_solver_prepare_model,
8851
  (equal_in_model_fun_t) bv_solver_var_equal_in_model,
8852
  (gen_inter_lemma_fun_t) bv_solver_gen_interface_lemma,
8853
  (release_model_fun_t) bv_solver_release_model,
8854
  (build_partition_fun_t) bv_solver_build_model_partition,
8855
  (free_partition_fun_t) bv_solver_release_model_partition,
8856
  (attach_to_var_fun_t) bv_solver_attach_eterm,
8857
  (get_eterm_fun_t) bv_solver_eterm_of_var,
8858
  (select_eq_polarity_fun_t) bv_solver_select_eq_polarity,
8859
};
8860

8861

8862
static bv_egraph_interface_t bv_solver_bv_egraph = {
8863
  (make_bv_var_fun_t) bv_solver_create_on_the_fly_var,
8864
  (bv_val_fun_t) bv_solver_value_in_model,
8865
};
8866

8867

8868
/*
8869
 * Get the egraph interfaces
8870
 */
8871
th_egraph_interface_t *bv_solver_egraph_interface(bv_solver_t *solver) {
4,401✔
8872
  return &bv_solver_egraph;
4,401✔
8873
}
8874

8875
bv_egraph_interface_t *bv_solver_bv_egraph_interface(bv_solver_t *solver) {
4,401✔
8876
  return &bv_solver_bv_egraph;
4,401✔
8877
}
8878

8879

8880

8881

8882
#if DUMP
8883

8884
/*******************
8885
 *  FOR DEBUGGING  *
8886
 ******************/
8887

8888
static void bv_solver_dump_state(bv_solver_t *solver, const char *filename) {
8889
  FILE *f;
8890

8891
  f = fopen(filename, "w");
8892
  if (f != NULL) {
8893
    //    fprintf(f, "\n--- Terms ---\n");
8894
    //    print_term_table(f, __yices_globals.terms);
8895
    fprintf(f, "\n--- Bitvector Partition ---\n");
8896
    print_bv_solver_partition(f, solver);
8897
    fprintf(f, "\n--- Bitvector Variables ---\n");
8898
    print_bv_solver_vars(f, solver);
8899
    fprintf(f, "\n--- Bitvector Atoms ---\n");
8900
    print_bv_solver_atoms(f, solver);
8901
    fprintf(f, "\ntotal: %"PRIu32" atoms\n", solver->atbl.natoms);
8902
    fprintf(f, "\n--- Bitvector Bounds ---\n");
8903
    print_bv_solver_bounds(f, solver);
8904
    fprintf(f, "\n--- DAG ---\n");
8905
    print_bv_solver_dag(f, solver);
8906
    if (solver->blaster != NULL) {
8907
      fprintf(f, "\n--- Gates ---\n");
8908
      print_gate_table(f, solver->blaster->htbl);
8909
    }
8910
    fprintf(f, "\n--- Clauses ---\n");
8911
    print_clauses(f, solver->core);
8912
    fprintf(f, "\n");
8913
    fclose(f);
8914
  }
8915
}
8916

8917
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc