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

Clearly specify the instruction_set effects #1307

Merged
merged 5 commits into from
Aug 1, 2023
Merged

Conversation

Lokathor
Copy link
Contributor

@Lokathor Lokathor commented Nov 23, 2022

This updates the instruction_set attribute entry to more clearly explain the additional restrictions that the attribute places on inlining. Since Rust performance heavily relies on inlining, it's actually a fairly big deal to document it.

Pinging @pnkfelix as the liaison for the instruction_set attribute during its development.

This explanation is actually slightly looser than the explanation given in the RFC: this explanation allows inlining between no-attribute code without inline asm and other code. So, T-lang should likely approve the update with an FCP or similar process. The intent is that once this is approved as the documentation for how the attribute works then rust-lang/rust#104121 (which updates the MIR inliner to match these rules) will be easier to land.

Updates the attributes page to specify what the instruction_set attribute does and where you can use it.

@pnkfelix
Copy link
Member

Nominating for a quick skim from T-lang. In particular, the rules around inlining, starting here:

https://github.com/rust-lang/reference/pull/1307/files#diff-11f03f772eabdb1a762b90f1ce58afd34c7938b20beae226e451da44d4fcd73aR378

are we okay with this set of rules? There are three basic rules there, the first two dictating the cases where inlining will be disallowed, and the third dictating when inlining will be allowed (and thus the calling function must not rely on details of the instruction set, or at least not details that would be in conflict with the instruction set of the callee that is being inlined).

The two specific questions are:

  1. Are we all okay with the first two rules, in terms of saying "these are cases where it is safe to rely on the instruction set"?
    • (I personally think they seem to be very clear and intuitive rules, a kind of case where I expect people to say "well yes, how could it be any other way?")
  2. Are we okay with the third rule, in terms of saying "in all other cases the code of a fn must not rely on the (implicit) instruction set"?
    • (I personally am fine with it, and its hard for me to imagine a scenario where we would want to allow a fn to have such an implicit reliance without any marker via the instruction_set attribute. But, having said that ... I assume it would then be a source of potential undefined behavior, so we should still take care in making a decision here.)

@Lokathor
Copy link
Contributor Author

I should perhaps note that if a function is inlined in some places as well as being fully generated to call over to from other places, the generated version will be of the target's default instruction set as one would expect.

The goal here is to carve out a little wiggle room for the MIR inliner to do more work. Without the ability to inline no-attribute code into attribute'd code it makes any use of the attribute a complete drop in performance.

For more background on how we got here you can also read the zulip topic: https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/What.20exactly.20does.20the.20MIR.20optimizer.20do.3F

@pnkfelix
Copy link
Member

pnkfelix commented Jan 4, 2023

Hey @Lokathor , sorry for the long delay in response here

The T-lang design team talked about this PR in its triage meeting yesterday

No one at the meeting expressed any problem with the rules as stated.

There was a slight concern about whether the language here is potentially misleading: we already don't say what inlining exactly "means", and all discussions of inlining attributes repeatedly say that they are all merely hints, with no requirements that inlining actually happen, or actually be strictly prohibited.

So, there was some feedback about whether this text could try incorporate that notion (redundantly, I acknowledge).

In other words, we wish for it to be clear that this text is non-normative, and is just meant to set users expectations about what might happen, without making strict guarantees in one direction or the other.

@pnkfelix
Copy link
Member

pnkfelix commented Jan 4, 2023

Also, there was some followup discussion on zulip

in that conversation, while attempting to summarize the meaning of the third rule, I wrote the something like the following:

If your function has neither the instruction_set attribute nor inline assembly, then the code you write within that function should not presume any particular instruction set

and there was some feedback indicating that this is a better way to write the third rule in question, with the belief that the resulting effects on whether inlining is allowed or not falls out naturally from that phrasing.

Maybe the third rule can instead be pulled out and phrased in something like the above form, and then you can keep the discussion of inlining, including all three parts, but reframe it all as consequences of the new phrasing?

@pnkfelix pnkfelix added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Jan 17, 2023
@nikomatsakis
Copy link
Contributor

@rustbot labels -I-lang-nominated

Removing nomination as this is waiting on @Lokathor

@Lokathor
Copy link
Contributor Author

Ah, slipped my mind, I'll try to get to this soon

@Lokathor
Copy link
Contributor Author

I think the new wording is sufficiently improved?

Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

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

Just some editorial nits.

src/attributes/codegen.md Outdated Show resolved Hide resolved
src/attributes/codegen.md Outdated Show resolved Hide resolved
@ehuss
Copy link
Contributor

ehuss commented May 28, 2023

@pnkfelix Did you have any comments on the updated text? Do you want to start an FCP to formally approve the changes, or was the team discussion sufficient?

@ehuss ehuss removed the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label May 28, 2023
Lokathor and others added 2 commits May 27, 2023 20:30
Co-authored-by: Eric Huss <eric@huss.org>
Co-authored-by: Eric Huss <eric@huss.org>
@nikomatsakis
Copy link
Contributor

@rustbot labels +I-lang-nominated

Raising for team discussion. I think that this text is fine as is. This whole feature is on that "grey line" where it doesn't theoretically affect language semantics etc etc.

@@ -374,4 +375,9 @@ fn foo_arm_code() {}
fn bar_thumb_code() {}
```

[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax
If your function has neither the `instruction_set` attribute nor inline assembly, then the code you write within that function should not presume any particular instruction set.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
If your function has neither the `instruction_set` attribute nor inline assembly, then the code you write within that function should not presume any particular instruction set.
If your function has neither the `instruction_set` attribute nor inline assembly, and you're compiling for a target with multiple instruction sets, the code you write within that function should not presume any particular instruction set.


* If a function has an `instruction_set` attribute it won't inline into a function of another instruction set.
* If a function does not have an `instruction_set` attribute but *does* contain inline assembly, then the inline assembly is assumed to require the default instruction set of the build target, and so inlining between different instruction sets won't happen.
* Otherwise, inlining happens normally.
Copy link
Member

Choose a reason for hiding this comment

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

This seems like it's specific to ARM and Thumb; this may not necessarily universally be true for all future uses of instruction_set.

@@ -374,4 +375,9 @@ fn foo_arm_code() {}
fn bar_thumb_code() {}
```

[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax
If your function has neither the `instruction_set` attribute nor inline assembly, then the code you write within that function should not presume any particular instruction set.
This ends up creating a limitation to how often code is inlined:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
This ends up creating a limitation to how often code is inlined:
For ARM in particular, `instruction_set` adds a limitation to where code gets inlined:

@Amanieu
Copy link
Member

Amanieu commented Jun 20, 2023

I don't think the reference should make any mention of inlining, since that is an implementation detail. Instead the text should clearly document the actual guaranteed effects of #[instruction_set]:

  • If the address of the function is taken as a function pointer. The low bit will be set to 0 or 1 depending on the instruction set.
  • Any inline assembly in the function will use the specified instruction set instead of the target default.

The restrictions on inlining are mainly an artifact of how inline assembly is compiled with LLVM: it uses the instruction set of the containing function after ininling. As such we need to ensure that any functions containing inline assembly are not inlined into functions with a different instruction set.

@Lokathor
Copy link
Contributor Author

@joshtriplett updated per the 2023-06-27 T-lang meeting, ready for FCP if the text seems fine.

@joshtriplett joshtriplett added the T-lang Team: Lang label Jul 11, 2023
@joshtriplett
Copy link
Member

@rfcbot merge

@rfcbot
Copy link

rfcbot commented Jul 11, 2023

Team member @joshtriplett 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!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@RalfJung
Copy link
Member

The PR description and title still need to be updated to the new content.

@Lokathor Lokathor changed the title Clearly specify the instruction_set inlining restrictions Clearly specify the instruction_set effects Jul 14, 2023
@Lokathor
Copy link
Contributor Author

should be fixed

@nikomatsakis
Copy link
Contributor

@rfcbot reviewed

@rfcbot
Copy link

rfcbot commented Jul 21, 2023

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

psst @joshtriplett, I wasn't able to add the final-comment-period label, please do so.

@nikomatsakis
Copy link
Contributor

@rustbot labels -I-lang-nominated +final-comment-period

@rfcbot
Copy link

rfcbot commented Jul 31, 2023

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.

This will be merged soon.

psst @joshtriplett, I wasn't able to add the finished-final-comment-period label, please do so.

Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

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

Thanks everyone!

@ehuss ehuss added this pull request to the merge queue Aug 1, 2023
Merged via the queue into rust-lang:master with commit 2a8068e Aug 1, 2023
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Aug 14, 2023
Update books

## rust-lang/book

3 commits in 668c64760b5c7ea654facb4ba5fe9faddfda27cc..72187f5cd0beaaa9c6f584156bcd88f921871e83
2023-08-04 14:42:07 UTC to 2023-08-03 13:36:44 UTC

- redirects: change link for the `#![no_std]` tutorial (rust-lang/book#3705)
- [chpt10.2] - Small wording changes (rust-lang/book#3724)
- Improve sentence (rust-lang/book#3725)

## rust-embedded/book

1 commits in 1e5556dd1b864109985d5871616ae6b9164bcead..99ad2847b865e96d8ae7b333d3ee96963557e621
2023-08-11 06:31:04 UTC to 2023-08-11 06:31:04 UTC

- Fix a small typo in qemu.md (rust-embedded/book#359)

## rust-lang/nomicon

1 commits in 302b995bcb24b70fd883980fd174738c3a10b705..388750b081c0893c275044d37203f97709e058ba
2023-08-10 21:15:21 UTC to 2023-08-10 21:15:21 UTC

- Document thiscall abi (rust-lang/nomicon#311)

## rust-lang/reference

10 commits in 1ea0178266b3f3f613b0fabdaf16a83961c99cdb..d43038932adeb16ada80e206d4c073d851298101
2023-08-12 19:07:28 UTC to 2023-07-16 20:12:46 UTC

- Document thiscall abi (rust-lang/reference#1092)
- add section about implied bounds (rust-lang/reference#1261)
- Clearly specify the `instruction_set` effects (rust-lang/reference#1307)
- Fix merge queue building twice. (rust-lang/reference#1383)
- Clarify UB around immutability & mutation (rust-lang/reference#1385)
- mention the extra const UB (rust-lang/reference#1273)
- Operator expressions: make the note about division by zero clearer. (rust-lang/reference#1384)
- Make unsafe keyword docs less confusing (rust-lang/reference#1379)
- Say that division by zero for primitive types panics (rust-lang/reference#1382)
- Add CI trigger for merge queues. (rust-lang/reference#1381)

## rust-lang/rust-by-example

3 commits in 8a87926a985ce32ca1fad1be4008ee161a0b91eb..07e0df2f006e59d171c6bf3cafa9d61dbeb520d8
2023-07-24 11:37:55 UTC to 2023-07-24 11:35:36 UTC

- Added attribute unused_labels - fixed warning. (rust-lang/rust-by-example#1729)
- more explanation about panic (rust-lang/rust-by-example#1728)
- chore: add the portuguese version of this project to `readme.md` (rust-lang/rust-by-example#1727)

## rust-lang/rustc-dev-guide

31 commits in b5a12d9..b123ab4
2023-08-14 08:34:59 UTC to 2023-07-11 06:02:34 UTC

- fix: stabilize debugger_visualizer (rust-lang/rustc-dev-guide#1766)
- feat(part-5-intro): make "Part 5" obvious (rust-lang/rustc-dev-guide#1753)
- Update from `#[warn_]` to `#[warning]` diagnostic attributes (rust-lang/rustc-dev-guide#1765)
- Add RPITIT documentation (rust-lang/rustc-dev-guide#1764)
- fix(visitor.md): fix a type name in a code sample (rust-lang/rustc-dev-guide#1762)
- fix(name-resolution): remove unnecessary closing paranthesis (rust-lang/rustc-dev-guide#1760)
- fix(macro-expansion.md): fix the article `an` to `a` (rust-lang/rustc-dev-guide#1759)
- fix(serialization.md): fix the name of a derive macro (rust-lang/rustc-dev-guide#1756)
- fix(serialization.md): add a necessary plural suffix (rust-lang/rustc-dev-guide#1757)
- fix(salsa.md): add punctuation to prevent confusion (rust-lang/rustc-dev-guide#1754)
- fix(salsa.md): remove duplicate "To Be" verb (rust-lang/rustc-dev-guide#1755)
- feat(fuzzing.md): make `halfempty` word a link (rust-lang/rustc-dev-guide#1750)
- fix(about.md): use `a` instead of `an` (rust-lang/rustc-dev-guide#1751)
- refactor(git.md): make git-scm links clickable (rust-lang/rustc-dev-guide#1747)
- fix(walkthrough.md) add a comma operator to eliminate ambiguity (rust-lang/rustc-dev-guide#1749)
- fix(git.md): remove a confusing end of sentence character (rust-lang/rustc-dev-guide#1748)
- refactor(profiling/with_perf): remove a wrong to be verb (rust-lang/rustc-dev-guide#1746)
- refactor(tests/headers): remove duplicate list item (rust-lang/rustc-dev-guide#1745)
- refactor(test/headers.md): make the meaning more obvious (rust-lang/rustc-dev-guide#1744)
- refactor(tests/ui): remove unnecessary duplicate word (rust-lang/rustc-dev-guide#1743)
- refactor(compiletest): remove unnecessary duplicate word (rust-lang/rustc-dev-guide#1742)
- generic_arguments.md: substs -> GenericArgs (rust-lang/rustc-dev-guide#1741)
- fix(suggested): remove an unnecessary and confusing statement (rust-lang/rustc-dev-guide#1739)
- fix(how-to-build-and-run): fix a typo ("fromer" -> "former") (rust-lang/rustc-dev-guide#1736)
- fix(how-to-build-and-run): remove a wrong paragraph (rust-lang/rustc-dev-guide#1735)
- coverage code has moved (rust-lang/rustc-dev-guide#1728)
- linked issue is closed (rust-lang/rustc-dev-guide#1729)
- remove duplicate reference in about-this-guide.md (rust-lang/rustc-dev-guide#1734)
- Explain more in depth what early and late bound generic parameters are (rust-lang/rustc-dev-guide#1732)
- add section for normalization with the new solver (rust-lang/rustc-dev-guide#1731)
- Improve cleanup-crew.md with an example post (rust-lang/rustc-dev-guide#1730)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants