-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Store scalar pair bools as i8 in memory #51583
Conversation
Note that we keep the two components separate and outside a LLVM aggregate when immediate, so that type should not exist. |
// Make sure to always load i1 as i8. | ||
if scalar.is_bool() { | ||
llptr = bx.pointercast(llptr, Type::i8p(bx.cx)); | ||
assert_eq!(val_ty(llptr), Type::i8p(bx.cx)); |
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.
You can just remove this check and the comment above it.
src/librustc_codegen_llvm/type_of.rs
Outdated
if scalar.is_bool() { | ||
// Make sure to return the same type `immediate_llvm_type` would when | ||
// dealing with an immediate pair. This means that `(bool, bool)` is | ||
// effectively represented as `{i8, i8}` in memory and `{i1, i1}` as an |
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.
The type {i1, i1}
is never created, so maybe say "two i1
s" instead?
pair | ||
} | ||
|
||
// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %arg0.0, i1 zeroext %arg0.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.
Oh, this is another unfortunate consequence, I forgot about return values. I wonder if they should be using the pair "passing mode" that arguments do, and create a LLVM aggregate type on the fly, using the immediate types for the pair components. That way we'd get {i1, i1}
for returns, but everything else would see {i8, i8}
.
Not sure it's worth the complexity though. When inlining, LLVM should collapse the zext followed by trunc, just like it gets rid of packing into a pair and unpacking it.
// Make sure it can operate directly on the unpacked args | ||
// CHECK: and i1 %arg0.0, %arg0.1 | ||
// CHECK: or i1 %arg0.0, %arg0.1 | ||
(a && b, a || b) |
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.
Would be cool to see this with branches, since they only ever take i1
.
Ping from triage, @cuviper: It looks like there are some comments on your PR, do you think you'll be able to address those? |
Sorry I forgot about this. Yes, I'll update for those comments. |
We represent `bool` as `i1` in a `ScalarPair`, unlike other aggregates, to optimize IR for checked operators and the like. With this patch, we still do so when the pair is an immediate value, but we use the `i8` memory type when the value is loaded or stored as an LLVM aggregate. So `(bool, bool)` looks like an `{ i1, i1 }` immediate, but `{ i8, i8 }` in memory. When a pair is a direct function argument, `PassMode::Pair`, it is still passed using the immediate `i1` type, but as a return value it will use the `i8` memory type. Also, `bool`-like` enum tags will now use scalar pairs when possible, where they were previously excluded due to optimization issues.
@eddyb - I've addressed your review comments, except for what you said about return values. Would you like a FIXME comment and/or an issue filed about that? |
Ping from triage @eddyb! This PR needs your review. |
@cuviper r=me with maybe an issue filed about that, but I wouldn't worry too much. Thanks! |
@cuviper: 🔑 Insufficient privileges: Not in reviewers |
@bors r=eddyb delegate+ |
✌️ @cuviper can now approve this pull request |
📌 Commit 557736b has been approved by |
@bors r+ p=5 (rollup fairness) |
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit 557736b has been approved by |
Store scalar pair bools as i8 in memory We represent `bool` as `i1` in a `ScalarPair`, unlike other aggregates, to optimize IR for checked operators and the like. With this patch, we still do so when the pair is an immediate value, but we use the `i8` memory type when the value is loaded or stored as an LLVM aggregate. So `(bool, bool)` looks like an `{ i1, i1 }` immediate, but `{ i8, i8 }` in memory. When a pair is a direct function argument, `PassMode::Pair`, it is still passed using the immediate `i1` type, but as a return value it will use the `i8` memory type. Also, `bool`-like` enum tags will now use scalar pairs when possible, where they were previously excluded due to optimization issues. Fixes #51516. Closes #51566. r? @eddyb cc @nox
☀️ Test successful - status-appveyor, status-travis |
We represent
bool
asi1
in aScalarPair
, unlike other aggregates,to optimize IR for checked operators and the like. With this patch, we
still do so when the pair is an immediate value, but we use the
i8
memory type when the value is loaded or stored as an LLVM aggregate.
So
(bool, bool)
looks like an{ i1, i1 }
immediate, but{ i8, i8 }
in memory. When a pair is a direct function argument,
PassMode::Pair
,it is still passed using the immediate
i1
type, but as a return valueit will use the
i8
memory type. Also,bool
-like` enum tags will nowuse scalar pairs when possible, where they were previously excluded due
to optimization issues.
Fixes #51516.
Closes #51566.
r? @eddyb
cc @nox