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

Eliminate some other bound checks when index comes from an enum #75529

Merged
merged 2 commits into from
Sep 1, 2020

Conversation

bugadani
Copy link
Contributor

@bugadani bugadani commented Aug 14, 2020

#36962 introduced an assumption for the upper limit of the enum's value. This PR adds an assumption to the lower value as well.

I've modified the original codegen test to show that derived (in that case, adding 1) values also don't generate bounds checks.

However, this test is actually carefully crafted to not hit a bug: if the enum's variants are modified to 1 and 2 instead of 2 and 3, the test fails by adding a bounds check. I suppose this is an LLVM issue and #75525, while not exactly in this context should be tracking it.

I'm not at all confident if this patch can be accepted, or even if it should be accepted in this state. But I'm curious about what others think :)

Improves Should improve #13926 but does not close it because it's not exactly predictable, where bounds checks may pop up against the assumptions.

@rust-highfive
Copy link
Collaborator

r? @lcnr

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 14, 2020
@bugadani
Copy link
Contributor Author

Looks like it's even more brittle than I expected. How should I proceed?

@bugadani
Copy link
Contributor Author

I found the min-llvm-version option to filter the test. However, should I mark the whole test for llvm >= 10, or split it up into 2 tests and just filter the part added by this PR?

@estebank
Copy link
Contributor

@bugadani splitting the test sounds like the best course of action.

@bugadani
Copy link
Contributor Author

Is there anything more I should do?

@lcnr
Copy link
Contributor

lcnr commented Aug 24, 2020

hmm, this looks fairly innocent to me but I don't know too much about this. Is there anything actionable left for #13926, because otherwise I would prefer to close that issue and open separate issues for the remaining cases. Afaict this does fix #13926 (comment).

I would prefer for someone else to take this over.

Maybe r? @eddyb considering that they reviewed #36962

@rust-highfive rust-highfive assigned eddyb and unassigned lcnr Aug 24, 2020
@bugadani
Copy link
Contributor Author

bugadani commented Aug 24, 2020

One problem is that LLVM seems a bit limited in how it handles assumptions and because of this, this patch currently only works for some values, but not for others. This is why I think that issue can't yet be closed, but this is not something that can be fixed this way.

The current test case is a bit of a lie because of this: it just demonstrates that some cases will be optimized, but I think I had to hunt for the numbers a bit since others did not get optimized...

@lcnr
Copy link
Contributor

lcnr commented Aug 24, 2020

Hmm, can you then add some of these not yet optimized cases as a comment to the issue so it's clear what still needs to be done here?

let cmp_end =
bx.icmp(IntPredicate::IntULE, llval, ll_t_in_const);

if *scalar.valid_range.start() > 0 {
Copy link
Member

Choose a reason for hiding this comment

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

Note to self/other reviewers: this condition should be enough because this is inside an if that checks for scalar.valid_range.end() > scalar.valid_range.start() (i.e. that the range does not wrap around, making it a valid simple unsigned integer range).

We could probably also support wraparound ranges, by treating them as signed integer ranges, but I guess that's less commonly used, especially for indexing?

@eddyb
Copy link
Member

eddyb commented Aug 24, 2020

I'm worried assume still has downsides, so:
@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Aug 24, 2020

⌛ Trying commit 6e670726116812a156cd0dd14cad1e5c58669f27 with merge 8f6a7e4210495c2a5cc5b0ab704b7ce17f2c5a35...

Copy link
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

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

LGTM, but I'll let someone else have the final say wrt codegen

@eddyb
Copy link
Member

eddyb commented Aug 24, 2020

r? @nagisa or @nikic

@rust-highfive rust-highfive assigned nagisa and unassigned eddyb Aug 24, 2020
@bors
Copy link
Contributor

bors commented Aug 24, 2020

☀️ Try build successful - checks-actions, checks-azure
Build commit: 8f6a7e4210495c2a5cc5b0ab704b7ce17f2c5a35 (8f6a7e4210495c2a5cc5b0ab704b7ce17f2c5a35)

@rust-timer
Copy link
Collaborator

Queued 8f6a7e4210495c2a5cc5b0ab704b7ce17f2c5a35 with parent 0301700, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (8f6a7e4210495c2a5cc5b0ab704b7ce17f2c5a35): comparison url.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying rollup- to bors.

Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up.

@bors rollup=never

@bugadani
Copy link
Contributor Author

bugadani commented Aug 24, 2020

Hmm, can you then add some of these not yet optimized cases as a comment to the issue so it's clear what still needs to be done here?

~This one fails: ~ Correction: this one passes with llvm11

// compile-flags: -O
// min-llvm-version: 10.0

#![crate_type = "lib"]

pub enum Bar {
    A = 1,
    B = 2
}

// CHECK-LABEL: @lookup_inc
#[no_mangle]
pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 {
    // CHECK-NOT: panic_bounds_check
    buf[f as usize + 1]
}

// CHECK-LABEL: @lookup_dec
#[no_mangle]
pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 {
    // CHECK-NOT: panic_bounds_check
    buf[f as usize - 1]
}

So does the original case:

// compile-flags: -O
// min-llvm-version: 10.0

#![crate_type = "lib"]

#[repr(u8)]
pub enum Exception {
    Low = 5,
    High = 10,
}

// CHECK-LABEL: @access
#[no_mangle]
pub fn access(array: &[usize; 12], exc: Exception) -> usize {
    // CHECK-NOT: panic_bounds_check
    array[(exc as u8 - 4) as usize]
}

In fact, it is harder to find cases where the test passes. The only explanation I can think of is that LLVM has some other idea about the assumptions than me.

Copy link
Member

@nagisa nagisa left a comment

Choose a reason for hiding this comment

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

I don’t mind adding this either, but I wouldn’t hold my breath that any specific behaviour will last, especially across backend versions.

I’m saying this specifically because I don’t think the behaviour added tests verify is something we want to guarantee. It is sure nice when the optimisations just work out and manage to produce exactly the desired outcome, but I wouldn’t block e.g. LLVM upgrade over this test failing. This is also relevant to e.g. users that build with an external LLVM (such as debian).

I guess we can try to remember that these are not actually super important if we find them failing? Perhaps a comment would be good to somehow indicate that these tests are not normative.

otherwise r=me

src/librustc_codegen_ssa/mir/rvalue.rs Outdated Show resolved Hide resolved
@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 31, 2020
@nagisa
Copy link
Member

nagisa commented Aug 31, 2020

Yeah this particular failure has been spuriously recently on many different PRs.

@bors
Copy link
Contributor

bors commented Sep 1, 2020

⌛ Testing commit 1d157ce with merge 37ddb0103c726415513dd29225f339dc04627d4a...

@rust-log-analyzer
Copy link
Collaborator

The job dist-i686-msvc of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @rust-lang/infra. (Feature Requests)

@bors
Copy link
Contributor

bors commented Sep 1, 2020

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 1, 2020
@bugadani
Copy link
Contributor Author

bugadani commented Sep 1, 2020

Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

I love it :) Especially the empty log excerpt, which is actually accurate since the logs indicate network error :)

@nagisa do you get notified about these, or should I keep pinging you?

@lcnr
Copy link
Contributor

lcnr commented Sep 1, 2020

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 1, 2020
@bors
Copy link
Contributor

bors commented Sep 1, 2020

⌛ Testing commit 1d157ce with merge b170fe1121dde6e9a7684038c8ccc5cb49f0c257...

@bors
Copy link
Contributor

bors commented Sep 1, 2020

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 1, 2020
@rust-log-analyzer
Copy link
Collaborator

Your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @rust-lang/infra. (Feature Requests)

@nagisa
Copy link
Member

nagisa commented Sep 1, 2020 via email

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 1, 2020
@bors
Copy link
Contributor

bors commented Sep 1, 2020

⌛ Testing commit 1d157ce with merge 397db05...

@bors
Copy link
Contributor

bors commented Sep 1, 2020

☀️ Test successful - checks-actions, checks-azure
Approved by: nagisa
Pushing 397db05 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 1, 2020
@bors bors merged commit 397db05 into rust-lang:master Sep 1, 2020
@bugadani bugadani deleted the bounds-check branch October 16, 2020 14:53
@cuviper cuviper added this to the 1.48.0 milestone May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.