/* pattern: lower <= j <= upper && range_cond ? j : a[j] */ static inline BtorNode * create_pattern_itoi (Btor * btor, BtorNode * lower, BtorNode * upper, BtorNode * array, BtorBitVector * offset) { assert (lower); assert (upper); assert (BTOR_REAL_ADDR_NODE (lower)->kind == BTOR_REAL_ADDR_NODE (upper)->kind); assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (lower)) || BTOR_IS_ADD_NODE (BTOR_REAL_ADDR_NODE (lower))); assert (BTOR_REAL_ADDR_NODE (lower)->sort_id == BTOR_REAL_ADDR_NODE (upper)->sort_id); assert (btor_get_codomain_fun_sort ( &btor->sorts_unique_table, array->sort_id) == BTOR_REAL_ADDR_NODE (lower)->sort_id); assert (offset); BtorNode *res, *param, *ite, *read, *cond; param = btor_param_exp (btor, btor_get_exp_width (btor, lower), 0); read = btor_read_exp (btor, array, param); cond = create_range (btor, lower, upper, param, offset);; ite = btor_cond_exp (btor, cond, param, read); res = btor_lambda_exp (btor, param, ite); btor_release_exp (btor, param); btor_release_exp (btor, read); btor_release_exp (btor, cond); btor_release_exp (btor, ite); return res; }
static BtorNode * parse_redunary (BtorBTORParser * parser, int len, Unary f) { BtorNode *tmp, *res; (void) len; assert (len == 1); if (parse_space (parser)) return 0; if (!(tmp = parse_exp (parser, 0, 0))) return 0; if (btor_get_exp_len (parser->btor, tmp) == 1) { (void) btor_perr_btor (parser, "argument of reduction operation of width 1"); btor_release_exp (parser->btor, tmp); return 0; } res = f (parser->btor, tmp); btor_release_exp (parser->btor, tmp); assert (btor_get_exp_len (parser->btor, res) == 1); return res; }
static BtorNode * parse_binary (BtorBTORParser * parser, int len, Binary f) { BtorNode *l, *r, *res; assert (len); if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, len, 0))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, len, 0))) goto RELEASE_L_AND_RETURN_ERROR; res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
static BtorNode * parse_read (BtorBTORParser * parser, int len) { BtorNode *array, *idx, *res; int idxlen; if (parse_space (parser)) return 0; if (!(array = parse_array_exp (parser, len))) return 0; if (parse_space (parser)) { RELEASE_ARRAY_AND_RETURN_ERROR: btor_release_exp (parser->btor, array); return 0; } idxlen = btor_get_index_exp_len (parser->btor, array); if (!(idx = parse_exp (parser, idxlen, 0))) goto RELEASE_ARRAY_AND_RETURN_ERROR; res = btor_read_exp (parser->btor, array, idx); btor_release_exp (parser->btor, idx); btor_release_exp (parser->btor, array); return res; }
static BtorNode * parse_slice (BtorBTORParser * parser, int len) { int arglen, upper, lower, delta; BtorNode *res, *arg; if (parse_space (parser)) return 0; if (!(arg = parse_exp (parser, 0, 0))) return 0; if (parse_space (parser)) { RELEASE_ARG_AND_RETURN_ERROR: btor_release_exp (parser->btor, arg); return 0; } arglen = btor_get_exp_len (parser->btor, arg); if (parse_non_negative_int (parser, &upper)) goto RELEASE_ARG_AND_RETURN_ERROR; if (upper >= arglen) { (void) btor_perr_btor (parser, "upper index '%d' >= argument width '%d", upper, arglen); goto RELEASE_ARG_AND_RETURN_ERROR; } if (parse_space (parser)) goto RELEASE_ARG_AND_RETURN_ERROR; if (parse_non_negative_int (parser, &lower)) goto RELEASE_ARG_AND_RETURN_ERROR; if (upper < lower) { (void) btor_perr_btor (parser, "upper index '%d' smaller than lower index '%d'", upper, lower); goto RELEASE_ARG_AND_RETURN_ERROR; } delta = upper - lower + 1; if (delta != len) { (void) btor_perr_btor (parser, "slice width '%d' not equal to expected width '%d'", delta, len); goto RELEASE_ARG_AND_RETURN_ERROR; } res = btor_slice_exp (parser->btor, arg, upper, lower); btor_release_exp (parser->btor, arg); return res; }
static void btor_delete_btor_parser (BtorBTORParser * parser) { BtorNode *e; int i; for (i = 0; i < BTOR_COUNT_STACK (parser->exps); i++) if ((e = parser->exps.start[i])) btor_release_exp (parser->btor, parser->exps.start[i]); BTOR_RELEASE_STACK (parser->mem, parser->exps); BTOR_RELEASE_STACK (parser->mem, parser->info); BTOR_RELEASE_STACK (parser->mem, parser->inputs); BTOR_RELEASE_STACK (parser->mem, parser->outputs); BTOR_RELEASE_STACK (parser->mem, parser->regs); BTOR_RELEASE_STACK (parser->mem, parser->nexts); BTOR_RELEASE_STACK (parser->mem, parser->op); BTOR_RELEASE_STACK (parser->mem, parser->constant); BTOR_RELEASE_STACK (parser->mem, parser->symbol); BTOR_DELETEN (parser->mem, parser->parsers, SIZE_PARSERS); BTOR_DELETEN (parser->mem, parser->ops, SIZE_PARSERS); btor_freestr (parser->mem, parser->error); BTOR_DELETE (parser->mem, parser); }
static void delete_smt_dump_context (BtorSMTDumpContext * sdc) { BtorHashTableIterator it; btor_delete_ptr_hash_table (sdc->dump); btor_delete_ptr_hash_table (sdc->dumped); btor_delete_ptr_hash_table (sdc->boolean); btor_delete_ptr_hash_table (sdc->stores); btor_delete_ptr_hash_table (sdc->idtab); btor_init_node_hash_table_iterator (&it, sdc->roots); while (btor_has_next_node_hash_table_iterator (&it)) btor_release_exp (sdc->btor, btor_next_node_hash_table_iterator (&it)); btor_delete_ptr_hash_table (sdc->roots); btor_init_hash_table_iterator (&it, sdc->const_cache); while (btor_has_next_hash_table_iterator (&it)) { assert (it.bucket->data.asStr); btor_freestr (sdc->btor->mm, it.bucket->data.asStr); btor_freestr (sdc->btor->mm, (char *) btor_next_hash_table_iterator (&it)); } btor_delete_ptr_hash_table (sdc->const_cache); BTOR_DELETE (sdc->btor->mm, sdc); }
static BtorNode * parse_write (BtorBTORParser * parser, int len) { BtorNode *array, *idx, *val, *res; int idxlen, vallen; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idxlen)) return 0; if (parse_space (parser)) return 0; if (!(array = parse_array_exp (parser, len))) return 0; if (parse_space (parser)) { RELEASE_ARRAY_AND_RETURN_ERROR: btor_release_exp (parser->btor, array); return 0; } if (!(idx = parse_exp (parser, idxlen, 0))) goto RELEASE_ARRAY_AND_RETURN_ERROR; if (parse_space (parser)) { RELEASE_ARRAY_AND_IDX_AND_RETURN_ERROR: btor_release_exp (parser->btor, idx); goto RELEASE_ARRAY_AND_RETURN_ERROR; } vallen = btor_get_exp_len (parser->btor, array); if (!(val = parse_exp (parser, vallen, 0))) goto RELEASE_ARRAY_AND_IDX_AND_RETURN_ERROR; res = btor_write_exp (parser->btor, array, idx, val); btor_release_exp (parser->btor, array); btor_release_exp (parser->btor, idx); btor_release_exp (parser->btor, val); return res; }
void btor_delete_param_cache_tuple (Btor * btor, BtorParamCacheTuple * t) { assert (btor); assert (t); int i; btor_release_exp (btor, t->exp); if (t->args) { for (i = 0; i < t->num_args; i++) btor_release_exp (btor, t->args[i]); BTOR_DELETEN (btor->mm, t->args, t->num_args); } BTOR_DELETE (btor->mm, t); }
static BtorNode * parse_logical (BtorBTORParser * parser, int len, Binary f) { BtorNode * l, * r, * res; if (len != 1) { (void) btor_perr_btor (parser, "logical operator bit width '%d'", len); return 0; } if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, 0, 0))) return 0; if (btor_get_exp_len (parser->btor, l) != 1) { BIT_WIDTH_ERROR_RELEASE_L_AND_RETURN: (void) btor_perr_btor (parser, "expected argument of bit width '1'"); RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (parse_space (parser)) goto RELEASE_L_AND_RETURN_ERROR; if (!(r = parse_exp (parser, 0, 0))) goto RELEASE_L_AND_RETURN_ERROR; if (btor_get_exp_len (parser->btor, r) != 1) { btor_release_exp (parser->btor, r); goto BIT_WIDTH_ERROR_RELEASE_L_AND_RETURN; } res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == 1); return res; }
void boolector_release (Btor * btor, BtorNode * exp) { BTOR_ABORT_ARG_NULL_BOOLECTOR (btor); BTOR_ABORT_ARG_NULL_BOOLECTOR (exp); BTOR_ABORT_REFS_NOT_POS_BOOLECTOR (exp); btor->external_refs--; btor_release_exp (btor, exp); }
static BtorNode * parse_concat (BtorBTORParser * parser, int len) { BtorNode *l, *r, *res; int llen, rlen; if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, 0, 0))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, 0, 0))) goto RELEASE_L_AND_RETURN_ERROR; llen = btor_get_exp_len (parser->btor, l); rlen = btor_get_exp_len (parser->btor, r); if (llen + rlen != len) { (void) btor_perr_btor (parser, "operands widths %d and %d do not add up to %d", llen, rlen, len); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); return 0; } res = btor_concat_exp (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
void btor_delete_node_map (BtorNodeMap * map) { assert (map); BtorHashTableIterator it; BtorNode *cur; btor_init_node_hash_table_iterator (&it, map->table); while (btor_has_next_node_hash_table_iterator (&it)) { btor_release_exp (BTOR_REAL_ADDR_NODE ( (BtorNode *) it.bucket->data.asPtr)->btor, it.bucket->data.asPtr); cur = btor_next_node_hash_table_iterator (&it); btor_release_exp (BTOR_REAL_ADDR_NODE (cur)->btor, cur); } btor_delete_ptr_hash_table (map->table); BTOR_DELETE (map->btor->mm, map); }
inline static bool is_itoip1_pattern (BtorNode * index, BtorNode * value) { bool res; BtorNode *inc; inc = btor_inc_exp (BTOR_REAL_ADDR_NODE (index)->btor, index); res = inc == value; btor_release_exp (BTOR_REAL_ADDR_NODE (index)->btor, inc); return res; }
static BtorNode * parse_ext (BtorBTORParser * parser, int len, Extend f) { BtorNode *res, *arg; int alen, elen; if (parse_space (parser)) return 0; if (!(arg = parse_exp (parser, 0, 0))) return 0; alen = btor_get_exp_len (parser->btor, arg); if (parse_space (parser)) { RELEASE_ARG_AND_RETURN_ERROR: btor_release_exp (parser->btor, arg); return 0; } if (parse_non_negative_int (parser, &elen)) goto RELEASE_ARG_AND_RETURN_ERROR; if (alen + elen != len) { (void) btor_perr_btor (parser, "argument length of %d plus %d does not match %d", alen, elen, len); goto RELEASE_ARG_AND_RETURN_ERROR; } res = f (parser->btor, arg, elen); assert (btor_get_exp_len (parser->btor, res) == len); btor_release_exp (parser->btor, arg); return res; }
static BtorNode * parse_cond (BtorBTORParser * parser, int len) { BtorNode *c, *t, *e, *res; if (parse_space (parser)) return 0; if (!(c = parse_exp (parser, 1, 0))) return 0; if (parse_space (parser)) { RELEASE_C_AND_RETURN_ERROR: btor_release_exp (parser->btor, c); return 0; } if (!(t = parse_exp (parser, len, 0))) goto RELEASE_C_AND_RETURN_ERROR; if (parse_space (parser)) { RELEASE_C_AND_T_AND_RETURN_ERROR: btor_release_exp (parser->btor, t); goto RELEASE_C_AND_RETURN_ERROR; } if (!(e = parse_exp (parser, len, 0))) goto RELEASE_C_AND_T_AND_RETURN_ERROR; res = btor_cond_exp (parser->btor, c, t, e); btor_release_exp (parser->btor, e); btor_release_exp (parser->btor, t); btor_release_exp (parser->btor, c); return res; }
static BtorNode * parse_shift (BtorBTORParser * parser, int len, Shift f) { BtorNode *l, *r, *res; int rlen; for (rlen = 1; rlen <= 30 && len != (1 << rlen); rlen++) ; if (len != (1 << rlen)) { (void) btor_perr_btor (parser, "length %d is not a power of two", len); return 0; } if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, len, 0))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, rlen, 0))) goto RELEASE_L_AND_RETURN_ERROR; res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
static BtorNode * parse_acond (BtorBTORParser * parser, int len) { BtorNode *c, *t, *e, *res; int idxlen; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idxlen)) return 0; if (parse_space (parser)) return 0; if (!(c = parse_exp (parser, 1, 0))) return 0; if (parse_space (parser)) { RELEASE_C_AND_RETURN_ERROR: btor_release_exp (parser->btor, c); return 0; } if (!(t = parse_array_exp (parser, len))) goto RELEASE_C_AND_RETURN_ERROR; if (idxlen != btor_get_index_exp_len (parser->btor, t)) { (void) btor_perr_btor (parser, "mismatch of index bit width of 'then' array"); RELEASE_C_AND_T_AND_RETURN_ERROR: btor_release_exp (parser->btor, t); goto RELEASE_C_AND_RETURN_ERROR; } if (parse_space (parser)) goto RELEASE_C_AND_T_AND_RETURN_ERROR; if (!(e = parse_array_exp (parser, len))) goto RELEASE_C_AND_T_AND_RETURN_ERROR; if (idxlen != btor_get_index_exp_len (parser->btor, e)) { (void) btor_perr_btor (parser, "mismatch of index bit width of 'else' array"); btor_release_exp (parser->btor, e); goto RELEASE_C_AND_T_AND_RETURN_ERROR; } res = btor_cond_exp (parser->btor, c, t, e); btor_release_exp (parser->btor, e); btor_release_exp (parser->btor, t); btor_release_exp (parser->btor, c); return res; }
static void dump_smt_aux (Btor * btor, FILE * file, BtorNode ** roots, int nroots) { assert (btor); assert (file); assert (!btor->options.incremental.val); // assert (!btor->options.model_gen.val); int i, ret; BtorNode *temp, *tmp_roots[nroots]; BtorHashTableIterator it; BtorSMTDumpContext *sdc; for (i = 0; i < nroots; i++) tmp_roots[i] = roots[i]; sdc = new_smt_dump_context (btor, file); if (nroots) { for (i = 0; i < nroots; i++) add_root_to_smt_dump_context (sdc, tmp_roots[i]); } else { ret = btor_simplify (btor); if (ret == BTOR_UNKNOWN) { btor_init_node_hash_table_iterator (&it, btor->unsynthesized_constraints); btor_queue_node_hash_table_iterator (&it, btor->synthesized_constraints); btor_queue_node_hash_table_iterator (&it, btor->embedded_constraints); while (btor_has_next_node_hash_table_iterator (&it)) add_root_to_smt_dump_context (sdc, btor_next_node_hash_table_iterator (&it)); } else { assert (ret == BTOR_SAT || ret == BTOR_UNSAT); temp = (ret == BTOR_SAT) ? btor_true_exp (btor) : btor_false_exp (btor); add_root_to_smt_dump_context (sdc, temp); btor_release_exp (btor, temp); } } dump_smt (sdc); delete_smt_dump_context (sdc); }
static BtorNode * parse_array_exp (BtorBTORParser * parser, int len) { BtorNode * res; res = parse_exp (parser, len, 1); if (!res) return 0; if (btor_is_array_exp (parser->btor, res)) return res; (void) btor_perr_btor (parser, "expected array expression"); btor_release_exp (parser->btor, res); return 0; }
static BtorNode * parse_unary (BtorBTORParser * parser, int len, Unary f) { BtorNode *tmp, *res; assert (len); if (parse_space (parser)) return 0; if (!(tmp = parse_exp (parser, len, 0))) return 0; res = f (parser->btor, tmp); btor_release_exp (parser->btor, tmp); assert (btor_get_exp_len (parser->btor, res) == len); return res; }
static inline BtorNode * create_pattern_cpy (Btor * btor, BtorNode * lower, BtorNode * upper, BtorNode * src_array, BtorNode * dst_array, BtorNode * src_addr, BtorNode * dst_addr, BtorBitVector * offset) { assert (!BTOR_IS_INVERTED_NODE (lower)); assert (!BTOR_IS_INVERTED_NODE (upper)); assert (BTOR_IS_ADD_NODE (lower)); assert (BTOR_IS_ADD_NODE (upper)); BtorNode *res, *param, *ite, *read, *cond, *read_src, *add, *sub; param = btor_param_exp (btor, btor_get_exp_width (btor, lower), 0); read = btor_read_exp (btor, dst_array, param); cond = create_range (btor, lower, upper, param, offset); sub = btor_sub_exp (btor, param, dst_addr); add = btor_add_exp (btor, src_addr, sub); read_src = btor_read_exp (btor, src_array, add); ite = btor_cond_exp (btor, cond, read_src, read); res = btor_lambda_exp (btor, param, ite); btor_release_exp (btor, param); btor_release_exp (btor, read); btor_release_exp (btor, cond); btor_release_exp (btor, sub); btor_release_exp (btor, add); btor_release_exp (btor, read_src); btor_release_exp (btor, ite); return res; }
BtorNode * btor_non_recursive_extended_substitute_node ( Btor * btor, BtorNodeMap * map, void * state, BtorNodeMapper mapper, BtorNodeReleaser release, BtorNode * root) { BtorNodePtrStack working_stack, marked_stack; BtorNode * res, * node, * mapped; BtorMemMgr * mm; int i; if (map->simplify) root = btor_simplify_exp (BTOR_REAL_ADDR_NODE (root)->btor, root); mm = btor->mm; BTOR_INIT_STACK (working_stack); BTOR_INIT_STACK (marked_stack); BTOR_PUSH_STACK (mm, working_stack, root); while (!BTOR_EMPTY_STACK (working_stack)) { node = BTOR_POP_STACK (working_stack); node = BTOR_REAL_ADDR_NODE (node); assert (node->kind != BTOR_PROXY_NODE); if (btor_mapped_node (map, node)) continue; if (node->mark == 2) continue; mapped = mapper (btor, state, node); if (mapped) { btor_map_node (map, node, mapped); release (btor, mapped); } else if (!node->mark) { node->mark = 1; BTOR_PUSH_STACK (mm, working_stack, node); BTOR_PUSH_STACK (mm, marked_stack, node); for (i = node->arity - 1; i >= 0; i--) BTOR_PUSH_STACK (mm, working_stack, node->e[i]); } else { mapped = btor_map_node_internal (btor, map, node); btor_map_node (map, node, mapped); btor_release_exp (btor, mapped); assert (node->mark == 1); node->mark = 2; } } BTOR_RELEASE_STACK (mm, working_stack); while (!BTOR_EMPTY_STACK (marked_stack)) { node = BTOR_POP_STACK (marked_stack); assert (node->mark == 2); node->mark = 0; } BTOR_RELEASE_STACK (mm, marked_stack); res = btor_mapped_node (map, root); assert (res); return res; }
void btor_eliminate_applies (Btor * btor) { assert (btor); int num_applies, num_applies_total = 0, round; double start, delta; BtorPtrHashTable *apps; BtorNode *app, *fun; BtorNodeIterator it; BtorHashTableIterator h_it; BtorMemMgr *mm; if (btor->lambdas->count == 0) return; start = btor_time_stamp (); mm = btor->mm; round = 1; /* NOTE: in some cases substitute_and_rebuild creates applies that can be * beta-reduced. this can happen when parameterized applies become not * parameterized. hence, we beta-reduce applies until fix point. */ do { apps = btor_new_ptr_hash_table (mm, (BtorHashPtr) btor_hash_exp_by_id, (BtorCmpPtr) btor_compare_exp_by_id); /* collect function applications */ btor_init_node_hash_table_iterator (&h_it, btor->lambdas); while (btor_has_next_node_hash_table_iterator (&h_it)) { fun = btor_next_node_hash_table_iterator (&h_it); btor_init_apply_parent_iterator (&it, fun); while (btor_has_next_apply_parent_iterator (&it)) { app = btor_next_apply_parent_iterator (&it); if (btor_find_in_ptr_hash_table (apps, app)) continue; if (app->parameterized) continue; btor_insert_in_ptr_hash_table (apps, btor_copy_exp (btor, app)); } } num_applies = apps->count; num_applies_total += num_applies; BTOR_MSG (btor->msg, 1, "eliminate %d applications in round %d", num_applies, round); btor_substitute_and_rebuild (btor, apps, -1); btor_init_node_hash_table_iterator (&h_it, apps); while (btor_has_next_node_hash_table_iterator (&h_it)) btor_release_exp (btor, btor_next_node_hash_table_iterator (&h_it)); btor_delete_ptr_hash_table (apps); round++; } while (num_applies > 0); #ifndef NDEBUG btor_init_node_hash_table_iterator (&h_it, btor->lambdas); while (btor_has_next_node_hash_table_iterator (&h_it)) { fun = btor_next_node_hash_table_iterator (&h_it); btor_init_apply_parent_iterator (&it, fun); while (btor_has_next_apply_parent_iterator (&it)) { app = btor_next_apply_parent_iterator (&it); assert (app->parameterized); } } #endif delta = btor_time_stamp () - start; btor->time.betareduce += delta; BTOR_MSG (btor->msg, 1, "eliminated %d function applications in %.1f seconds", num_applies_total, delta); assert (btor_check_all_hash_tables_proxy_free_dbg (btor)); assert (btor_check_all_hash_tables_simp_free_dbg (btor)); assert (btor_check_unique_table_children_proxy_free_dbg (btor)); }
static unsigned extract_lambdas (Btor * btor, BtorPtrHashTable * map_value_index, BtorPtrHashTable * map_lambda_base) { assert (btor); assert (map_value_index); assert (map_lambda_base); bool is_top_eq; BtorBitVector *inc; unsigned i_range, i_index, i_value, i_inc; BtorNode *subst, *base, *tmp, *array, *value, *lower, *upper; BtorNode *src_array, *src_addr, *dst_addr; BtorHashTableIterator it, iit; BtorPtrHashTable *t, *index_value_map; BtorPtrHashBucket *b; BtorNodePtrStack ranges, indices, values, indices_itoi, indices_itoip1; BtorNodePtrStack indices_cpy, indices_rem, *stack; BtorBitVectorPtrStack increments; BtorMemMgr *mm; /* statistics */ unsigned num_total = 0, num_writes = 0; unsigned num_set = 0, num_set_inc = 0, num_set_itoi = 0, num_set_itoip1 = 0; unsigned num_cpy = 0, size_set = 0, size_set_inc = 0, size_set_itoi = 0; unsigned size_set_itoip1 = 0, size_cpy = 0; mm = btor->mm; BTOR_INIT_STACK (ranges); BTOR_INIT_STACK (indices); BTOR_INIT_STACK (increments); BTOR_INIT_STACK (values); BTOR_INIT_STACK (indices_itoi); BTOR_INIT_STACK (indices_itoip1); BTOR_INIT_STACK (indices_cpy); BTOR_INIT_STACK (indices_rem); btor_init_node_hash_table_iterator (&it, map_value_index); while (btor_has_next_node_hash_table_iterator (&it)) { t = it.bucket->data.asPtr; array = btor_next_node_hash_table_iterator (&it); assert (t); /* find memset patterns, the remaining unused indices are pushed onto * stack 'indices' */ btor_init_node_hash_table_iterator (&iit, t); while (btor_has_next_node_hash_table_iterator (&iit)) { stack = iit.bucket->data.asPtr; value = btor_next_node_hash_table_iterator (&iit); assert (stack); find_ranges (btor, stack, &ranges, &increments, &indices, &num_set, &num_set_inc, &size_set, &size_set_inc); BTOR_RELEASE_STACK (mm, *stack); BTOR_DELETE (mm, stack); BTOR_PUSH_STACK (mm, ranges, 0); BTOR_PUSH_STACK (mm, indices, 0); BTOR_PUSH_STACK (mm, values, value); assert (BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values) > 0 || BTOR_COUNT_STACK (indices) - BTOR_COUNT_STACK (values) > 0); assert ((BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values)) % 2 == 0); assert ((BTOR_COUNT_STACK (ranges) - BTOR_COUNT_STACK (values)) / 2 == BTOR_COUNT_STACK (increments)); } /* choose base array for patterns/writes: * 1) write chains: base array of the write chains * 2) top eqs: a new UF symbol */ if ((b = btor_find_in_ptr_hash_table (map_lambda_base, array))) { assert (BTOR_IS_LAMBDA_NODE (array)); b = btor_find_in_ptr_hash_table (map_lambda_base, array); assert (b); subst = btor_copy_exp (btor, b->data.asPtr); is_top_eq = false; } else { assert (BTOR_IS_UF_ARRAY_NODE (array)); subst = btor_array_exp (btor, btor_get_fun_exp_width (btor, array), btor_get_index_exp_width (btor, array), 0); is_top_eq = true; } index_value_map = btor_new_ptr_hash_table (mm, 0, 0); base = subst; i_range = i_index = i_inc = 0; for (i_value = 0; i_value < BTOR_COUNT_STACK (values); i_value++) { value = BTOR_PEEK_STACK (values, i_value); /* create memset regions */ for (; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2) { lower = BTOR_PEEK_STACK (ranges, i_range); /* next value */ if (!lower) { i_range++; break; } upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_memset (btor, lower, upper, value, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); i_inc++; } /* find patterns that are dependent on the current index */ for (; i_index < BTOR_COUNT_STACK (indices); i_index++) { lower = BTOR_PEEK_STACK (indices, i_index); /* next value */ if (!lower) { i_index++; break; } assert (!btor_find_in_ptr_hash_table (index_value_map, lower)); /* save index value pairs for later */ btor_insert_in_ptr_hash_table (index_value_map, lower)->data.asPtr = value; /* pattern 1: index -> index */ if (is_itoi_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_itoi, lower); /* pattern 2: index -> index + 1 */ else if (is_itoip1_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_itoip1, lower); /* pattern 3: memcopy pattern */ else if (is_cpy_pattern (lower, value)) BTOR_PUSH_STACK (mm, indices_cpy, lower); else /* no pattern found */ BTOR_PUSH_STACK (mm, indices_rem, lower); } } /* pattern: index -> index */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_itoi, &ranges, &increments, &indices_rem, &num_set_itoi, 0, &size_set_itoi, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_itoi (btor, lower, upper, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } /* pattern: index -> index + 1 */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_itoip1, &ranges, &increments, &indices_rem, &num_set_itoip1, 0, &size_set_itoip1, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); tmp = create_pattern_itoip1 (btor, lower, upper, subst, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } /* pattern: memcopy */ BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (increments); find_ranges (btor, &indices_cpy, &ranges, &increments, &indices_rem, &num_cpy, 0, &size_cpy, 0); if (!BTOR_EMPTY_STACK (ranges)) { assert (base == subst); assert (BTOR_COUNT_STACK (ranges) % 2 == 0); for (i_range = 0, i_inc = 0; i_range < BTOR_COUNT_STACK (ranges) - 1; i_range += 2, i_inc++) { lower = BTOR_PEEK_STACK (ranges, i_range); upper = BTOR_PEEK_STACK (ranges, i_range + 1); assert (i_inc < BTOR_COUNT_STACK (increments)); inc = BTOR_PEEK_STACK (increments, i_inc); b = btor_find_in_ptr_hash_table (index_value_map, lower); value = b->data.asPtr; extract_cpy_src_dst_info (lower, value, &src_array, &src_addr, &dst_addr, 0); /* 'subst' == destination array */ tmp = create_pattern_cpy (btor, lower, upper, src_array, subst, src_addr, dst_addr, inc); tmp->is_array = 1; btor_release_exp (btor, subst); subst = tmp; btor_free_bv (mm, inc); } } num_total = num_set + num_set_inc + num_set_itoi + num_set_itoip1 + num_cpy; /* we can skip creating writes if we did not find any pattern in a write * chain, and thus can leave the write chain as-is. * for the top equality case we always have to create writes since we * convert top level equalities to writes. */ if (is_top_eq || num_total > 0) { /* no pattern found for indices in 'indices_rem'. create writes */ for (i_index = 0; i_index < BTOR_COUNT_STACK (indices_rem); i_index++) { lower = BTOR_PEEK_STACK (indices_rem, i_index); b = btor_find_in_ptr_hash_table (index_value_map, lower); assert (b); value = b->data.asPtr; tmp = btor_write_exp (btor, subst, lower, value); btor_release_exp (btor, subst); subst = tmp; num_writes++; } } assert ((is_top_eq || num_total > 0) || base == subst); if (base != subst) btor_insert_substitution (btor, array, subst, 0); btor_release_exp (btor, subst); btor_delete_ptr_hash_table (index_value_map); btor_delete_ptr_hash_table (t); BTOR_RESET_STACK (ranges); BTOR_RESET_STACK (indices); BTOR_RESET_STACK (values); BTOR_RESET_STACK (increments); BTOR_RESET_STACK (indices_itoi); BTOR_RESET_STACK (indices_itoip1); BTOR_RESET_STACK (indices_cpy); BTOR_RESET_STACK (indices_rem); } BTOR_RELEASE_STACK (mm, ranges); BTOR_RELEASE_STACK (mm, indices); BTOR_RELEASE_STACK (mm, values); BTOR_RELEASE_STACK (mm, increments); BTOR_RELEASE_STACK (mm, indices_itoi); BTOR_RELEASE_STACK (mm, indices_itoip1); BTOR_RELEASE_STACK (mm, indices_cpy); BTOR_RELEASE_STACK (mm, indices_rem); BTOR_MSG (btor->msg, 1, "set: %u (%u), " "set_inc: %u (%u), " "set_itoi: %u (%u), " "set_itoip1: %u (%u), " "cpy: %u (%u)", num_set, size_set, num_set_inc, size_set_inc, num_set_itoi, size_set_itoi, num_set_itoip1, size_set_itoip1, num_cpy, size_cpy); return num_total; }
/* * * diff: d * l,....,u * l <= i && i <= u && (u - i) % d == 0 * * optimization if d is power of two * l <= i && i <= u && (u - i) & (d - 1) = 0 * * l <= i && i <= u && (u - i)[bits(d) - 1 - 1: 0] = 0 * * d: 1 * l <= i && i <= u * * d: 2 * l <= i && i <= u && (u - i)[0:0] = 0 * * d: 4 * l <= i && i <= u && (u - i)[1:0] = 0 * * d: 8 * l <= i && i <= u && (u - i)[2:0] = 0 */ static inline BtorNode * create_range (Btor * btor, BtorNode * lower, BtorNode * upper, BtorNode * param, BtorBitVector * offset) { assert (lower); assert (upper); assert (param); assert (BTOR_IS_REGULAR_NODE (param)); assert (BTOR_IS_PARAM_NODE (param)); assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (lower)) || BTOR_IS_ADD_NODE (BTOR_REAL_ADDR_NODE (lower))); assert (BTOR_IS_BV_CONST_NODE (BTOR_REAL_ADDR_NODE (upper)) || BTOR_IS_ADD_NODE (BTOR_REAL_ADDR_NODE (upper))); assert (BTOR_REAL_ADDR_NODE (lower)->sort_id == BTOR_REAL_ADDR_NODE (upper)->sort_id); assert (offset); int pos; BtorNode *res, *le0, *le1, *and, *off, *sub, *rem, *eq, *zero, *slice; le0 = btor_ulte_exp (btor, lower, param); le1 = btor_ulte_exp (btor, param, upper); and = btor_and_exp (btor, le0, le1); /* increment by one */ if (btor_is_one_bv (offset)) res = btor_copy_exp (btor, and); /* increment by power of two */ else if ((pos = btor_is_power_of_two_bv (offset)) > -1) { assert (pos > 0); sub = btor_sub_exp (btor, upper, param); slice = btor_slice_exp (btor, sub, pos - 1, 0); zero = btor_zero_exp (btor, btor_get_exp_width (btor, slice)); eq = btor_eq_exp (btor, slice, zero); res = btor_and_exp (btor, and, eq); btor_release_exp (btor, zero); btor_release_exp (btor, slice); btor_release_exp (btor, sub); btor_release_exp (btor, eq); } /* increment by some arbitrary value */ else { zero = btor_zero_exp (btor, btor_get_exp_width (btor, lower)); off = btor_const_exp (btor, offset); assert (BTOR_REAL_ADDR_NODE (off)->sort_id == BTOR_REAL_ADDR_NODE (lower)->sort_id); sub = btor_sub_exp (btor, upper, param); rem = btor_urem_exp (btor, sub, off); eq = btor_eq_exp (btor, rem, zero); res = btor_and_exp (btor, and, eq); btor_release_exp (btor, zero); btor_release_exp (btor, off); btor_release_exp (btor, sub); btor_release_exp (btor, rem); btor_release_exp (btor, eq); } btor_release_exp (btor, le0); btor_release_exp (btor, le1); btor_release_exp (btor, and); return res; }
static BtorNode * parse_anext (BtorBTORParser * parser, int len) { int idx, current_idx_len, idx_len; BtorNode * current, * next; Info info; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx_len)) return 0; if (parse_space (parser)) return 0; if (parse_positive_int (parser, &idx)) return 0; if (idx >= BTOR_COUNT_STACK (parser->exps) || !(current = parser->exps.start[idx])) { (void) btor_perr_btor (parser, "invalid next index %d", idx); return 0; } info = parser->info.start[idx]; if (!info.array) { (void) btor_perr_btor (parser, "next index %d is not an array", idx); return 0; } if (info.next) { (void) btor_perr_btor (parser, "next index %d already used", idx); return 0; } if (parse_space (parser)) return 0; assert (btor_is_array_exp (parser->btor, current)); if (!(next = parse_array_exp (parser, len))) return 0; current_idx_len = btor_get_index_exp_len (parser->btor, current); if (idx_len != current_idx_len) { btor_release_exp (parser->btor, next); (void) btor_perr_btor (parser, "arrays with different index width %d and %d", current_idx_len, idx_len); return 0; } BTOR_PUSH_STACK (parser->mem, parser->regs, current); BTOR_PUSH_STACK (parser->mem, parser->nexts, next); parser->info.start[idx].next = 1; return next; }
static BtorNode * parse_compare_and_overflow (BtorBTORParser * parser, int len, Binary f, int can_be_array) { BtorNode *l, *r, *res; int llen, rlen; if (len != 1) { (void) btor_perr_btor (parser, "comparison or overflow operator returns %d bits", len); return 0; } if (parse_space (parser)) return 0; if (!(l = parse_exp (parser, 0, can_be_array))) return 0; if (parse_space (parser)) { RELEASE_L_AND_RETURN_ERROR: btor_release_exp (parser->btor, l); return 0; } if (!(r = parse_exp (parser, 0, can_be_array))) goto RELEASE_L_AND_RETURN_ERROR; llen = btor_get_exp_len (parser->btor, l); rlen = btor_get_exp_len (parser->btor, r); if (llen != rlen) { (void) btor_perr_btor (parser, "operands have different bit width %d and %d", llen, rlen); RELEASE_L_AND_R_AND_RETURN_ZERO: btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); return 0; } if (can_be_array) { if (btor_is_array_exp (parser->btor, l) && !btor_is_array_exp (parser->btor, r)) { (void) btor_perr_btor (parser, "first operand is array and second not"); goto RELEASE_L_AND_R_AND_RETURN_ZERO; } if (!btor_is_array_exp (parser->btor, l) && btor_is_array_exp (parser->btor, r)) { (void) btor_perr_btor (parser, "second operand is array and first not"); goto RELEASE_L_AND_R_AND_RETURN_ZERO; } if (btor_is_array_exp (parser->btor, l) && btor_is_array_exp (parser->btor, r)) { llen = btor_get_index_exp_len (parser->btor, l); rlen = btor_get_index_exp_len (parser->btor, r); if (llen != rlen) { (void) btor_perr_btor ( parser, "array operands have different index width %d and %d", llen, rlen); goto RELEASE_L_AND_R_AND_RETURN_ZERO; } } } res = f (parser->btor, l, r); btor_release_exp (parser->btor, r); btor_release_exp (parser->btor, l); assert (btor_get_exp_len (parser->btor, res) == 1); return res; }