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
Conversation
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:
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/ddmd/intrange.d
Outdated
@@ -77,35 +78,71 @@ struct SignExtendedNumber | |||
return 0; | |||
} | |||
|
|||
SignExtendedNumber opNeg() const | |||
ref SignExtendedNumber opAddAssign(int a) |
There was a problem hiding this comment.
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 : "++")()
?
src/ddmd/intrange.d
Outdated
|
||
private alias SignExtendedNumber R; | ||
|
||
R opUnary(string op:"~")() const |
There was a problem hiding this comment.
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
src/ddmd/intrange.d
Outdated
R opBinary(string op:"^^")(R rhs) | ||
{ | ||
// Not yet implemented | ||
assert(0); |
There was a problem hiding this comment.
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?
src/ddmd/intrange.d
Outdated
|
||
private alias IntRange R; | ||
|
||
R copy() const |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
src/ddmd/intrange.d
Outdated
R opUnary(string op:"-")() | ||
{ | ||
// Not yet implemented | ||
assert(0); |
There was a problem hiding this comment.
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.
src/ddmd/intrange.d
Outdated
} | ||
|
||
R l = this.copy(); | ||
R r = rhs.copy(); |
There was a problem hiding this comment.
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.
src/ddmd/intrange.d
Outdated
R opBinary(string op:"+")(R rhs) | ||
{ | ||
// Not yet implemented | ||
assert(0); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
src/ddmd/intrange.d
Outdated
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){ |
There was a problem hiding this comment.
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.
src/ddmd/intrange.d
Outdated
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) |
There was a problem hiding this comment.
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)
There was a problem hiding this 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; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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;
As per discussions with @andralex @WalterBright and @tgehr , this PR is the first step to improving VRP in dmd. Reimplemented
and
,or
,xor
overIntRange
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 forand
,or
,xor
fromdcast.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