Skip to content
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

VRP for and,or,xor + Refactoring intrange.d + Fix Issue 10310 #7317

Merged
merged 1 commit into from Nov 16, 2017

Conversation

somzzz
Copy link
Contributor

@somzzz somzzz commented Nov 14, 2017

As per discussions with @andralex @WalterBright and @tgehr , this PR is the first step to improving VRP in dmd. Reimplemented and, or, xor over IntRange using the algorithms designed by @tgehr :
https://github.com/tgehr/d-compiler/blob/master/vrange.d

Refactored intrange.d to use DMD2 style op overloads. Moved implementation for and, or, xor from dcast.d. This is a first step, the other operators will follow - this PR is quite big already.

Also fixing bug related to imprecise xor bounds:
https://issues.dlang.org/show_bug.cgi?id=10310

@dlang-bot
Copy link
Contributor

dlang-bot commented Nov 14, 2017

Thanks for your pull request, @somzzz! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.

Some tips to help speed things up:

  • smaller, focused PRs are easier to review than big ones

  • try not to mix up refactoring or style changes with bug fixes or feature enhancements

  • provide helpful commit messages explaining the rationale behind each change

Bear in mind that large or tricky changes may require multiple rounds of review and revision.

Please see CONTRIBUTING.md for more information.

Bugzilla references

Auto-close Bugzilla Description
10310 VRP for bitwise &

Copy link
Member

@andralex andralex left a comment

Choose a reason for hiding this comment

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

@@ -77,35 +78,71 @@ struct SignExtendedNumber
return 0;
}

SignExtendedNumber opNeg() const
ref SignExtendedNumber opAddAssign(int a)
Copy link
Member

Choose a reason for hiding this comment

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

This is odd... why not opUnary(string op : "++")()?


private alias SignExtendedNumber R;

R opUnary(string op:"~")() const
Copy link
Member

Choose a reason for hiding this comment

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

we use spaces around :, I recall Timon's spacing is more compact

R opBinary(string op:"^^")(R rhs)
{
// Not yet implemented
assert(0);
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this going to crash during use?


private alias IntRange R;

R copy() const
Copy link
Member

Choose a reason for hiding this comment

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

Why is this necessary? Doesn't IntRange(another) suffice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There isn't any IntRange constructor which takes another IntRange as param.

Copy link
Member

Choose a reason for hiding this comment

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

That would be implicitly defined, or you can define it if needed.

R opUnary(string op:"-")()
{
// Not yet implemented
assert(0);
Copy link
Member

Choose a reason for hiding this comment

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

This looks fairly easy to implement.

}

R l = this.copy();
R r = rhs.copy();
Copy link
Member

Choose a reason for hiding this comment

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

Aside from the copy brow-raiser, you may want to use lhs and rhs for the operands, e.g. in github's font l and 1 are difficult to distinguish.

R opBinary(string op:"+")(R rhs)
{
// Not yet implemented
assert(0);
Copy link
Member

Choose a reason for hiding this comment

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

Reiterating suggestion: on overflow, conservatively return the maximum range.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This PR is only for the bitops, the old code doesn't use operator overloads for IntRange, so currently there is no code that calls into assert(0). Most of the implementation for these operators is split between dcast.d eg
https://github.com/dlang/dmd/blob/master/src/ddmd/dcast.d#L3613
and SignExtendedNumber and should be refactored. The purpose of adding those stubs is to suggest this.

I wanted to do this in different PRs. Similarly, at the end, if we decide we don't need SignExtendedNumber anymore, we can remove it in its own PR.

If you think it's better to handle all VRP in one go, we can do that.

private:
// Credits to Timon Gehr maxOr, minOr, maxAnd, minAnd
// https://github.com/tgehr/d-compiler/blob/master/vrange.d
static SignExtendedNumber maxOr(R lhs, R rhs){
Copy link
Member

Choose a reason for hiding this comment

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

Formatting issues - brace should be on its own line and the function body should be indented.

auto xor = lhs.imax.value ^ rhs.imax.value;
auto and = lhs.imax.value & rhs.imax.value;

for(uinteger_t d = 1LU << (8 * uinteger_t.sizeof - 1); d; d >>= 1)
Copy link
Member

Choose a reason for hiding this comment

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

space after if etc (adjust from Timon's convention to ours)

Copy link
Member

@andralex andralex left a comment

Choose a reason for hiding this comment

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

no blockers

@@ -77,35 +78,70 @@ struct SignExtendedNumber
return 0;
}

SignExtendedNumber opNeg() const
private alias SignExtendedNumber R;
Copy link
Member

Choose a reason for hiding this comment

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

This is a distraction, a future PR should eliminate it and rename SignExtendedNumber to SignExtended.


R opUnary(string op : "~")() const
{
return SignExtendedNumber(~value);
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this (and other similar operations) is correct. It converts a negative number into a positive one. Shouldn't it be return SignExtendedNumber(~value, negative);? cc @WalterBright @tgehr

Copy link
Contributor

@tgehr tgehr Nov 17, 2017

Choose a reason for hiding this comment

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

~ flips the sign bit, so it might need to be SignExtendedNumber(~value, !negative) if the underlying datatype is signed.

Copy link
Member

Choose a reason for hiding this comment

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

@tgehr I actually tried that, then druntime failed to compile

uinteger_t sum = value + a.value;
bool carry = sum < value && sum < a.value;
if (negative != a.negative)
return SignExtendedNumber(value & rhs.value);
Copy link
Member

Choose a reason for hiding this comment

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

same question here about signedness of result - looks like any two inputs produce a positive number

R opBinary(string op : "+")(R rhs)
{
uinteger_t sum = value + rhs.value;
bool carry = sum < value && sum < rhs.value;
Copy link
Member

Choose a reason for hiding this comment

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

Clearer and more efficient:

bool carry = value > uinteger_t.max - rhs.value;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants