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

Lower baseline expectations for i686 unix-like targets #548

Closed
1 of 3 tasks
goshhhy opened this issue Aug 24, 2022 · 7 comments
Closed
1 of 3 tasks

Lower baseline expectations for i686 unix-like targets #548

goshhhy opened this issue Aug 24, 2022 · 7 comments
Labels
major-change A proposal to make a major change to rustc T-compiler Add this label so rfcbot knows to poll the compiler team

Comments

@goshhhy
Copy link

goshhhy commented Aug 24, 2022

Proposal

This is a proprosal to lower the baseline expectations for the following targets from pentium4 to pentiumpro:

  • i686-unknown-linux-gnu
  • i686-unknown-linux-musl
  • i686-unknown-freebsd
  • i686-unknown-openbsd
  • i686-unknown-netbsd
  • i686-unknown-haiku

This is a follow-up to #543 (Promote i586-unknown-linux-gnu to Tier 2 with Host Tools). The general consensus in the Zulip discussion was that, rather than promoting that target, the i686 target baselines should be fixed such that it matches the expectation of the target operating system.

The listed targets all generally have an assumption downstream that the baseline for "i686" is a Pentium Pro, and does not include support for SSE2. There are users on these platforms (myself among them) that are unable to use Rust, or Rust binaries compiled for their platform, because Rust's baseline assumption on these targets (Pentium 4) differs from the actual expectation of the platform. This change would enable these users to use the official Rust host tools and other Rust binaries. It could cause some binaries to run slower on newer processors, if those binaries were built targeting i686.

At a minimum, Gentoo and Debian have issues about this. Rust also has an issue open on this (rust-lang/rust#82435), which this proposal would resolve. Debian and FreeBSD are known to patch the target to match their assumptions. Some other distributions ship their own compilers targeting i586 to work around this. Haiku and NetBSD both target i586 as a minimum (NetBSD targets i486 where possible; for Rust, this is currently infeasible due to atomics issues). Fedora is a notable outlier, but does not actually have i686 support - that target is used for multilib only, and all x86_64 processors support at least the featureset of the Pentium 4. If this proposal is accepted, @cuviper has expressed willingness to update Fedora such that their rustc's baseline target remains the same as it currently is (including SSE2 support). Other distributions which only offer i686 targets for multilib support on 64-bit hosts can easily follow suit.

The Windows, VxWorks and UEFI i686 targets are proposed to be left alone. Currently, the minimum supported Windows version in Rust is Windows 7, which requires a baseline of a Pentium 4 as of the March 2018 update. It is extremely unlikely that lowering the baseline for Windows would benefit any user, and extremely likely that it would negatively affect performance for many users, since 32-bit binaries are more common on 64-bit Windows than on 64-bit unix-like platforms. VxWorks is left alone as well - the purpose of this MCP is essentially to fix self-hosting for users with older hardware, and VxWorks is a target that is universally cross-compiled for. Users targeting VxWorks through cross-compilation can set target feature flags as they need. UEFI shares the same rationale, and additionally was not commonplace until nearly a decade after the release of the Pentium 4 and SSE2.

To ensure the relevant users know about this change, it was suggested that a blog post be written, similar to the one done recently for glibc and linux kernel version requirements.. I agree with this suggestion. If accepted I would also propose reaching out to some of the distribution maintainers for Rust packages, particularly for distributions that do not support 32-bit hosts, to ensure that they are aware of the change.

Mentors or Reviewers

Process

The main points of the Major Change Process are as follows:

  • File an issue describing the proposal.
  • A compiler team member or contributor who is knowledgeable in the area can second by writing @rustbot second.
    • Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a -C flag, then full team check-off is required.
    • Compiler team members can initiate a check-off via @rfcbot fcp merge on either the MCP or the PR.
  • Once an MCP is seconded, the Final Comment Period begins. If no objections are raised after 10 days, the MCP is considered approved.

You can read more about Major Change Proposals on forge.

Comments

This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.

@goshhhy goshhhy added major-change A proposal to make a major change to rustc T-compiler Add this label so rfcbot knows to poll the compiler team labels Aug 24, 2022
@rustbot
Copy link
Collaborator

rustbot commented Aug 24, 2022

This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.

cc @rust-lang/compiler @rust-lang/compiler-contributors

@rustbot rustbot added the to-announce Announce this issue on triage meeting label Aug 24, 2022
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Sep 8, 2022
@Fierelier
Copy link

I'd like to see this merged.

librsvg, which is based on Rust and required by GTK, requires SSE2, which breaks almost all GTK apps on hardware that does not have it, despite the distro targeting i686 specifically. I'm not 100% sure if this is related but it could be. I'm just trying to use my computer and this just adds to the confusion.

I think i686 should mean i686.

@workingjubilee
Copy link
Member

workingjubilee commented Jan 26, 2023

Since we have discussed this extensively on Zulip, and a consensus is emerging on how we should address this, I feel it is prudent to publicly document roughly what the consensus is arriving at:

As some users do still use a divergent interpretation of i686 in a similar sense to how Rust does, quite deliberately, including the "Red Hat" distros but also openSUSE, we have begun to desire not only to make this change but to add an i786-unknown-linux-gnu target (a target that is recognized by autotools) or i686v1-unknown-linux-gnu target (with a relationship as an x86_64v1 vs. x86_64v2 target... so, i686v1 is a 32-bit x86 CPU that would otherwise fulfill AMD64 ABI requirements, i686v0 would be the Pentium Pro "baseline", i686v2 would be one with SSE4.2, etc). In other words, a properly named "it's a Pentium 4" target. Then i686-unknown-linux-gnu would have its requirements lowered appropriately.

This is because it is commonly used, so making it easy to use is important, and because it will be easier to maintain first-in-class 32-bit support for targets with hardware that supports assumptions made early in Rust's development. Namely: that floating point types use fixed widths and do not engage in "float promotion" (and thus do not experience the harms of double rounding), and that there is one effective suite of float registers in use, not two with different floating point functionality. These are just some issues that reconciling Rust with only using the x87 FPU will encounter, and while I, personally, will be dedicating some time to working on such problems, we largely do not think such heroics should be required in the compiler behavior for a tier 1 target. This also implies demoting the i686-unknown-linux-gnu target to tier 2 with host tools.

The consensus is that, while this will have some gotchas, and we will have to add enhanced support to the cc crate amongst other ecosystem tools, and it may break some build scripts that code directly against target triple strings or require other adjustments, this will generally not break Rust code "per se" due to the semantics of #[cfg] not depending on that, or at least not in ways that it isn't already broken, and that it will help fix many existing problems. As more and more Rust code is shipped and depended on, the status quo is already disruptive, if only to a small set of users, so there is little merit in entirely avoiding disrupting things for that small set of users when trying to fix things for them. The main trick will be user education and to handle host and stdlib distribution appropriately.

@workingjubilee
Copy link
Member

I made my summary post on the apparent consensus on Jan 26. At the time, it seemed correct.

Then on Jan 28, it was noted that Clang has a very... interesting interpretation of i686-unknown-linux-gnu. Specifically:

  • Clang's i686-unknown-linux-gnu default matches our definition, thus Fedora's and so on
  • If you supply -march=i686 to clang you get the "correct" ("Pentium Pro") results (???)

This was a bit of a temperature shock since, while LLVM may not be our only code generator, it is the premiere backend, and cross-language link-time optimization is very valuable. Losing compatibility with Clang here could result in notable regressions for a lot of the legacy x86 ecosystem actively using Rust, as not only do they lose SSE2, but cross-language LTO is hindered, as it's correct to inline Pentium Pro-compatible functions into Pentium 4 code, but not the other way around. That's much more opaque and confusing, and it would be more likely to be a silent regression. If our primary concern is fixing software that uses Rust as a component so that it plays well with C, which includes e.g. display managers which may be large and performance sensitive, where LTO could significantly increase their size or degrade their performance on top of giving up SSE2 acceleration, and do so silently, potentially affecting cross-compiling and the like...

Well. That's bad!

People sat and chewed on that one a bit. As visible, no one has seconded this proposal yet. Then we started discussing the ecosystem concerns a bit more intently with further feedback from Rust members more active in maintaining the cc-rs crate. Also noted was that the big difference between i586, i686 and i786 under this proposal would be:

  • i786: SSE2 (ABI impact + improvements in functional correctness, performance, etc.)
  • i686: ...CMOV I guess?
  • i586: CPUID and CMPXCHG8B, so a lot of fundamental x86 ecosystem tools

So... the resultant i686 target would be at significant risk of being an awkward in-between that isn't really anyone's primary concern. While this may be more "correct", we're not sure it's worth the churn anymore. It's started seeming like #543 was really the right way to go to begin with, as while it doesn't fix things for Debian or other distros that support i686 and actually use the "Pentium Pro" definition, promoting i586-unknown-linux-gnu to having host tools would at least solve the bootstrap problem decisively for most 32-bit Linux distros, which can matter a lot for source-only ones.

It's also worth noting that if the Linux kernel follows up on a recently-discussed intention to drop i486 support and require i586, supporting the exact minimum the kernel requires going forward for that target would help.

@Fierelier
Copy link

Fierelier commented Feb 22, 2023

I'm not sure if I understand the part about clang and i686-unknown-linux-gnu correctly. Do you mean that it defines it as having SSE2? If so, where is this written?


If I understand correctly, please correct me when I'm wrong, the main concern is speed?

Yes, demoting i686 to not using SSE2 nor SSE would reduce speed for those currently using i686 successfully on SSE2 compatible hardware. It would definitely be a regression to them.

But I just feel like it would be good to get this technicality right, for the sake of it aligning with most other software, and reducing complications when i686 is truly wished for (from a distro's perspective, it often is).

Users and distros should probably migrate to a Pentium 4 target in cases where pure i686 is too slow for their purpose.

Perhaps as a bit of a compromise, users using i686 on a CPU with SSE2 could be notified in some way by the compiler, perhaps by probing the available CPU extensions? Another compromise could perhaps be to compile for i686 but to tune for Pentium 4, so -march=i686 -mtune=pentium4?


If you do happen to end up going along with the proposal, I'm curious about the naming. Would the i786 not be a Pentium 3 like chip, containing SSE but not SSE2?


I understand if you would rather just offer i586 host tools instead.

@bjorn3
Copy link
Member

bjorn3 commented Feb 22, 2023

If I understand correctly, please correct me when I'm wrong, the main concern is speed?

Also correctness. When using x87 instead of SSE floats, you will have to deal with the fact that x87 uses 80bit floats instead of the 32bit or 64bit floats you wrote as user. This causes rounding errors. And not only that, but if the value needs to be spilled to the stack or otherwise written to memory, they are rounded causing a double rounding issue and in the case of spilling you can't predict when the rounding will happen.

@nikic
Copy link
Contributor

nikic commented Mar 11, 2023

Closing this as declined, as the alternative proposal #543 has been accepted.

@nikic nikic closed this as not planned Won't fix, can't repro, duplicate, stale Mar 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major-change A proposal to make a major change to rustc T-compiler Add this label so rfcbot knows to poll the compiler team
Projects
None yet
Development

No branches or pull requests

7 participants