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

Store scalar pair bools as i8 in memory #51583

Merged
merged 2 commits into from
Jul 10, 2018
Merged

Conversation

cuviper
Copy link
Member

@cuviper cuviper commented Jun 15, 2018

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 15, 2018
@eddyb
Copy link
Member

eddyb commented Jun 16, 2018

{ i1, i1 } immediate

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));
Copy link
Member

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.

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
Copy link
Member

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 i1s" instead?

pair
}

// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %arg0.0, i1 zeroext %arg0.1)
Copy link
Member

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)
Copy link
Member

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.

@pietroalbini pietroalbini added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 25, 2018
@TimNN
Copy link
Contributor

TimNN commented Jul 3, 2018

Ping from triage, @cuviper: It looks like there are some comments on your PR, do you think you'll be able to address those?

@cuviper
Copy link
Member Author

cuviper commented Jul 3, 2018

Sorry I forgot about this. Yes, I'll update for those comments.

cuviper added 2 commits July 5, 2018 09:59
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.
@cuviper cuviper force-pushed the packed_pair-bool branch from 08cfb58 to 557736b Compare July 5, 2018 21:23
@cuviper
Copy link
Member Author

cuviper commented Jul 5, 2018

@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?

@cuviper cuviper added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 5, 2018
@pietroalbini
Copy link
Member

Ping from triage @eddyb! This PR needs your review.

@eddyb
Copy link
Member

eddyb commented Jul 9, 2018

@cuviper r=me with maybe an issue filed about that, but I wouldn't worry too much. Thanks!

@cuviper
Copy link
Member Author

cuviper commented Jul 10, 2018

OK, filed #52198. Not sure if I have bors access, but let's try:

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Jul 10, 2018

@cuviper: 🔑 Insufficient privileges: Not in reviewers

@Mark-Simulacrum
Copy link
Member

@bors r=eddyb delegate+

@bors
Copy link
Contributor

bors commented Jul 10, 2018

✌️ @cuviper can now approve this pull request

@bors
Copy link
Contributor

bors commented Jul 10, 2018

📌 Commit 557736b has been approved by eddyb

@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 Jul 10, 2018
@Mark-Simulacrum
Copy link
Member

@bors r+ p=5 (rollup fairness)

@bors
Copy link
Contributor

bors commented Jul 10, 2018

💡 This pull request was already approved, no need to approve it again.

@bors
Copy link
Contributor

bors commented Jul 10, 2018

📌 Commit 557736b has been approved by Mark-Simulacrum

@bors
Copy link
Contributor

bors commented Jul 10, 2018

⌛ Testing commit 557736b with merge b3e7d70...

bors added a commit that referenced this pull request Jul 10, 2018
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
@bors
Copy link
Contributor

bors commented Jul 10, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: Mark-Simulacrum
Pushing b3e7d70 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

7 participants