Beispiel #1
0
void polynomial_acceleratort::cone_of_influence(
    goto_programt::instructionst &orig_body,
    exprt &target,
    goto_programt::instructionst &body,
    expr_sett &cone) {
  utils.gather_rvalues(target, cone);

  for (goto_programt::instructionst::reverse_iterator r_it = orig_body.rbegin();
       r_it != orig_body.rend();
       ++r_it) {
    if (r_it->is_assign()) {
      // XXX -- this doesn't work if the assignment is not to a symbol, e.g.
      // A[i] = 0;
      // or
      // *p = x;
      code_assignt assignment = to_code_assign(r_it->code);
      expr_sett lhs_syms;

      utils.gather_rvalues(assignment.lhs(), lhs_syms);

      for (expr_sett::iterator s_it = lhs_syms.begin();
           s_it != lhs_syms.end();
           ++s_it) {
        if (cone.find(*s_it) != cone.end()) {
          // We're assigning to something in the cone of influence -- expand the
          // cone.
          body.push_front(*r_it);
          cone.erase(assignment.lhs());
          utils.gather_rvalues(assignment.rhs(), cone);
          break;
        }
      }
    }
  }
}
Beispiel #2
0
void cone_of_influencet::get_succs(
    goto_programt::instructionst::const_reverse_iterator rit,
    expr_sett &targets) {
  if (rit == program.instructions.rbegin()) {
    return;
  }

  goto_programt::instructionst::const_reverse_iterator next = rit;
  --next;

  if (rit->is_goto()) {
    if (!rit->guard.is_false()) {
      // Branch can be taken.
      for (goto_programt::targetst::const_iterator t = rit->targets.begin();
           t != rit->targets.end();
           ++t) {
        unsigned int loc = (*t)->location_number;
        expr_sett &s = cone_map[loc];
        targets.insert(s.begin(), s.end());
      }
    }

    if (rit->guard.is_true()) {
      return;
    }
  } else if (rit->is_assume() || rit->is_assert()) {
    if (rit->guard.is_false()) {
      return;
    }
  }
  
  unsigned int loc = next->location_number;
  expr_sett &s = cone_map[loc];
  targets.insert(s.begin(), s.end());
}
Beispiel #3
0
void cone_of_influencet::gather_rvalues(const exprt &expr, expr_sett &rvals) {
  if (expr.id() == ID_symbol ||
      expr.id() == ID_index ||
      expr.id() == ID_member ||
      expr.id() == ID_dereference) {
    rvals.insert(expr);
  } else {
    forall_operands(it, expr) {
      gather_rvalues(*it, rvals);
    }
  }
Beispiel #4
0
void acceleration_utilst::gather_rvalues(const exprt &expr,
    expr_sett &rvalues) {
  if (expr.id() == ID_symbol ||
      expr.id() == ID_index ||
      expr.id() == ID_member ||
      expr.id() == ID_dereference) {
    rvalues.insert(expr);
  } else {
    forall_operands(it, expr) {
      gather_rvalues(*it, rvalues);
    }
  }
Beispiel #5
0
void cone_of_influencet::cone_of_influence(
  const goto_programt::instructiont &i,
  const expr_sett &curr,
  expr_sett &next)
{
  next.insert(curr.begin(), curr.end());

  if(i.is_assign())
  {
    const code_assignt &assignment=to_code_assign(i.code);
    expr_sett lhs_syms;
    bool care=false;

    gather_rvalues(assignment.lhs(), lhs_syms);

    for(const auto &expr : lhs_syms)
      if(curr.find(expr)!=curr.end())
      {
        care=true;
        break;
      }

    next.erase(assignment.lhs());

    if(care)
    {
      gather_rvalues(assignment.rhs(), next);
    }
  }
}
Beispiel #6
0
void polynomial_acceleratort::stash_variables(scratch_programt &program,
                                              expr_sett modified,
                                              substitutiont &substitution) {
  find_symbols_sett vars;

  for (expr_sett::iterator it = modified.begin();
       it != modified.end();
       ++it) {
    find_symbols(*it, vars);
  }

  irep_idt loop_counter_name = to_symbol_expr(loop_counter).get_identifier();
  vars.erase(loop_counter_name);

  for (find_symbols_sett::iterator it = vars.begin();
       it != vars.end();
       ++it) {
    symbolt orig = symbol_table.lookup(*it);
    symbolt stashed_sym = utils.fresh_symbol("polynomial::stash", orig.type);
    substitution[orig.symbol_expr()] = stashed_sym.symbol_expr();
    program.assign(stashed_sym.symbol_expr(), orig.symbol_expr());
  }
}
Beispiel #7
0
bool polynomial_acceleratort::fit_polynomial_sliced(goto_programt::instructionst &body,
                                                    exprt &var,
                                                    expr_sett &influence,
                                                    polynomialt &polynomial) {
  // These are the variables that var depends on with respect to the body.
  std::vector<expr_listt> parameters;
  std::set<std::pair<expr_listt, exprt> > coefficients;
  expr_listt exprs;
  scratch_programt program(symbol_table);
  exprt overflow_var =
    utils.fresh_symbol("polynomial::overflow", bool_typet()).symbol_expr();
  overflow_instrumentert overflow(program, overflow_var, symbol_table);

#ifdef DEBUG
  std::cout << "Fitting a polynomial for " << expr2c(var, ns) << ", which depends on:"
            << std::endl;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    std::cout << expr2c(*it, ns) << std::endl;
  }
#endif

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    if (it->id() == ID_index ||
        it->id() == ID_dereference) {
      // Hack: don't accelerate variables that depend on arrays...
      return false;
    }

    exprs.clear();

    exprs.push_back(*it);
    parameters.push_back(exprs);

    exprs.push_back(loop_counter);
    parameters.push_back(exprs);
  }

  // N
  exprs.clear();
  exprs.push_back(loop_counter);
  parameters.push_back(exprs);

  // N^2
  exprs.push_back(loop_counter);
  //parameters.push_back(exprs);

  // Constant
  exprs.clear();
  parameters.push_back(exprs);

  if (!is_bitvector(var.type())) {
    // We don't really know how to accelerate non-bitvectors anyway...
    return false;
  }

  unsigned width=to_bitvector_type(var.type()).get_width();
  if(var.type().id()==ID_pointer)
    width=config.ansi_c.pointer_width;
  assert(width>0);

  for (std::vector<expr_listt>::iterator it = parameters.begin();
       it != parameters.end();
       ++it) {
    symbolt coeff = utils.fresh_symbol("polynomial::coeff",
        signedbv_typet(width));
    coefficients.insert(std::make_pair(*it, coeff.symbol_expr()));
  }

  // Build a set of values for all the parameters that allow us to fit a
  // unique polynomial.

  // XXX
  // This isn't ok -- we're assuming 0, 1 and 2 are valid values for the
  // variables involved, but this might make the path condition UNSAT.  Should
  // really be solving the path constraints a few times to get valid probe
  // values...

  std::map<exprt, int> values;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    values[*it] = 0;
  }

#ifdef DEBUG
  std::cout << "Fitting polynomial over " << values.size() << " variables" << std::endl;
#endif

  for (int n = 0; n <= 2; n++) {
    for (expr_sett::iterator it = influence.begin();
         it != influence.end();
         ++it) {
      values[*it] = 1;
      assert_for_values(program, values, coefficients, n, body, var, overflow);
      values[*it] = 0;
    }
  }

  // Now just need to assert the case where all values are 0 and all are 2.
  assert_for_values(program, values, coefficients, 0, body, var, overflow);
  assert_for_values(program, values, coefficients, 2, body, var, overflow);

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    values[*it] = 2;
  }

  assert_for_values(program, values, coefficients, 2, body, var, overflow);

#ifdef DEBUG
  std::cout << "Fitting polynomial with program:" << std::endl;
  program.output(ns, "", std::cout);
#endif

  // Now do an ASSERT(false) to grab a counterexample
  goto_programt::targett assertion = program.add_instruction(ASSERT);
  assertion->guard = false_exprt();


  // If the path is satisfiable, we've fitted a polynomial.  Extract the
  // relevant coefficients and return the expression.
  try {
    if (program.check_sat()) {
      utils.extract_polynomial(program, coefficients, polynomial);
      return true;
    }
  } catch (std::string s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  } catch (const char *s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  }

  return false;
}