Skip to content

use optional for unknown pointer offset sizes #2137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 30, 2018

Conversation

kroening
Copy link
Member

This removes another case of using -1 as 'error value': pointer_offset_size and variants.

@kroening kroening requested a review from tautschnig April 28, 2018 17:37
@kroening kroening force-pushed the optional_pointer_offset branch 4 times, most recently from 2a7f009 to aac7dd7 Compare April 29, 2018 14:36
Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. I'd be curious to know whether there is any change in performance (positive or negative) for some of this code is called a lot.

if(offset_bits.has_value())
offset = to_range_spect(*offset_bits);
else
offset = -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: use ? : as above instead of the if ... else

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged with next branch

if(subtype_bits.has_value())
sub_size = to_range_spect(*subtype_bits);
else
sub_size = -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ? : as above.

if(subtype_bits.has_value())
sub_size = to_range_spect(*subtype_bits);
else
sub_size = -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ? : as above.

if(subtype_bits.has_value())
sub_size = to_range_spect(*subtype_bits);
else
sub_size = -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ? : as above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged with next branch.

{
range_spect size = to_range_spect(*param_bits);
gen(from, identifier, 0, size);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this should invoke gen even when the size cannot be determined (using -1 as a value of size is well-defined).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


if(width>=0)
return std::string(integer2size_t(width), 'x');
if(width.has_value() && *width >= 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The *width >= 0 is trivially true and should be removed.

@kroening kroening force-pushed the optional_pointer_offset branch from aac7dd7 to 4964eb2 Compare April 30, 2018 09:11
@kroening
Copy link
Member Author

Performance: I would expect a very minor positive effect (the comparison with of an mp_integer with -1 is mildly elaborate).

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nitpicks but at least a couple of mistakes to fix

to_range_spect(pointer_offset_bits(vector_type.subtype(), ns));
auto subtype_bits = pointer_offset_bits(vector_type.subtype(), ns);

sub_size = subtype_bits.has_value()?to_range_spect(*subtype_bits):-1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?: op spacing (also below)

if(comp_offset>op1_offset)
if(!comp_offset.has_value())
continue;
else if(comp_offset > op1_offset)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*comp_offset?

if(s<=0)
auto s = pointer_offset_bits(src, ns);

if(!s.has_value())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

|| !*s

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had pondered this one as well, but it's actually ok as the loop simply turns into a no-op.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah true, though I suspect the original author intended to skip set-up for the loop in that case. That means the only proper error is the != vs. == problem below.

return member_bits;
auto member_bits = pointer_offset_bits(comp.type(), ns);
if(!member_bits.has_value())
return optionalt<mp_integer>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use {} as a shorthand if you prefer

// no arrays of non-byte sized objects
assert(el_size%8==0);
mp_integer el_bytes=el_size/8;
DATA_INVARIANT(*el_size>0, "no arrays of zero-sized objects");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rephrase as a "should" statement for clarity when printed as an error dump (as written it's not clear whether we're forbidding or complaining that no such array was found)

@@ -2038,7 +2033,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
const typet &op_type=ns.follow(root.type());

// size must be known
if(val_size<=0)
if(!val_size.has_value() || *val_size != 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

== 0

{
result_expr.make_nil();
break;
}

// can we determine the current offset, and is it a byte-sized
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment belongs above, since the "can we determine" and the byte alignment question are now checked seperately

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is still wrong -- "Can we determine the current offset?" belongs above if(!m_offset.has_value() || ...), then "Is it a byte-sized member?" belongs here.

@smowton
Copy link
Contributor

smowton commented Apr 30, 2018

@kroening for the breakages that didn't cause a CI failure suggest adding a test case

@kroening kroening force-pushed the optional_pointer_offset branch from 2621da2 to fe9223e Compare April 30, 2018 14:47
m_offset>=offset_int+update_size)
else if(
update_size.has_value() && *update_size > 0 &&
*m_offset >= offset_int + *update_size)
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider putting braces around break (preceding multi-line conditional) to improve readability

auto el_size = pointer_offset_bits(op_type.subtype(), ns);
if(
!el_size.has_value() || *el_size == 0 || (*el_size) % 8 != 0 ||
(*val_size) % 8 != 0)
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider putting braces around return (preceding multi-line conditional) to improve readability

if(
sub_size.has_value() && *sub_size > 0 &&
!to_integer(index_expr.index(), i))
return (*o) + i * (*sub_size);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider putting braces around return (preceding multi-line conditional) to improve readability

throw "can't flatten byte_update for sub-type without size";

mp_integer sub_size = *sub_size_opt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const &

throw "byte_update of unknown width:\n"+src.pretty();

mp_integer element_size = *element_size_opt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const &

mp_integer alloc_size;

if(elem_size<0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there was some value in the != 0 check here as we are going to divide by elem_size later on, but that might already be implied by an invariant of pointer_offset_size().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nitpick, otherwise lgtm.

{
result_expr.make_nil();
break;
}

// can we determine the current offset, and is it a byte-sized
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is still wrong -- "Can we determine the current offset?" belongs above if(!m_offset.has_value() || ...), then "Is it a byte-sized member?" belongs here.

@kroening kroening force-pushed the optional_pointer_offset branch from 3b89aa5 to 03aceea Compare May 14, 2018 17:49
@kroening
Copy link
Member Author

Fixed the comment

@kroening
Copy link
Member Author

kroening commented May 22, 2018

There is performance cost:

#include "optional.h"
#include "mp_arith.h"

optionalt<mp_integer> some_a(long long i)
{
  if(i%2)
    return {};
  else
    return mp_integer(i);
}

mp_integer some_b(long long i)
{
  if(i%2)
    return -1;
  else
    return i;
}

int main()
{
  long long j=0;
  for(long long i=0; i<20000000; i++)
  {
    //if(some_a(i).has_value()) j++;
    if(some_b(i)!=-1) j++;
  }
}

With -O2 or -O3 the difference is 1.50s vs. 1.24s

@kroening kroening force-pushed the optional_pointer_offset branch 3 times, most recently from 53e10d9 to f06e62e Compare June 7, 2018 14:04
@kroening kroening force-pushed the optional_pointer_offset branch from f06e62e to 5ff66cb Compare June 14, 2018 10:34
@kroening
Copy link
Member Author

Rebased.

@kroening kroening force-pushed the optional_pointer_offset branch from 5ff66cb to bd5e6d8 Compare July 6, 2018 09:04
@kroening kroening requested a review from pkesseli as a code owner July 6, 2018 09:04
@tautschnig
Copy link
Collaborator

@kroening Could you please rebase again? With the continuous evaluation set-up prepared by @peterschrammel we should surely notice if this change truly results in a performance impact.

@kroening
Copy link
Member Author

Rebase done.

@kroening kroening force-pushed the optional_pointer_offset branch 2 times, most recently from 28f0abe to efdc901 Compare August 24, 2018 17:09
@kroening kroening force-pushed the optional_pointer_offset branch from efdc901 to 4568839 Compare September 22, 2018 17:13
@kroening kroening assigned peterschrammel and unassigned kroening Sep 22, 2018
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed Diffblue compatibility checks (cbmc commit: 4568839).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/85642915

@kroening kroening force-pushed the optional_pointer_offset branch from 4568839 to 3f59028 Compare September 30, 2018 11:05
@kroening
Copy link
Member Author

New data, on Linux:

clang++ 3.5.0 -O2:
with optionalt: 0.58s
with -1: 0.65s

clang++ 6.0.1 -O2:
with std::optional: 0.54s
with optionalt: 0.54s
with -1: 0.61s

g++ 8.2.0 -O2:
with std::optional: 0.61s
with optionalt: 0.59s
with -1: 0.66s

I.e., this delivers a performance improvement on Linux. Will merge once CIed.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed Diffblue compatibility checks (cbmc commit: 3f59028).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/86391538

@tautschnig tautschnig merged commit 8401f49 into develop Sep 30, 2018
@tautschnig tautschnig deleted the optional_pointer_offset branch September 30, 2018 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants