-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Array indexed by exhaustive match still generates bounds checks #149480
Copy link
Copy link
Open
Labels
A-mir-optArea: MIR optimizationsArea: MIR optimizationsC-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.S-has-bisectionStatus: A bisection has been found for this issueStatus: A bisection has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Metadata
Metadata
Assignees
Labels
A-mir-optArea: MIR optimizationsArea: MIR optimizationsC-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.S-has-bisectionStatus: A bisection has been found for this issueStatus: A bisection has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Type
Fields
Give feedbackNo fields configured for issues without a type.
Given this enum that has two inner enums for a total of 3 + 2 = 5 variants, rustc fails to notice that the
matchoutput is always withinarr's bounds and still generates bounds-checking code. GodboltCommenting out any of the five variants removes the bounds check. This is the case even if commenting out, say, A2, so that the min and max values generated by the
matchare still 0..=4. In other words it seems the number of variants matters, not the values they map to.Keeping all five variants and increasing the array size to 256 also eliminates the bounds check. In this case, changing the B1 arm to map to 255 still does not generate bounds checks. So it seems rustc does track the range of all five arms, but somehow the array length being 256 or less than 256 matters to it.
Flattening all five variants into one enum also eliminates the bounds check.
Uncommenting the
assert!replaces the bounds check code with assert panic code, so there's no net benefit. Uncommenting theassert_uncheckedeliminates the bounds check as expected.Based on the compilers Godbolt provides, this regressed between 1.81.0 and 1.82.0. That is, 1.81.0 does not generate bounds checks but 1.82.0 does. These are old enough that I figured this doesn't deserve to be tagged as "regression". In any case it is not noticeable in benchmarks of my real code (more top-level variants and a lot more sub-variants) since the branch is predicted correctly.
I noticed #147831 , but given that that one regressed from 1.89 to 1.90, I assume it is not the same as this one.
Meta
rustc --version --verbose: