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 * SUPPORT FOR CONVERTING BIT-VECTOR POLYNOMIALS
21 * TO ELEMENTARY EXPRESSIONS.
22 */
23
24 #include <assert.h>
25
26 #include "solvers/bv/bvpoly_compiler.h"
27 #include "terms/bv64_constants.h"
28 #include "utils/bit_tricks.h"
29
30
31 #define TRACE 0
32
33 #if TRACE
34
35 #include <stdio.h>
36 #include <inttypes.h>
37
38 #include "solvers/bv/bvsolver_printer.h"
39
40 #endif
41
42
43 /*
44 * QUEUES
45 */
46
47 /*
48 * Initialize to empty queue
49 */
init_bvc_queue(bvc_queue_t * queue)50 static inline void init_bvc_queue(bvc_queue_t *queue) {
51 queue->data = NULL;
52 queue->top = 0;
53 queue->size = 0;
54 }
55
56
57 /*
58 * Make the queue larger
59 */
bvc_queue_extend(bvc_queue_t * queue)60 static void bvc_queue_extend(bvc_queue_t *queue) {
61 uint32_t n;
62
63 n = queue->size;
64 if (n == 0) {
65 // first allocation
66 n = DEF_BVC_QUEUE_SIZE;
67 assert(n > 0 && n <= MAX_BVC_QUEUE_SIZE && queue->data == NULL);
68 } else {
69 n += (n >> 1); // 50% large
70 assert(n > queue->size);
71 if (n > MAX_BVC_QUEUE_SIZE) {
72 out_of_memory();
73 }
74 }
75
76 queue->data = (thvar_t *) safe_realloc(queue->data, n * sizeof(thvar_t));
77 queue->size = n;
78 }
79
80
81 /*
82 * Push x on the queue
83 */
bvc_queue_push(bvc_queue_t * queue,thvar_t x)84 static void bvc_queue_push(bvc_queue_t *queue, thvar_t x) {
85 uint32_t i;
86
87 i = queue->top;
88 if (i == queue->size) {
89 bvc_queue_extend(queue);
90 }
91 assert(i < queue->size);
92 queue->data[i] = x;
93 queue->top = i + 1;
94 }
95
96
97 /*
98 * Empty the queue
99 */
reset_bvc_queue(bvc_queue_t * queue)100 static inline void reset_bvc_queue(bvc_queue_t *queue) {
101 queue->top = 0;
102 }
103
104
105 /*
106 * Delete
107 */
delete_bvc_queue(bvc_queue_t * queue)108 static void delete_bvc_queue(bvc_queue_t *queue) {
109 if (queue->data != NULL) {
110 safe_free(queue->data);
111 queue->data = NULL;
112 }
113 }
114
115
116
117
118
119 /*
120 * COMPILER
121 */
122
123 /*
124 * Initialize:
125 * - vtbl = attached variable table
126 * - mtbl = attached merge table
127 */
init_bv_compiler(bvc_t * c,bv_vartable_t * vtbl,mtbl_t * mtbl)128 void init_bv_compiler(bvc_t *c, bv_vartable_t *vtbl, mtbl_t *mtbl) {
129 c->vtbl = vtbl;
130 c->mtbl = mtbl;
131 init_back_hmap(&c->cmap, 0);
132 init_bvc_queue(&c->elemexp);
133
134 init_bvc_dag(&c->dag, 0);
135 init_bvc_queue(&c->queue);
136 init_int_bvset(&c->in_queue, 0);
137
138 init_ivector(&c->buffer, 10);
139 init_bvpoly_buffer(&c->pbuffer);
140 init_pp_buffer(&c->pp_buffer, 10);
141 }
142
143
144 /*
145 * Delete
146 */
delete_bv_compiler(bvc_t * c)147 void delete_bv_compiler(bvc_t *c) {
148 delete_back_hmap(&c->cmap);
149 delete_bvc_queue(&c->elemexp);
150
151 delete_bvc_dag(&c->dag);
152 delete_bvc_queue(&c->queue);
153 delete_int_bvset(&c->in_queue);
154
155 delete_ivector(&c->buffer);
156 delete_bvpoly_buffer(&c->pbuffer);
157 delete_pp_buffer(&c->pp_buffer);
158 }
159
160
161 /*
162 * Empty
163 */
reset_bv_compiler(bvc_t * c)164 void reset_bv_compiler(bvc_t *c) {
165 reset_back_hmap(&c->cmap);
166 reset_bvc_queue(&c->elemexp);
167
168 reset_bvc_dag(&c->dag);
169 reset_bvc_queue(&c->queue);
170 reset_int_bvset(&c->in_queue);
171
172 ivector_reset(&c->buffer);
173 reset_bvpoly_buffer(&c->pbuffer, 32); // any bitsize would do
174 pp_buffer_reset(&c->pp_buffer);
175 }
176
177
178 /*
179 * Push: prepare a backtrack point
180 */
bv_compiler_push(bvc_t * c)181 void bv_compiler_push(bvc_t *c) {
182 back_hmap_push(&c->cmap);
183 }
184
185 /*
186 * For pop: remove all variables with index >= nv
187 */
bvc_queue_remove_vars(bvc_queue_t * q,uint32_t nv)188 static void bvc_queue_remove_vars(bvc_queue_t *q, uint32_t nv) {
189 uint32_t i, n, j;
190 thvar_t x;
191
192 j = 0;
193 n = q->top;
194 for (i=0; i<n; i++) {
195 x = q->data[i];
196 if (x < nv) {
197 q->data[j] = x;
198 j ++;
199 }
200 }
201 q->top = j;
202 }
203
bv_compiler_pop(bvc_t * c,uint32_t nv)204 void bv_compiler_pop(bvc_t *c, uint32_t nv) {
205 back_hmap_pop(&c->cmap);
206 bvc_queue_remove_vars(&c->elemexp, nv);
207 }
208
209
210
211 /*
212 * Set level to n:
213 * - this has the same effect as calling push n times
214 * - we use this function to make sure the compiler's internal
215 * level is the same as the bv_solver when the compiler i
216 * allocated.
217 */
bv_compiler_set_level(bvc_t * c,uint32_t n)218 void bv_compiler_set_level(bvc_t *c, uint32_t n) {
219 back_hmap_set_level(&c->cmap, n);
220 }
221
222
223
224 /*
225 * Get the variable mapped to x in cmap
226 * - return -1 if nothing is mapped to x
227 */
bvvar_compiles_to(bvc_t * c,thvar_t x)228 thvar_t bvvar_compiles_to(bvc_t *c, thvar_t x) {
229 back_hmap_elem_t *p;
230 thvar_t y;
231
232 assert(0 < x && x < c->vtbl->nvars);
233
234 y = null_thvar;
235 p = back_hmap_find(&c->cmap, x);
236 if (p != NULL) {
237 y = p->val;
238 assert(0 < y && y < c->vtbl->nvars);
239 }
240
241 return y;
242 }
243
244
245 /*
246 * Store the mapping [x --> y] in c->cmap
247 */
bv_compiler_store_map(bvc_t * c,thvar_t x,thvar_t y)248 static void bv_compiler_store_map(bvc_t *c, thvar_t x, thvar_t y) {
249 back_hmap_elem_t *p;
250
251 assert(0 < x && x < c->vtbl->nvars && 0 < y && y < c->vtbl->nvars && x != y);
252
253 p = back_hmap_get(&c->cmap, x);
254 assert(p->val == -1);
255 p->val = y;
256 }
257
258
259
260 /*
261 * CONSTRUCTORS FOR ELEMENTARY EXPRESSIONS
262 */
263
264 /*
265 * Map x to a constant a
266 * - n = number of bits in a
267 */
bv_compiler_map_to_const64(bvc_t * c,thvar_t x,uint64_t a,uint32_t n)268 static void bv_compiler_map_to_const64(bvc_t *c, thvar_t x, uint64_t a, uint32_t n) {
269 thvar_t v;
270
271 assert(1 <= n && n <= 64 && a == norm64(a, n));
272 v = get_bvconst64(c->vtbl, n, a);
273 bv_compiler_store_map(c, x, v);
274 }
275
276
bv_compiler_map_to_const(bvc_t * c,thvar_t x,uint32_t * a,uint32_t n)277 static void bv_compiler_map_to_const(bvc_t *c, thvar_t x, uint32_t *a, uint32_t n) {
278 thvar_t v;
279
280 assert(n > 64 && bvconst_is_normalized(a, n));
281 v = get_bvconst(c->vtbl, n, a);
282 bv_compiler_store_map(c, x, v);
283 }
284
285
286 // variant: constant = 0
bv_compiler_map_to_zero(bvc_t * c,thvar_t x,uint32_t n)287 static void bv_compiler_map_to_zero(bvc_t *c, thvar_t x, uint32_t n) {
288 uint32_t aux[8];
289 uint32_t *a;
290 uint32_t w;
291
292 assert(n > 64);
293 w = (n+31) >> 5;
294 if (w <= 8) {
295 bvconst_clear(aux, w);
296 bv_compiler_map_to_const(c, x, aux, n);
297 } else {
298 a = bvconst_alloc(w);
299 bvconst_clear(a, w);
300 bv_compiler_map_to_const(c, x, a, n);
301 bvconst_free(a, w);
302 }
303 }
304
305
306 /*
307 * In all constructors:
308 * - n = number of bits
309 * - x (and y) = operands
310 */
bv_compiler_mk_bvadd(bvc_t * c,uint32_t n,thvar_t x,thvar_t y)311 static thvar_t bv_compiler_mk_bvadd(bvc_t *c, uint32_t n, thvar_t x, thvar_t y) {
312 thvar_t v;
313 bool new;
314
315 assert(0 < x && x < c->vtbl->nvars && 0 < y && y < c->vtbl->nvars);
316
317 // normalize: left operand <= right operand
318 if (x > y) {
319 v = x; x = y; y = v;
320 }
321
322 v = get_bvadd(c->vtbl, n, x, y, &new);
323 if (new) {
324 bvc_queue_push(&c->elemexp, v);
325 }
326
327 return v;
328 }
329
bv_compiler_mk_bvsub(bvc_t * c,uint32_t n,thvar_t x,thvar_t y)330 static thvar_t bv_compiler_mk_bvsub(bvc_t *c, uint32_t n, thvar_t x, thvar_t y) {
331 thvar_t v;
332 bool new;
333
334 assert(0 < x && x < c->vtbl->nvars && 0 < y && y < c->vtbl->nvars);
335
336 v = get_bvsub(c->vtbl, n, x, y, &new);
337 if (new) {
338 bvc_queue_push(&c->elemexp, v);
339 }
340
341 return v;
342 }
343
bv_compiler_mk_bvmul(bvc_t * c,uint32_t n,thvar_t x,thvar_t y)344 static thvar_t bv_compiler_mk_bvmul(bvc_t *c, uint32_t n, thvar_t x, thvar_t y) {
345 thvar_t v;
346 bool new;
347
348 assert(0 < x && x < c->vtbl->nvars && 0 < y && y < c->vtbl->nvars);
349
350 // normalize: left operand <= right operand
351 if (x > y) {
352 v = x; x = y; y = v;
353 }
354
355 v = get_bvmul(c->vtbl, n, x, y, &new);
356 if (new) {
357 bvc_queue_push(&c->elemexp, v);
358 }
359
360 return v;
361 }
362
bv_compiler_mk_bvneg(bvc_t * c,uint32_t n,thvar_t x)363 static thvar_t bv_compiler_mk_bvneg(bvc_t *c, uint32_t n, thvar_t x) {
364 thvar_t v;
365 bool new;
366
367 assert(0 < x && x < c->vtbl->nvars);
368
369 v = get_bvneg(c->vtbl, n, x, &new);
370 if (new) {
371 bvc_queue_push(&c->elemexp, v);
372 }
373
374 return v;
375 }
376
bv_compiler_mk_zero(bvc_t * c,uint32_t n)377 static thvar_t bv_compiler_mk_zero(bvc_t *c, uint32_t n) {
378 uint32_t aux[8];
379 uint32_t *a;
380 uint32_t w;
381 thvar_t v;
382
383 assert(1 <= n);
384
385 if (n <= 64) {
386 v = get_bvconst64(c->vtbl, n, 0);
387 } else {
388 w = (n+31) >> 5;
389 a = aux;
390 if (w > 8) {
391 a = bvconst_alloc(w);
392 }
393 bvconst_clear(a, w);
394 v = get_bvconst(c->vtbl, n, a);
395 if (w > 8) {
396 bvconst_free(a, w);
397 }
398 }
399
400 bvc_queue_push(&c->elemexp, v);
401
402 return v;
403 }
404
bv_compiler_mk_const64(bvc_t * c,uint64_t a,uint32_t n)405 static thvar_t bv_compiler_mk_const64(bvc_t *c, uint64_t a, uint32_t n) {
406 thvar_t v;
407
408 assert(1 <= n && n <= 64 && a == norm64(a, n));
409 v = get_bvconst64(c->vtbl, n, a);
410 bvc_queue_push(&c->elemexp, v);
411
412 return v;
413 }
414
bv_compiler_mk_const(bvc_t * c,uint32_t * a,uint32_t n)415 static thvar_t bv_compiler_mk_const(bvc_t *c, uint32_t *a, uint32_t n) {
416 thvar_t v;
417
418 assert(n > 64 && bvconst_is_normalized(a, n));
419 v = get_bvconst(c->vtbl, n, a);
420 bvc_queue_push(&c->elemexp, v);
421
422 return v;
423 }
424
425
426 /*
427 * POWER-PRODUCT CONSTRUCTION
428 */
429
430 /*
431 * Build (bvmul x y) but treat x = null_thvar as 1
432 */
mk_bvmul_aux(bvc_t * c,uint32_t n,thvar_t x,thvar_t y)433 static thvar_t mk_bvmul_aux(bvc_t *c, uint32_t n, thvar_t x, thvar_t y) {
434 return x == null_thvar ? y : bv_compiler_mk_bvmul(c, n, x, y);
435 }
436
437 /*
438 * Build the variable x := (x_1^d_1 ... x_k^d_k)
439 * - where x_1^d_1 ... x_k^d_k is stored in b
440 * - n = number of bits in x_1 ... x_k
441 * - the total degree d_1 + ... + d_k must be positive
442 */
bv_compiler_mk_power_product(bvc_t * c,uint32_t n,pp_buffer_t * b)443 static thvar_t bv_compiler_mk_power_product(bvc_t *c, uint32_t n, pp_buffer_t *b) {
444 varexp_t *a;
445 ivector_t *v;
446 uint32_t i, m, d;
447 bool zero_deg;
448 thvar_t x;
449
450
451 v = &c->buffer;
452 ivector_reset(v);
453
454 m = b->len;
455 a = b->prod;
456
457 do {
458 zero_deg = true;
459 x = null_thvar;
460 /*
461 * In each iteration:
462 * x = product of all variables x_i's that have odd degree
463 * (or null_thvar if all variables have even degree)
464 * d_i := d_i/2
465 */
466 for (i=0; i<m; i++) {
467 d = a[i].exp;
468 if ((d & 1) != 0) {
469 x = mk_bvmul_aux(c, n, x, a[i].var);
470 }
471 d >>= 1;
472 a[i].exp = d;
473 zero_deg = zero_deg & (d == 0);
474 }
475
476 ivector_push(v, x);
477
478 } while (! zero_deg);
479
480
481 /*
482 * v contains [x_0, ... x_t],
483 * the result is x_0 * x_1^2 * x_2^4 ... * x_t^(2^t)
484 */
485 assert(v->size > 0);
486 i = v->size - 1;
487 x = v->data[i];
488 assert(x != null_thvar);
489 while (i > 0) {
490 i --;
491 x = bv_compiler_mk_bvmul(c, n, x, x);
492 x = mk_bvmul_aux(c, n, v->data[i], x);
493 }
494
495 return x;
496 }
497
498
499
500 /*
501 * SIMPLIFICATION
502 */
503
504 /*
505 * Apply the substitution stored in the merge table to p
506 * - store the result in the poly_buffer b
507 */
bv_compiler_simplify_poly64(bvc_t * c,bvpoly64_t * p,bvpoly_buffer_t * b)508 static void bv_compiler_simplify_poly64(bvc_t *c, bvpoly64_t *p, bvpoly_buffer_t *b) {
509 bv_vartable_t *vtbl;
510 uint32_t i, n;
511 thvar_t x;
512
513 reset_bvpoly_buffer(b, p->bitsize);
514
515 vtbl = c->vtbl;
516
517 n = p->nterms;
518 i = 0;
519 if (p->mono[0].var == const_idx) {
520 bvpoly_buffer_add_const64(b, p->mono[0].coeff);
521 i ++;
522 }
523
524 while (i < n) {
525 assert(p->mono[i].var != const_idx);
526 x = mtbl_get_root(c->mtbl, p->mono[i].var);
527 // x = bv_compiler_subst_var(c, p->mono[i].var);
528 if (bvvar_is_const64(vtbl, x)) {
529 bvpoly_buffer_add_const64(b, p->mono[i].coeff * bvvar_val64(vtbl, x));
530 } else {
531 bvpoly_buffer_add_mono64(b, x, p->mono[i].coeff);
532 }
533 i ++;
534 }
535
536 normalize_bvpoly_buffer(b);
537 }
538
bv_compiler_simplify_poly(bvc_t * c,bvpoly_t * p,bvpoly_buffer_t * b)539 static void bv_compiler_simplify_poly(bvc_t *c, bvpoly_t *p, bvpoly_buffer_t *b) {
540 bv_vartable_t *vtbl;
541 uint32_t i, n;
542 thvar_t x;
543
544 reset_bvpoly_buffer(b, p->bitsize);
545
546 vtbl = c->vtbl;
547
548 n = p->nterms;
549 i = 0;
550 if (p->mono[0].var == const_idx) {
551 bvpoly_buffer_add_constant(b, p->mono[0].coeff);
552 i ++;
553 }
554
555 while (i < n) {
556 assert(p->mono[i].var != const_idx);
557 x = mtbl_get_root(c->mtbl, p->mono[i].var);
558 // x = bv_compiler_subst_var(c, p->mono[i].var);
559 if (bvvar_is_const(vtbl, x)) {
560 bvpoly_buffer_addmul_constant(b, p->mono[i].coeff, bvvar_val(vtbl, x));
561 } else {
562 bvpoly_buffer_add_monomial(b, x, p->mono[i].coeff);
563 }
564 i ++;
565 }
566
567 normalize_bvpoly_buffer(b);
568 }
569
570
571 /*
572 * COMPILATION PHASE 1: STORE VARIABLES TO COMPILE
573 */
574
575 /*
576 * Check whether x is in cmap
577 */
bvvar_is_compiled(bvc_t * c,thvar_t x)578 static inline bool bvvar_is_compiled(bvc_t *c, thvar_t x) {
579 return back_hmap_find(&c->cmap, x) != NULL;
580 }
581
582
583 /*
584 * Check whether x must be added to the queue
585 * - i.e., x is not already compiled and not already in the queue
586 */
bvvar_to_process(bvc_t * c,thvar_t x)587 static bool bvvar_to_process(bvc_t *c, thvar_t x) {
588 return !int_bvset_member(&c->in_queue, x) && !bvvar_is_compiled(c, x);
589 }
590
591
592 /*
593 * Add variable x to the internal queue
594 * - also recursively add all the children of x
595 * so that the children precede x in c->queue
596 */
bv_compiler_push_poly64(bvc_t * c,bvpoly64_t * p)597 static void bv_compiler_push_poly64(bvc_t *c, bvpoly64_t *p) {
598 uint32_t i, n;
599 thvar_t x;
600
601 n = p->nterms;
602 i = 0;
603 if (p->mono[0].var == const_idx) {
604 i = 1;
605 }
606 while (i < n) {
607 x = mtbl_get_root(c->mtbl, p->mono[i].var);
608 bv_compiler_push_var(c, x);
609 i ++;
610 }
611 }
612
bv_compiler_push_poly(bvc_t * c,bvpoly_t * p)613 static void bv_compiler_push_poly(bvc_t *c, bvpoly_t *p) {
614 uint32_t i, n;
615 thvar_t x;
616
617 n = p->nterms;
618 i = 0;
619 if (p->mono[0].var == const_idx) {
620 i = 1;
621 }
622 while (i < n) {
623 x = mtbl_get_root(c->mtbl, p->mono[i].var);
624 bv_compiler_push_var(c, x);
625 i ++;
626 }
627 }
628
bv_compiler_push_pprod(bvc_t * c,pprod_t * p)629 static void bv_compiler_push_pprod(bvc_t *c, pprod_t *p) {
630 uint32_t i, n;
631 thvar_t x;
632
633 n = p->len;
634 for (i=0; i<n; i++) {
635 x = mtbl_get_root(c->mtbl, p->prod[i].var);
636 bv_compiler_push_var(c, x);
637 }
638 }
639
640
641 /*
642 * Add x and all the variables on which x depends to the queue
643 * - mark x first (to prevent looping if there are circular dependencies)
644 * - recursively push the children
645 * - then add x to the queue
646 */
bv_compiler_push_var(bvc_t * c,thvar_t x)647 void bv_compiler_push_var(bvc_t *c, thvar_t x) {
648 bv_vartable_t *vtbl;
649
650 assert(0 < x && x < c->vtbl->nvars);
651
652 vtbl = c->vtbl;
653
654 switch (bvvar_tag(vtbl, x)) {
655 case BVTAG_POLY64:
656 if (bvvar_to_process(c, x)) {
657 int_bvset_add(&c->in_queue, x);
658 bv_compiler_push_poly64(c, bvvar_poly64_def(vtbl, x));
659 bvc_queue_push(&c->queue, x);
660 }
661 break;
662
663 case BVTAG_POLY:
664 if (bvvar_to_process(c, x)) {
665 int_bvset_add(&c->in_queue, x);
666 bv_compiler_push_poly(c, bvvar_poly_def(vtbl, x));
667 bvc_queue_push(&c->queue, x);
668 }
669 break;
670
671 case BVTAG_PPROD:
672 if (bvvar_to_process(c, x)) {
673 int_bvset_add(&c->in_queue, x);
674 bv_compiler_push_pprod(c, bvvar_pprod_def(vtbl, x));
675 bvc_queue_push(&c->queue, x);
676 }
677 break;
678
679 default:
680 // skip x
681 break;
682 }
683 }
684
685
686
687 /*
688 * COMPILATION PHASE 2: CONVERT TO THE DAG REPRESENTATION
689 */
690
691 /*
692 * Convert p to a DAG node
693 * - return the node occurrence
694 * - all variables of p that are not in dag->vsets are mapped to leaf nodes
695 */
bv_compiler_pprod_to_dag(bvc_t * c,pprod_t * p,uint32_t bitsize)696 static node_occ_t bv_compiler_pprod_to_dag(bvc_t *c, pprod_t *p, uint32_t bitsize) {
697 bvc_dag_t *dag;
698 ivector_t *v;
699 uint32_t i, n;
700 thvar_t x;
701 node_occ_t q;
702
703 dag = &c->dag;
704
705 v = &c->buffer;
706 ivector_reset(v);
707
708 n = p->len;
709 for (i=0; i<n; i++) {
710 x = mtbl_get_root(c->mtbl, p->prod[i].var);
711 // x = bv_compiler_subst_var(c, p->prod[i].var);
712 q = bvc_dag_get_nocc_of_var(dag, x, bitsize);
713 ivector_push(v, q);
714 }
715
716 return bvc_dag_pprod(dag, p, v->data, bitsize);
717 }
718
719
720 /*
721 * Convert polynomial buffer b to DAG:
722 * - b must not be constant
723 */
bv_compiler_pbuffer_to_dag(bvc_t * c,bvpoly_buffer_t * b)724 static node_occ_t bv_compiler_pbuffer_to_dag(bvc_t *c, bvpoly_buffer_t *b) {
725 bvc_dag_t *dag;
726 ivector_t *v;
727 uint32_t i, n, nbits;
728 thvar_t x;
729 node_occ_t q;
730
731 assert(! bvpoly_buffer_is_constant(b));
732
733 dag = &c->dag;
734
735 v = &c->buffer;
736 ivector_reset(v);
737
738 n = bvpoly_buffer_num_terms(b);
739 nbits = bvpoly_buffer_bitsize(b);
740
741 i = 0;
742 if (bvpoly_buffer_var(b, 0) == const_idx) {
743 ivector_push(v, const_idx); // need a place-holder in v->data[0]
744 i = 1;
745 }
746 while (i < n) {
747 x = bvpoly_buffer_var(b, i);
748 assert(x != const_idx && mtbl_is_root(c->mtbl, x));
749 q = bvc_dag_get_nocc_of_var(dag, x, nbits);
750 ivector_push(v, q);
751 i++;
752 }
753
754 return bvc_dag_poly_buffer(dag, b, v->data);
755 }
756
757
758
759 /*
760 * Build a DAG node for x and store the mapping [x --> node]
761 * - x must be a polynomial or a power product
762 */
bv_compiler_map_var_to_dag(bvc_t * c,thvar_t x)763 static void bv_compiler_map_var_to_dag(bvc_t *c, thvar_t x) {
764 bv_vartable_t *vtbl;
765 bvpoly_buffer_t *b;
766 node_occ_t q;
767 uint64_t a;
768
769 assert(0 < x && x < c->vtbl->nvars && int_bvset_member(&c->in_queue, x));
770
771 q = -1; // Stop GCC warning
772
773 vtbl = c->vtbl;
774
775 switch (bvvar_tag(vtbl, x)) {
776 case BVTAG_POLY64:
777 b = &c->pbuffer;
778 bv_compiler_simplify_poly64(c, bvvar_poly64_def(vtbl, x), b);
779 if (bvpoly_buffer_is_constant(b)) {
780 a = 0;
781 if (!bvpoly_buffer_is_zero(b)) {
782 a = bvpoly_buffer_coeff64(b, 0);
783 }
784 bv_compiler_map_to_const64(c, x, a, b->bitsize);
785 return;
786 }
787 q = bv_compiler_pbuffer_to_dag(c, b);
788 break;
789
790 case BVTAG_POLY:
791 b = &c->pbuffer;
792 bv_compiler_simplify_poly(c, bvvar_poly_def(vtbl, x), b);
793 if (bvpoly_buffer_is_constant(b)) {
794 if (bvpoly_buffer_is_zero(b)) {
795 bv_compiler_map_to_zero(c, x, b->bitsize);
796 } else {
797 bv_compiler_map_to_const(c, x, bvpoly_buffer_coeff(b, 0), b->bitsize);
798 }
799 return;
800 }
801 q = bv_compiler_pbuffer_to_dag(c, b);
802 break;
803
804 case BVTAG_PPROD:
805 q = bv_compiler_pprod_to_dag(c, bvvar_pprod_def(vtbl, x), bvvar_bitsize(vtbl, x));
806 break;
807
808 default:
809 assert(false);
810 break;
811 }
812
813 bvc_dag_map_var(&c->dag, x, q);
814 int_bvset_remove(&c->in_queue, x);
815 }
816
817
818
819 /*
820 * Simplify the DAG nodes using elementary expression x
821 */
822
823 // case 1: x is (bvadd y z) where y != z and both y and z occur in the dag
bv_compiler_simplify_dag_bvadd(bvc_t * c,thvar_t x,thvar_t y,thvar_t z)824 static void bv_compiler_simplify_dag_bvadd(bvc_t *c, thvar_t x, thvar_t y, thvar_t z) {
825 bvc_dag_t *dag;
826 node_occ_t ny, nz, nx;
827 uint32_t nbits;
828
829 dag = &c->dag;
830 ny = bvc_dag_nocc_of_var(dag, y);
831 nz = bvc_dag_nocc_of_var(dag, z);
832 if (bvc_dag_check_reduce_sum(dag, ny, nz)) {
833 nbits = bvvar_bitsize(c->vtbl, x);
834 assert(bvvar_bitsize(c->vtbl, y) == nbits &&
835 bvvar_bitsize(c->vtbl, z) == nbits);
836
837 nx = bvc_dag_leaf(dag, x, nbits);
838 bvc_dag_reduce_sum(dag, nx, ny, nz);
839 }
840 }
841
842 // case 2: x is (bvsub y z) where y != z and both y and z occur in the dag
bv_compiler_simplify_dag_bvsub(bvc_t * c,thvar_t x,thvar_t y,thvar_t z)843 static void bv_compiler_simplify_dag_bvsub(bvc_t *c, thvar_t x, thvar_t y, thvar_t z) {
844 bvc_dag_t *dag;
845 node_occ_t ny, nz, nx;
846 uint32_t nbits;
847
848 dag = &c->dag;
849 ny = bvc_dag_nocc_of_var(dag, y);
850 nz = negate_occ(bvc_dag_nocc_of_var(dag, z));
851 if (bvc_dag_check_reduce_sum(dag, ny, nz)) {
852 nbits = bvvar_bitsize(c->vtbl, x);
853 assert(bvvar_bitsize(c->vtbl, y) == nbits &&
854 bvvar_bitsize(c->vtbl, z) == nbits);
855
856 nx = bvc_dag_leaf(dag, x, nbits);
857 bvc_dag_reduce_sum(dag, nx, ny, nz);
858 }
859 }
860
861 // case 3: x is (bvmul y z) where y and z occur in the dag
bv_compiler_simplify_dag_bvmul(bvc_t * c,thvar_t x,thvar_t y,thvar_t z)862 static void bv_compiler_simplify_dag_bvmul(bvc_t *c, thvar_t x, thvar_t y, thvar_t z) {
863 bvc_dag_t *dag;
864 node_occ_t ny, nz, nx;
865 uint32_t nbits;
866
867 dag = &c->dag;
868 ny = bvc_dag_nocc_of_var(dag, y);
869 nz = bvc_dag_nocc_of_var(dag, z);
870 if (bvc_dag_check_reduce_prod(dag, ny, nz)) {
871 nbits = bvvar_bitsize(c->vtbl, x);
872 assert(bvvar_bitsize(c->vtbl, y) == nbits &&
873 bvvar_bitsize(c->vtbl, z) == nbits);
874
875 nx = bvc_dag_leaf(dag, x, nbits);
876 bvc_dag_reduce_prod(dag, nx, ny, nz);
877 }
878 }
879
880
881
bv_compiler_simplify_dag(bvc_t * c,thvar_t x)882 static void bv_compiler_simplify_dag(bvc_t *c, thvar_t x) {
883 bv_vartable_t *vtbl;
884 bvc_dag_t *dag;
885 thvar_t *aux;
886 thvar_t y, z;
887
888 dag = &c->dag;
889 vtbl = c->vtbl;
890 switch (bvvar_tag(vtbl, x)) {
891 case BVTAG_ADD:
892 aux = bvvar_binop(vtbl, x);
893 y = mtbl_get_root(c->mtbl, aux[0]);
894 z = mtbl_get_root(c->mtbl, aux[1]);
895 if (y != z && bvc_dag_var_is_present(dag, y) && bvc_dag_var_is_present(dag, z)) {
896 bv_compiler_simplify_dag_bvadd(c, x, y, z);
897 }
898 break;
899
900 case BVTAG_SUB:
901 aux = bvvar_binop(vtbl, x);
902 y = mtbl_get_root(c->mtbl, aux[0]);
903 z = mtbl_get_root(c->mtbl, aux[1]);
904 if (y != z && bvc_dag_var_is_present(dag, y) && bvc_dag_var_is_present(dag, z)) {
905 bv_compiler_simplify_dag_bvsub(c, x, y, z);
906 }
907 break;
908
909 case BVTAG_MUL:
910 aux = bvvar_binop(vtbl, x);
911 y = mtbl_get_root(c->mtbl, aux[0]);
912 z = mtbl_get_root(c->mtbl, aux[1]);
913 if (bvc_dag_var_is_present(dag, y) && bvc_dag_var_is_present(dag, z)) {
914 bv_compiler_simplify_dag_bvmul(c, x, y, z);
915 }
916 break;
917
918 default:
919 break;
920 }
921 }
922
923
924
925 /*
926 * PHASE 3: CONVERT NODES TO ELEMENTARY EXPRESSIONS
927 */
928
929 /*
930 * Compilation of an elementary node i
931 */
932 // case 1: i is [offset a0 n]
bvc_process_offset(bvc_t * c,bvnode_t i,bvc_offset_t * d)933 static void bvc_process_offset(bvc_t *c, bvnode_t i, bvc_offset_t *d) {
934 bv_vartable_t *vtbl;
935 uint32_t nbits;
936 thvar_t x, y, z;
937
938 vtbl = c->vtbl;
939 nbits = d->header.bitsize;
940 if (nbits <= 64) {
941 y = get_bvconst64(vtbl, nbits, d->constant.c);
942 } else {
943 y = get_bvconst(vtbl, nbits, d->constant.w);
944 }
945 z = bvc_dag_get_var_of_leaf(&c->dag, d->nocc);
946
947 if (sign_of_occ(d->nocc) == 0) {
948 // i is compiled to [bvadd y z]
949 x = bv_compiler_mk_bvadd(c, nbits, y, z);
950 } else {
951 // i is compiled to [bvsub y z];
952 x = bv_compiler_mk_bvsub(c, nbits, y, z);
953 }
954 bvc_dag_convert_to_leaf(&c->dag, i, x);
955 }
956
957 // case 2: i is [mono a0 n]
bvc_process_monomial(bvc_t * c,bvnode_t i,bvc_mono_t * d)958 static void bvc_process_monomial(bvc_t *c, bvnode_t i, bvc_mono_t *d) {
959 bv_vartable_t *vtbl;
960 uint32_t nbits;
961 thvar_t x, y, z;
962
963 vtbl = c->vtbl;
964 nbits = d->header.bitsize;
965 if (nbits <= 64) {
966 y = get_bvconst64(vtbl, nbits, d->coeff.c);
967 } else {
968 y = get_bvconst(vtbl, nbits, d->coeff.w);
969 }
970 assert(sign_of_occ(d->nocc) == 0);
971 z = bvc_dag_get_var_of_leaf(&c->dag, d->nocc);
972
973 // i is compiled to [bvmul y z]
974 x = bv_compiler_mk_bvmul(c, nbits, y, z);
975 bvc_dag_convert_to_leaf(&c->dag, i, x);
976 }
977
978 // case 3: i is [prod n1 n2] or [prod n1^2]
bvc_process_elem_prod(bvc_t * c,bvnode_t i,bvc_prod_t * d)979 static void bvc_process_elem_prod(bvc_t *c, bvnode_t i, bvc_prod_t *d) {
980 uint32_t nbits;
981 node_occ_t nx, ny, nz;
982 thvar_t x, y, z;
983
984 assert((d->len == 1 && d->prod[0].exp == 2) ||
985 (d->len == 2 && d->prod[0].exp == 1 && d->prod[1].exp == 1));
986
987 nbits = d->header.bitsize;
988
989 ny = d->prod[0].var;
990 assert(sign_of_occ(ny) == 0);
991 y = bvc_dag_get_var_of_leaf(&c->dag, ny);
992 nz = ny;
993 z = y;
994 if (d->len == 2) {
995 nz = d->prod[1].var;
996 assert(sign_of_occ(nz) == 0);
997 z = bvc_dag_get_var_of_leaf(&c->dag, nz);
998 }
999
1000 // i is compiled to [bvmul y z]
1001 x = bv_compiler_mk_bvmul(c, nbits, y, z);
1002 bvc_dag_convert_to_leaf(&c->dag, i, x);
1003
1004 // now replace (ny * nz) by nx everywhere
1005 nx = bvp(i);
1006 bvc_dag_reduce_prod(&c->dag, nx, ny, nz);
1007 }
1008
1009 // case 4: i is [sum n1 n2]
bvc_process_elem_sum(bvc_t * c,bvnode_t i,bvc_sum_t * d)1010 static void bvc_process_elem_sum(bvc_t *c, bvnode_t i, bvc_sum_t *d) {
1011 uint32_t nbits;
1012 node_occ_t nx, ny, nz;
1013 thvar_t x, y, z;
1014
1015 assert(d->len == 2);
1016
1017 nbits = d->header.bitsize;
1018 ny = d->sum[0];
1019 nz = d->sum[1];
1020 y = bvc_dag_get_var_of_leaf(&c->dag, ny);
1021 z = bvc_dag_get_var_of_leaf(&c->dag, nz);
1022
1023 if (sign_of_occ(ny) == 0) {
1024 if (sign_of_occ(nz) == 0) {
1025 // i is compiled to [bvadd y z]
1026 x = bv_compiler_mk_bvadd(c, nbits, y, z);
1027 } else {
1028 // i is compiled to [bvsub y z]
1029 x = bv_compiler_mk_bvsub(c, nbits, y, z);
1030 }
1031 } else {
1032 if (sign_of_occ(nz) == 0) {
1033 // i is compiled to [bvsub z y]
1034 x = bv_compiler_mk_bvsub(c, nbits, z, y);
1035 } else {
1036 // i is compiled to [bnveg [bvadd y z]]?
1037 x = bv_compiler_mk_bvadd(c, nbits, y, z);
1038 x = bv_compiler_mk_bvneg(c, nbits, x);
1039 }
1040 }
1041
1042 // replace ny nz by nx everywhere
1043 bvc_dag_convert_to_leaf(&c->dag, i, x);
1044 nx = bvp(i);
1045 bvc_dag_reduce_sum(&c->dag, nx, ny, nz);
1046 }
1047
1048 // case 5: i is zero
bvc_process_zero(bvc_t * c,bvnode_t i,bvc_zero_t * d)1049 static void bvc_process_zero(bvc_t *c, bvnode_t i, bvc_zero_t *d) {
1050 uint32_t nbits;
1051 thvar_t x;
1052
1053 nbits = d->header.bitsize;
1054 x = bv_compiler_mk_zero(c, nbits);
1055 bvc_dag_convert_to_leaf(&c->dag, i, x);
1056 }
1057
1058
1059 // case 6: i is a constant node
bvc_process_constant(bvc_t * c,bvnode_t i,bvc_constant_t * d)1060 static void bvc_process_constant(bvc_t *c, bvnode_t i, bvc_constant_t *d) {
1061 uint32_t nbits;
1062 thvar_t x;
1063
1064 nbits = d->header.bitsize;
1065 if (nbits <= 64) {
1066 x = bv_compiler_mk_const64(c, d->value.c, nbits);
1067 } else {
1068 x = bv_compiler_mk_const(c, d->value.w, nbits);
1069 }
1070 bvc_dag_convert_to_leaf(&c->dag, i, x);
1071 }
1072
1073
bvc_process_elem_node(bvc_t * c,bvnode_t i)1074 static void bvc_process_elem_node(bvc_t *c, bvnode_t i) {
1075 bvc_dag_t *dag;
1076
1077 dag = &c->dag;
1078 switch (bvc_dag_node_type(dag, i)) {
1079 case BVC_ZERO:
1080 bvc_process_zero(c, i, bvc_dag_node_zero(dag, i));
1081 break;
1082
1083 case BVC_CONSTANT:
1084 bvc_process_constant(c, i, bvc_dag_node_constant(dag, i));
1085 break;
1086
1087 case BVC_OFFSET:
1088 bvc_process_offset(c, i, bvc_dag_node_offset(dag, i));
1089 break;
1090
1091 case BVC_MONO:
1092 bvc_process_monomial(c, i, bvc_dag_node_mono(dag, i));
1093 break;
1094
1095 case BVC_PROD:
1096 bvc_process_elem_prod(c, i, bvc_dag_node_prod(dag, i));
1097 break;
1098
1099 case BVC_SUM:
1100 bvc_process_elem_sum(c, i, bvc_dag_node_sum(dag, i));
1101 break;
1102
1103 case BVC_LEAF:
1104 case BVC_ALIAS:
1105 assert(false);
1106 break;
1107 }
1108 }
1109
1110
1111
1112 /*
1113 * SIMPLE NODES
1114 */
1115
1116 /*
1117 * Check whether product or sum p is simple:
1118 * - return true if all the nodes occurring in p are leaves
1119 * and p contains at most one shared leaf
1120 * - we take the degree into account: if p contains product x^k
1121 * with k>1 and x is shared then that's more than one shared occurrence
1122 */
bvc_prod_is_simple(bvc_dag_t * dag,bvc_prod_t * p)1123 static bool bvc_prod_is_simple(bvc_dag_t *dag, bvc_prod_t *p) {
1124 uint32_t i, n, n_shared;
1125 node_occ_t nx;
1126
1127 n_shared = 0;
1128 n = p->len;
1129 for (i=0; i<n; i++) {
1130 nx = p->prod[i].var;
1131 if (!bvc_dag_occ_is_leaf(dag, nx)) {
1132 return false;
1133 }
1134 if (bvc_dag_occ_is_shared(dag, nx)) {
1135 // n_shared ++;
1136 n_shared += p->prod[i].exp;
1137 if (n_shared > 1) return false;
1138 }
1139 }
1140
1141 assert(n_shared <= 1);
1142
1143 return true;
1144 }
1145
bvc_sum_is_simple(bvc_dag_t * dag,bvc_sum_t * p)1146 static bool bvc_sum_is_simple(bvc_dag_t *dag, bvc_sum_t *p) {
1147 uint32_t i, n, n_shared;
1148 node_occ_t nx;
1149
1150 n_shared = 0;
1151 n = p->len;
1152 for (i=0; i<n; i++) {
1153 nx = p->sum[i];
1154 if (!bvc_dag_occ_is_leaf(dag, nx)) {
1155 return false;
1156 }
1157 if (bvc_dag_occ_is_shared(dag, nx)) {
1158 n_shared ++;
1159 if (n_shared > 1) return false;
1160 }
1161 }
1162
1163 assert(n_shared <= 1);
1164
1165 return true;
1166 }
1167
1168
1169 /*
1170 * Compilation of a simple/non-elementary node i
1171 */
bvc_process_simple_prod(bvc_t * c,bvnode_t i,bvc_prod_t * p)1172 static void bvc_process_simple_prod(bvc_t *c, bvnode_t i, bvc_prod_t *p) {
1173 pp_buffer_t *pp;
1174 uint32_t j, m, nbits;
1175 thvar_t x;
1176
1177 assert(p->len >= 1);
1178
1179 pp = &c->pp_buffer;
1180 pp_buffer_reset(pp);
1181
1182 /*
1183 * p is [n1^d1 ... n_m^d_m]
1184 * find x_i := variable of leaf node n_i
1185 * then build x = [x1^d1 ... x_m^d_m]
1186 */
1187 nbits = p->header.bitsize;
1188 m = p->len;
1189 for (j=0; j<m; j++) {
1190 assert(sign_of_occ(p->prod[j].var) == 0);
1191 x = bvc_dag_get_var_of_leaf(&c->dag, p->prod[j].var);
1192 pp_buffer_push_varexp(pp, x, p->prod[j].exp);
1193 }
1194
1195 x = bv_compiler_mk_power_product(c, nbits, pp);
1196
1197 // replace i by [leaf x] in DAG
1198 bvc_dag_convert_to_leaf(&c->dag, i, x);
1199 }
1200
bvc_process_simple_sum(bvc_t * c,bvnode_t i,bvc_sum_t * p)1201 static void bvc_process_simple_sum(bvc_t *c, bvnode_t i, bvc_sum_t *p) {
1202 uint32_t j, m, nbits;
1203 node_occ_t n;
1204 thvar_t x, y;
1205 bool all_neg;
1206
1207 assert(p->len >= 3);
1208
1209 nbits = p->header.bitsize;
1210 m = p->len;
1211 n = p->sum[0];
1212 x = bvc_dag_get_var_of_leaf(&c->dag, n);
1213 all_neg = (sign_of_occ(n) != 0);
1214
1215 /*
1216 * Invariant:
1217 * - all_neg means that all node occurrences
1218 * in 0 ... j-1 have negative sign.
1219 * - if all_neg is true, then x is the opposite
1220 * if (sum n0 ... n_{j-1})
1221 * otherwise, x is (sum n0 ... n_{j-1}
1222 */
1223 for (j=1; j<m; j++) {
1224 n = p->sum[j];
1225 y = bvc_dag_get_var_of_leaf(&c->dag, n);
1226 if (all_neg) {
1227 if (sign_of_occ(n) == 0) {
1228 x = bv_compiler_mk_bvsub(c, nbits, y, x);
1229 all_neg = false;
1230 } else {
1231 x = bv_compiler_mk_bvadd(c, nbits, x, y);
1232 }
1233 } else {
1234 if (sign_of_occ(n) == 0) {
1235 x = bv_compiler_mk_bvadd(c, nbits, x, y);
1236 } else {
1237 x = bv_compiler_mk_bvsub(c, nbits, x, y);
1238 }
1239 }
1240 }
1241
1242 if (all_neg) {
1243 x = bv_compiler_mk_bvneg(c, nbits, x);
1244 }
1245
1246 // replace i by [leaf x] in DAG
1247 bvc_dag_convert_to_leaf(&c->dag, i, x);
1248 }
1249
1250
1251 /*
1252 * Process node i:
1253 * - if it's simple, node i is compiled and moved to the list of leaves
1254 * - otherwise, node i is moved to the auxiliary list (in c->dag)
1255 */
bvc_process_node_if_simple(bvc_t * c,bvnode_t i)1256 static void bvc_process_node_if_simple(bvc_t *c, bvnode_t i) {
1257 bvc_dag_t *dag;
1258 bvc_prod_t *p;
1259 bvc_sum_t *s;
1260
1261 dag = &c->dag;
1262 switch (bvc_dag_node_type(dag, i)) {
1263 case BVC_OFFSET:
1264 case BVC_MONO:
1265 break; // skip it
1266
1267 case BVC_PROD:
1268 p = bvc_dag_node_prod(dag, i);
1269 if (bvc_prod_is_simple(dag, p)) {
1270 bvc_process_simple_prod(c, i, p);
1271 return;
1272 }
1273 break;
1274
1275 case BVC_SUM:
1276 s = bvc_dag_node_sum(dag, i);
1277 if (bvc_sum_is_simple(dag, s)) {
1278 bvc_process_simple_sum(c, i, s);
1279 return;
1280 }
1281 break;
1282
1283 case BVC_LEAF:
1284 case BVC_ALIAS:
1285 case BVC_ZERO:
1286 case BVC_CONSTANT:
1287 assert(false);
1288 break;
1289 }
1290
1291 /*
1292 * i not touched: remove it from the complex-node list
1293 */
1294 bvc_move_node_to_aux_list(dag, i);
1295 }
1296
1297
1298
1299 /*
1300 * COMPILATION
1301 */
1302
1303 /*
1304 * Convert all elementary nodes
1305 */
bv_compiler_convert_elem_nodes(bvc_t * c)1306 static void bv_compiler_convert_elem_nodes(bvc_t *c) {
1307 bvnode_t j;
1308
1309 /*
1310 * Note: bvc_process_elem_node removes j from the elementary node list
1311 * so we always get the first element of the leaf list until it's empty
1312 */
1313 for (;;) {
1314 j = bvc_first_elem_node(&c->dag);
1315 if (j < 0) break;
1316 bvc_process_elem_node(c, j);
1317
1318 #if TRACE
1319 printf("\n=== After compiling node n%"PRId32" =====\n", j);
1320 print_bvc_dag(stdout, &c->dag);
1321 fflush(stdout);
1322 #endif
1323 }
1324 }
1325
1326
1327 /*
1328 * Convert all simple nodes
1329 */
bv_compiler_convert_simple_nodes(bvc_t * c)1330 static void bv_compiler_convert_simple_nodes(bvc_t *c) {
1331 bvnode_t j;
1332
1333 for (;;) {
1334 j = bvc_first_complex_node(&c->dag);
1335 if (j < 0) break;
1336 bvc_process_node_if_simple(c, j);
1337
1338 #if TRACE
1339 printf("\n=== After compiling node n%"PRId32" =====\n", j);
1340 print_bvc_dag(stdout, &c->dag);
1341 fflush(stdout);
1342 #endif
1343
1344 }
1345 // move back all aux nodes to the complex list
1346 bvc_move_aux_to_complex_list(&c->dag);
1347 }
1348
1349
1350 /*
1351 * Auxiliary function: create (bvneg x) if it doesn't exist
1352 * already.
1353 * TODO: check for (bvneg (bvneg z)) and other simplifications?
1354 */
bv_compiler_get_bvneg(bvc_t * c,thvar_t x)1355 static thvar_t bv_compiler_get_bvneg(bvc_t *c, thvar_t x) {
1356 thvar_t y;
1357 uint32_t nbits;
1358
1359 assert(0 < x && x < c->vtbl->nvars);
1360 y = find_bvneg(c->vtbl, x);
1361 if (y < 0) {
1362 nbits = bvvar_bitsize(c->vtbl, x);
1363 y = bv_compiler_mk_bvneg(c, nbits, x);
1364 }
1365
1366 return y;
1367 }
1368
1369
1370 /*
1371 * Get the variable y that x is compiled to
1372 * - store the mapping [x --> y] in the cmap
1373 */
bv_compiler_store_mapping(bvc_t * c,thvar_t x)1374 static void bv_compiler_store_mapping(bvc_t *c, thvar_t x) {
1375 back_hmap_elem_t *p;
1376 node_occ_t r;
1377 thvar_t y;
1378 uint32_t sign;
1379
1380 assert(0 < x && x < c->vtbl->nvars);
1381
1382 p = back_hmap_get(&c->cmap, x);
1383 if (p->val >= 0) {
1384 // x is already compiled (to a constant)
1385 assert(p->val != x);
1386 return;
1387 }
1388
1389 r = bvc_dag_nocc_of_var(&c->dag, x); // node occurrence mapped to x
1390 if (bvc_dag_nocc_has_flipped(&c->dag, r)) {
1391 r = negate_occ(r);
1392 }
1393
1394 y = bvc_dag_get_nocc_compilation(&c->dag, r); // r is compiled to y
1395 assert(y >= 0);
1396
1397 /*
1398 * y is a pair (variable + sign)
1399 * if the sign is negative, x is mapped to (bvneg variable)
1400 * if the sign is positive, x is mapped to variable
1401 */
1402 sign = (y & 1);
1403 y >>= 1;
1404 assert(bvvar_bitsize(c->vtbl, x) == bvvar_bitsize(c->vtbl, y));
1405 if (sign != 0) {
1406 y = bv_compiler_get_bvneg(c, y);
1407 }
1408 assert(0 < y && y < c->vtbl->nvars && x != y);
1409 p->val = y;
1410 }
1411
1412
bv_compiler_process_queue(bvc_t * c)1413 void bv_compiler_process_queue(bvc_t *c) {
1414 uint32_t i, n;
1415
1416 // printf("\n=== bv compiler: process-queue: %"PRIu32" variables ===\n", c->vtbl->nvars);
1417 // printf("Initial compile map\n");
1418 // show_cmap(c);
1419
1420 n = c->queue.top;
1421 for (i=0; i<n; i++) {
1422 bv_compiler_map_var_to_dag(c, c->queue.data[i]);
1423 }
1424
1425 #if TRACE
1426 printf("\n==== INIITIAL DAG ====\n");
1427 print_bvc_dag(stdout, &c->dag);
1428 #endif
1429
1430 // try to simplify the DAG nodes using existing elementary expressions
1431 n = c->elemexp.top;
1432 for (i=0; i<n; i++) {
1433 bv_compiler_simplify_dag(c, c->elemexp.data[i]);;
1434 }
1435
1436 // compile the rest until the complex-node list is empty
1437 for (;;) {
1438 bv_compiler_convert_elem_nodes(c);
1439 bv_compiler_convert_simple_nodes(c);
1440 bv_compiler_convert_elem_nodes(c);
1441
1442 assert(bvc_first_elem_node(&c->dag) < 0);
1443 if (bvc_first_complex_node(&c->dag) < 0) break;
1444
1445 #if TRACE
1446 printf("\n==== FORCING ELEM NODES ====\n");
1447 print_bvc_dag(stdout, &c->dag);
1448 fflush(stdout);
1449 #endif
1450
1451 bvc_dag_force_elem_node(&c->dag);
1452
1453 #if TRACE
1454 printf("\n==== AFTER FORCING ====\n");
1455 print_bvc_dag(stdout, &c->dag);
1456 fflush(stdout);
1457 #endif
1458
1459 }
1460
1461
1462 /*
1463 * Collect the compilation results
1464 */
1465 n = c->queue.top;
1466 for (i=0; i<n; i++) {
1467 bv_compiler_store_mapping(c, c->queue.data[i]);
1468 }
1469
1470
1471 /*
1472 * Cleanup
1473 */
1474 reset_bvc_queue(&c->queue);
1475 reset_bvc_dag(&c->dag);
1476 reset_int_bvset(&c->in_queue);
1477
1478 // printf("\n=== done: process-queue: %"PRIu32" variables ===\n", c->vtbl->nvars);
1479 // printf("Final compile map\n");
1480 // show_cmap(c);
1481 }
1482