Exemplo n.º 1
0
bool simplify_exprt::simplify_index(exprt &expr)
{
  bool result=true;

  // extra arithmetic optimizations
  const exprt &index=to_index_expr(expr).index();
  const exprt &array=to_index_expr(expr).array();

  if(index.id()==ID_div &&
     index.operands().size()==2)
  {
    if(index.op0().id()==ID_mult &&
       index.op0().operands().size()==2 &&
       index.op0().op1()==index.op1())
    {
      exprt tmp=index.op0().op0();
      expr.op1()=tmp;
      result=false;
    }
    else if(index.op0().id()==ID_mult &&
            index.op0().operands().size()==2 &&
            index.op0().op0()==index.op1())
    {
      exprt tmp=index.op0().op1();
      expr.op1()=tmp;
      result=false;
    }
  }

  if(array.id()==ID_lambda)
  {
    // simplify (lambda i: e)(x) to e[i/x]

    const exprt &lambda_expr=array;

    if(lambda_expr.operands().size()!=2)
      return true;

    if(expr.op1().type()==lambda_expr.op0().type())
    {
      exprt tmp=lambda_expr.op1();
      replace_expr(lambda_expr.op0(), expr.op1(), tmp);
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_with)
  {
    // we have (a WITH [i:=e])[j]

    const exprt &with_expr=array;

    if(with_expr.operands().size()!=3)
      return true;

    if(with_expr.op1()==expr.op1())
    {
      // simplify (e with [i:=v])[i] to v
      exprt tmp=with_expr.op2();
      expr.swap(tmp);
      return false;
    }
    else
    {
      // Turn (a with i:=x)[j] into (i==j)?x:a[j].
      // watch out that the type of i and j might be different.
      equal_exprt equality_expr(expr.op1(), with_expr.op1());

      if(equality_expr.lhs().type()!=equality_expr.rhs().type())
        equality_expr.rhs().make_typecast(equality_expr.lhs().type());

      simplify_inequality(equality_expr);

      index_exprt new_index_expr;
      new_index_expr.type()=expr.type();
      new_index_expr.array()=with_expr.op0();
      new_index_expr.index()=expr.op1();

      simplify_index(new_index_expr); // recursive call

      if(equality_expr.is_true())
      {
        expr=with_expr.op2();
        return false;
      }
      else if(equality_expr.is_false())
      {
        expr.swap(new_index_expr);
        return false;
      }

      if_exprt if_expr(equality_expr, with_expr.op2(), new_index_expr);
      simplify_if(if_expr);

      expr.swap(if_expr);

      return false;
    }
  }
  else if(array.id()==ID_constant ||
          array.id()==ID_array)
  {
    mp_integer i;

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>=array.operands().size())
    {
      // out of bounds
    }
    else
    {
      // ok
      exprt tmp=array.operands()[integer2size_t(i)];
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_string_constant)
  {
    mp_integer i;

    const irep_idt &value=array.get(ID_value);

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>value.size())
    {
      // out of bounds
    }
    else
    {
      // terminating zero?
      char v=(i==value.size())?0:value[integer2size_t(i)];
      exprt tmp=from_integer(v, expr.type());
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_array_of)
  {
    if(array.operands().size()==1)
    {
      exprt tmp=array.op0();
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()=="array-list")
  {
    // These are index/value pairs, alternating.
    for(size_t i=0; i<array.operands().size()/2; i++)
    {
      exprt tmp_index=array.operands()[i*2];
      tmp_index.make_typecast(index.type());
      simplify(tmp_index);
      if(tmp_index==index)
      {
        exprt tmp=array.operands()[i*2+1];
        expr.swap(tmp);
        return false;
      }
    }
  }
  else if(array.id()==ID_byte_extract_little_endian ||
          array.id()==ID_byte_extract_big_endian)
  {
    const typet &array_type=ns.follow(array.type());

    if(array_type.id()==ID_array)
    {
      // This rewrites byte_extract(s, o, array_type)[i]
      // to byte_extract(s, o+offset, sub_type)

      mp_integer sub_size=pointer_offset_size(array_type.subtype(), ns);
      if(sub_size==-1)
        return true;

      // add offset to index
      mult_exprt offset(from_integer(sub_size, array.op1().type()), index);
      plus_exprt final_offset(array.op1(), offset);
      simplify_node(final_offset);

      exprt result(array.id(), expr.type());
      result.copy_to_operands(array.op0(), final_offset);
      expr.swap(result);

      simplify_rec(expr);

      return false;
    }
  }
  else if(array.id()==ID_if)
  {
    const if_exprt &if_expr=to_if_expr(array);
    exprt cond=if_expr.cond();

    index_exprt idx_false=to_index_expr(expr);
    idx_false.array()=if_expr.false_case();

    to_index_expr(expr).array()=if_expr.true_case();

    expr=if_exprt(cond, expr, idx_false, expr.type());
    simplify_rec(expr);

    return false;
  }

  return result;
}
Exemplo n.º 2
0
bool simplify_exprt::simplify_floatbv_typecast(exprt &expr)
{
  // These casts usually reduce precision, and thus, usually round.

  assert(expr.operands().size()==2);

  const typet &dest_type=ns.follow(expr.type());
  const typet &src_type=ns.follow(expr.op0().type());

  // eliminate redundant casts
  if(dest_type==src_type)
  {
    expr=expr.op0();
    return false;
  }

  exprt op0=expr.op0();
  exprt op1=expr.op1(); // rounding mode

  // We can soundly re-write (float)((double)x op (double)y)
  // to x op y. True for any rounding mode!

  #if 0
  if(op0.id()==ID_floatbv_div ||
     op0.id()==ID_floatbv_mult ||
     op0.id()==ID_floatbv_plus ||
     op0.id()==ID_floatbv_minus)
  {
    if(op0.operands().size()==3 &&
       op0.op0().id()==ID_typecast &&
       op0.op1().id()==ID_typecast &&
       op0.op0().operands().size()==1 &&
       op0.op1().operands().size()==1 &&
       ns.follow(op0.op0().type())==dest_type &&
       ns.follow(op0.op1().type())==dest_type)
    {
      exprt result(op0.id(), expr.type());
      result.operands().resize(3);
      result.op0()=op0.op0().op0();
      result.op1()=op0.op1().op0();
      result.op2()=op1;

      simplify_node(result);
      expr.swap(result);
      return false;
    }
  }
  #endif

  // constant folding
  if(op0.is_constant() && op1.is_constant())
  {
    mp_integer rounding_mode;
    if(!to_integer(op1, rounding_mode))
    {
      if(src_type.id()==ID_floatbv)
      {
        if(dest_type.id()==ID_floatbv) // float to float
        {
          ieee_floatt result(to_constant_expr(op0));
          result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
          result.change_spec(to_floatbv_type(dest_type));
          expr=result.to_expr();
          return false;
        }
        else if(dest_type.id()==ID_signedbv ||
                dest_type.id()==ID_unsignedbv)
        {
          if(rounding_mode==ieee_floatt::ROUND_TO_ZERO)
          {
            ieee_floatt result(to_constant_expr(op0));
            result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
            mp_integer value=result.to_integer();
            expr=from_integer(value, dest_type);
            return false;
          }
        }
      }
      else if(src_type.id()==ID_signedbv ||
              src_type.id()==ID_unsignedbv)
      {
        mp_integer value;
        if(!to_integer(op0, value))
        {
          if(dest_type.id()==ID_floatbv) // int to float
          {
            ieee_floatt result;
            result.rounding_mode=(ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
            result.spec=to_floatbv_type(dest_type);
            result.from_integer(value);
            expr=result.to_expr();
            return false;
          }
        }
      }
    }
  }

  #if 0
  // (T)(a?b:c) --> a?(T)b:(T)c
  if(expr.op0().id()==ID_if &&
     expr.op0().operands().size()==3)
  {
    exprt tmp_op1=binary_exprt(expr.op0().op1(), ID_floatbv_typecast, expr.op1(), dest_type);
    exprt tmp_op2=binary_exprt(expr.op0().op2(), ID_floatbv_typecast, expr.op1(), dest_type);
    simplify_floatbv_typecast(tmp_op1);
    simplify_floatbv_typecast(tmp_op2);
    expr=if_exprt(expr.op0().op0(), tmp_op1, tmp_op2, dest_type);
    simplify_if(expr);
    return false;
  }
  #endif

  return true;
}
Exemplo n.º 3
0
bool simplify_exprt::simplify_pointer_offset(exprt &expr)
{
    if(expr.operands().size()!=1) return true;

    exprt &ptr=expr.op0();

    if(ptr.id()==ID_if && ptr.operands().size()==3)
    {
        if_exprt if_expr=lift_if(expr, 0);
        simplify_pointer_offset(if_expr.true_case());
        simplify_pointer_offset(if_expr.false_case());
        simplify_if(if_expr);
        expr.swap(if_expr);

        return false;
    }

    if(ptr.type().id()!=ID_pointer) return true;

    if(ptr.id()==ID_address_of)
    {
        if(ptr.operands().size()!=1) return true;

        mp_integer offset=compute_pointer_offset(ptr.op0(), ns);

        if(offset!=-1)
        {
            expr=from_integer(offset, expr.type());
            return false;
        }
    }
    else if(ptr.id()==ID_typecast) // pointer typecast
    {
        if(ptr.operands().size()!=1) return true;

        const typet &op_type=ns.follow(ptr.op0().type());

        if(op_type.id()==ID_pointer)
        {
            // Cast from pointer to pointer.
            // This just passes through, remove typecast.
            exprt tmp=ptr.op0();
            ptr=tmp;

            // recursive call
            simplify_node(expr);
            return false;
        }
        else if(op_type.id()==ID_signedbv ||
                op_type.id()==ID_unsignedbv)
        {
            // Cast from integer to pointer, say (int *)x.

            if(ptr.op0().is_constant())
            {
                // (T *)0x1234 -> 0x1234
                exprt tmp=ptr.op0();
                tmp.make_typecast(expr.type());
                simplify_node(tmp);
                expr.swap(tmp);
                return false;
            }
            else
            {
                // We do a bit of special treatment for (TYPE *)(a+(int)&o),
                // which is re-written to 'a'.

                typet type=ns.follow(expr.type());
                exprt tmp=ptr.op0();
                if(tmp.id()==ID_plus && tmp.operands().size()==2)
                {
                    if(tmp.op0().id()==ID_typecast &&
                            tmp.op0().operands().size()==1 &&
                            tmp.op0().op0().id()==ID_address_of)
                    {
                        expr=tmp.op1();
                        if(type!=expr.type())
                            expr.make_typecast(type);

                        simplify_node(expr);
                        return false;
                    }
                    else if(tmp.op1().id()==ID_typecast &&
                            tmp.op1().operands().size()==1 &&
                            tmp.op1().op0().id()==ID_address_of)
                    {
                        expr=tmp.op0();
                        if(type!=expr.type())
                            expr.make_typecast(type);

                        simplify_node(expr);
                        return false;
                    }
                }
            }
        }
    }
    else if(ptr.id()==ID_plus) // pointer arithmetic
    {
        exprt::operandst ptr_expr;
        exprt::operandst int_expr;

        for(const auto & op : ptr.operands())
        {
            if(op.type().id()==ID_pointer)
                ptr_expr.push_back(op);
            else if(!op.is_zero())
            {
                exprt tmp=op;
                if(tmp.type()!=expr.type())
                {
                    tmp.make_typecast(expr.type());
                    simplify_node(tmp);
                }

                int_expr.push_back(tmp);
            }
        }

        if(ptr_expr.size()!=1 || int_expr.empty())
            return true;

        typet pointer_type=ptr_expr.front().type();

        mp_integer element_size=
            pointer_offset_size(pointer_type.subtype(), ns);

        if(element_size==0) return true;

        // this might change the type of the pointer!
        exprt pointer_offset(ID_pointer_offset, expr.type());
        pointer_offset.copy_to_operands(ptr_expr.front());
        simplify_node(pointer_offset);

        exprt sum;

        if(int_expr.size()==1)
            sum=int_expr.front();
        else
        {
            sum=exprt(ID_plus, expr.type());
            sum.operands()=int_expr;
        }

        simplify_node(sum);

        exprt size_expr=
            from_integer(element_size, expr.type());

        binary_exprt product(sum, ID_mult, size_expr, expr.type());

        simplify_node(product);

        expr=binary_exprt(pointer_offset, ID_plus, product, expr.type());

        simplify_node(expr);

        return false;
    }
    else if(ptr.id()==ID_constant &&
            ptr.get(ID_value)==ID_NULL)
    {
        expr=gen_zero(expr.type());

        simplify_node(expr);

        return false;
    }

    return true;
}