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

Make `abs`, `wrapping_abs`, `overflowing_abs` const functions #63786

Merged
merged 2 commits into from Sep 10, 2019

Conversation

@tspiteri
Copy link
Contributor

commented Aug 21, 2019

This makes abs, wrapping_abs and overflowing_abs const functions like #58044 makes wrapping_neg and overflowing_neg const functions.

abs is made const by returning (self ^ -1) - -1 = !self + 1 = -self for negative numbers and (self ^ 0) - 0 = self for non-negative numbers. The subexpression self >> ($BITS - 1) evaluates to -1 for negative numbers and 0 otherwise. The subtraction overflows when self is min_value(), as we would be subtracting max_value() - -1; this is when abs should overflow.

wrapping_abs and overflowing_abs make use of wrapping_sub and overflowing_sub instead of the subtraction operator.

@rust-highfive

This comment has been minimized.

Copy link
Collaborator

commented Aug 21, 2019

r? @cramertj

(rust_highfive has picked a reviewer for you, use r? to override)

@Centril Centril added this to the 1.39 milestone Aug 21, 2019

@Centril Centril added the needs-fcp label Aug 21, 2019

@cramertj

This comment has been minimized.

Copy link
Member

commented Aug 22, 2019

@alexcrichton

This comment has been minimized.

Copy link
Member

commented Aug 22, 2019

@rfcbot fcp merge

@rfcbot

This comment has been minimized.

Copy link

commented Aug 22, 2019

Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@Centril

This comment has been minimized.

Copy link
Member

commented Aug 30, 2019

Ping @withoutboats @Kimundi @sfackler in case y'all missed this. :)

@rfcbot

This comment has been minimized.

Copy link

commented Aug 30, 2019

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot

This comment has been minimized.

Copy link

commented Sep 9, 2019

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

The RFC will be merged soon.

@alexcrichton

This comment has been minimized.

Copy link
Member

commented Sep 10, 2019

@bors: r+

@bors

This comment has been minimized.

Copy link
Contributor

commented Sep 10, 2019

📌 Commit adee559 has been approved by alexcrichton

Centril added a commit to Centril/rust that referenced this pull request Sep 10, 2019
Rollup merge of rust-lang#63786 - tspiteri:const-abs, r=alexcrichton
Make `abs`, `wrapping_abs`, `overflowing_abs` const functions

This makes `abs`, `wrapping_abs` and `overflowing_abs` const functions like rust-lang#58044 makes `wrapping_neg` and `overflowing_neg` const functions.

`abs` is made const by returning `(self ^ -1) - -1` = `!self + 1` = `-self` for negative numbers and `(self ^ 0) - 0` = `self` for non-negative numbers. The subexpression `self >> ($BITS - 1)` evaluates to `-1` for negative numbers and `0` otherwise. The subtraction overflows when `self` is `min_value()`, as we would be subtracting `max_value() - -1`; this is when `abs` should overflow.

`wrapping_abs` and `overflowing_abs` make use of `wrapping_sub` and `overflowing_sub` instead of the subtraction operator.
bors added a commit that referenced this pull request Sep 10, 2019
Auto merge of #64354 - Centril:rollup-oaq0xoi, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #63786 (Make `abs`, `wrapping_abs`, `overflowing_abs` const functions)
 - #63989 (Add Yaah to clippy toolstain notification list)
 - #64256 (test/c-variadic: Fix patterns on powerpc64)
 - #64292 (lowering: extend temporary lifetimes around await)
 - #64311 (lldb: avoid mixing "Hit breakpoint" message with other output.)
 - #64330 (Clarify E0507 to note Fn/FnMut relationship to borrowing)
 - #64331 (Changed instant is earlier to instant is later)
 - #64344 (rustc_mir: buffer -Zdump-mir output instead of pestering the kernel constantly.)

Failed merges:

r? @ghost

@bors bors merged commit adee559 into rust-lang:master Sep 10, 2019

5 checks passed

pr Build #20190907.22 succeeded
Details
pr (Linux mingw-check) Linux mingw-check succeeded
Details
pr (Linux x86_64-gnu-llvm-6.0) Linux x86_64-gnu-llvm-6.0 succeeded
Details
pr (LinuxTools) LinuxTools succeeded
Details
pr (LinuxTools) LinuxTools succeeded
Details
self
}
pub const fn wrapping_abs(self) -> Self {
(self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1))

This comment has been minimized.

Copy link
@RalfJung

RalfJung Sep 10, 2019

Member

I am not a big fan of making code less readable just to please our const qualification. :/

Cc @oli-obk @eddyb

This comment has been minimized.

Copy link
@eddyb

eddyb Sep 11, 2019

Member

We've had variables for a while, please use them.

This comment has been minimized.

Copy link
@nikic

nikic Sep 11, 2019

Contributor

Has it been verified that this optimizes to identical LLVM IR?

This comment has been minimized.

Copy link
@tspiteri

tspiteri Sep 11, 2019

Author Contributor

@eddyb Since this has already passed final comment period and been merged, shall I open a new PR to use variables?

This comment has been minimized.

Copy link
@tspiteri

tspiteri Sep 11, 2019

Author Contributor

@nikic I can't read LLVM IR; what I did do before submitting the PR was to use llvm-mca, and although the assembly is not identical, the performance measure from llvm-mca was the same, or if I remember well, in some tests the reverse throughput improved by something tiny like 0.1, but not regressed. I only used llvm-mca with i686 or x86-64 instructions, and I don't think I tested all types comprehensively.

This comment has been minimized.

Copy link
@nikic

nikic Sep 11, 2019

Contributor

@tspiteri Asm and IR of the two implementations: https://rust.godbolt.org/z/BXphZX

The new implementation is not combined into a select. The throughput of the final asm is only half the problem. LLVM understands abs operations as a special SelectPatternFlavor and can optimize them accordingly. This will not work if the abs is not in its canonical representation (as a select).

This comment has been minimized.

Copy link
@tspiteri

tspiteri Sep 11, 2019

Author Contributor

@nikic Hmm, using variables as @eddyb suggested seems to hit two birds with one stone. If I insert a variable for the sign, I get one implementation and an alias: https://godbolt.org/z/m-seT0

Does that mean that the performance will not regress?

This comment has been minimized.

Copy link
@nikic

nikic Sep 11, 2019

Contributor

@tspiteri Oops, I simply made a typo in my test and that's why the result is different, duh :) It actually does produce the same IR, both with variable and without. So forget everything I said, this change is fine from the optimization perspective.

This comment has been minimized.

Copy link
@tspiteri

tspiteri Sep 11, 2019

Author Contributor

@nikic While abs and wrapping_abs seem to be fine performance-wise, overflowing_abs from this PR actually does suffer from the problem discussed, so I will not forget everything you said! :) It's easily fixed by making it return (self.wrapping_abs(), self == Self::min_value()).

This comment has been minimized.

Copy link
@RalfJung

RalfJung Sep 11, 2019

Member

And also, the code with the sign factored out is more readable. ;)

That said, I still think we should rather wait for CTFE to support conditionals than compromise code readability, and even the let sign version is still arcane magic. But that call is up to T-libs.

@tspiteri tspiteri deleted the tspiteri:const-abs branch Sep 10, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.