tool-conventions icon indicating copy to clipboard operation
tool-conventions copied to clipboard

Enabling features by default in LLVM

Open tlively opened this issue 4 years ago • 43 comments

I know we discussed this a while ago, but I forget what exactly we came up with @aheejin @dschuff @sbc100 @sunfishcode. IIRC, it wasn't too different from enabling new features once the following two conditions are satisfied:

  • The feature has been in phase 4 for six months.
  • All major browsers have shipped it.

Am I remembering that correctly? (I couldn't find this discussion in our notes). Should there be a time delay on the second condition as well? I'm thinking about this because multivalue and mutable globals might be eligible to be turned on by default. If so, it would be nice to get that in before LLVM 12 is cut.

tlively avatar Dec 21 '20 23:12 tlively

Thanks for reviving this issue. I seem to remember it was something I meant to do a while back.

Aside from the issue of what to do when in LLVM, did we agree that binaryen and emscripten should be in sync with LLVM (i.e. was there any reason not to have them all be in sync?)

sbc100 avatar Dec 22 '20 17:12 sbc100

I don't remember having discussed what to do with other tools, but IMO having them match LLVM seems reasonable.

tlively avatar Dec 22 '20 18:12 tlively

Same with WABT. You don't really want these tools to error on every LLVM generated binary because --enable-* was omitted.

aardappel avatar Dec 22 '20 18:12 aardappel

For Binaryen this generally wouldn't be an issue because it reads the target features section by default. I assume WABT is more frequently used with binaries that have had their target features section stripped, though.

tlively avatar Dec 22 '20 18:12 tlively

Yeah I think it makes sense for all tools to stay in sync. They should all probably strive for an --mvp mode that can be set on the command line for folks that don't like progress.

sbc100 avatar Dec 22 '20 20:12 sbc100

Is this criteria decided? As someone who works in non-web browser wasm32-wasi scenarios, making this tied to browser release cycle makes it different from all other rustc targets and at a pace where it's not ideal for anything other than web.

The feature has been in phase 4 for six months. All major browsers have shipped it.

What's the mechanism to decide this as doing things in this way hurts places like IOT, or others where HOST programs cannot be updated due to various reasons at the same pace. This essentially locks application writers that target wasm to run on those host programs to a particular rust version (as WASM and WASI evolve). In the case of wasi, this may be alleviated by having stdlibs independent of rustc releases (not possible today tho).

E.g. if we could use the latest rust with a stdlib from 3 versions ago, then the addition of new wasi capabilities for wasm32-wasi targets won't really affect this type of use-cases.

This also goes towards a more philosophical discussion of what does it mean to have targets in stable rust and what guarantees those build targets are going to be held against but this is probably not the right forum to discuss it I think.

AlexEne avatar Mar 11 '21 19:03 AlexEne

Presumably rust, like any other toolchain, will need some way to disable certainly features at compile time if they hope to target older/legacy runtimes? If not, then its output would only be use-able on platforms that support the same set of defaults (i.e. no legacy targets).

Another option for toolchains (other than allowing feature selection on the command line) is to use a tool like binaryen to remove the use of certain features, post link. This would allow the compiler itself to be less configurable, and delay feature selection until a late phase. (Obviously this only works for features that can be polyfilled or re-written away)

sbc100 avatar Mar 11 '21 20:03 sbc100

I like the disable feature for defaults that break backwards compatibility. E.g. Threads won't break anything as now for example rust panics whenever you try to instantiate a thread, so having it panic because it can't find some functionality after threads are moved into the default feature set doesn't really qualify as breaking.

But in the case they are breaking, we could add flags to disable those once they move into the default set of features. The case i'm describing isn't the majority so adding some flags to remove breaking stuff makes sense

AlexEne avatar Mar 12 '21 14:03 AlexEne

As well is individual features tools can/should probably provide an --mvp flag of some find to remove all non-mvp features. I believe binaryen, wabt and llvm already support this.

sbc100 avatar Mar 12 '21 15:03 sbc100

The proposed wording at the top of this issue talks about browsers, which doesn't address major non-Web engines. And even among browsers, there are different versions. And the idea of documenting a 6-month waiting period feels too rigid. Some features have taken engines longer to implement. Others were implemented before reaching stage 4.

Even if we wrote words to pin these things down more, for the foreseeable future I expect we'd still end up adding an informal decision-making on top for each feature anyway. So I've now added a comment to this proposed LLVM patch which just says:

+// This includes features that have achieved phase 4 of the standards process,
+// and that are expected to work for most users in the current time, with
+// consideration given to available support in relevant engines and tools, and
+// the importance of the features.

sunfishcode avatar Oct 18 '22 19:10 sunfishcode

I agree some amount of informal reasoning is necessary.

But I do hope we can do that in a cross-ecosystem way, that is, avoid differences between toolchains. In some sense maybe it's ok if say Emscripten is web-focused and makes choices based on browsers, and WASI-libc is server-focused and chooses based on server VMs, and maybe those choices end up different sometimes. But if it would be possible to make a single set of decisions across the entire ecosystem I think that simplicity would have benefits.

kripken avatar Oct 18 '22 20:10 kripken

@kripken Do you have a concern about the wording of the comment above, or about the selection of proposed features in the patch: bulk-memory, mutable-globals, nontrapping-fptoint, and sign-ext?

sunfishcode avatar Oct 18 '22 20:10 sunfishcode

The wording seems ok to me. About the selection, I'd be happiest if we knew we were also going to enable those precise features in Emscripten shortly. I'm not sure of current plans there (@sbc100 @dschuff ?).

But I guess my larger suggestion is, it might be nice if we decided at the level of the entire ecosystem on the set of features rather than doing so in separate toolchains. I don't feel terribly strongly, though - I think that would have benefits, but minor, so if it slows progress maybe it's not worth it.

kripken avatar Oct 18 '22 20:10 kripken

In terms of switching emscripten defaults, we need to decide when we're ready to break users on old devices with the default build, and finish getting the tools and/or documentation in place to help developers target them.

For the first question, the long pole on the web is nontrapping and bulk memory, shipped in Safari/iOS 15, which Apple says is on about 90% of phones and 80% of tablets released in the last 4 years. If we don't like those numbers, we could just enable mutable-gobals and signext as they have been out for longer. Of those I might guess that nontrapping-fptoint would be the most valuable because of the extra blocks we have to insert to implement LLVM IR's version of FP to int conversion.

Then we need to decide whether we want to expand the use of the -s MIN_SAFARI_VERSION etc flags at compile time, or lower features away at link time with Binaryen as mentioned above, or just have a doc that says "if you want to target Safari 15, use the following feature flags".

Regarding the ecosystem I think it would be nice to all move together too, and if we can get get this first step coordinated we'd at least have done the easy first step. It wouldn't necessarily surprise me if there were some SDK in the future that went their own way; that was basically the sentiment expressed above that people might not want to wait on Safari to implement something to enable a feature in some completely unrelated embedding. But if we coordinate LLVM itself, at lease we're applying a nudge in that direction.

dschuff avatar Oct 18 '22 22:10 dschuff

I've now updated D125729 to remove bulk-memory and nontrapping-fptoint. Does anyone have any objections to the patch now?

sunfishcode avatar Oct 18 '22 23:10 sunfishcode

sgtm. It does seem safer to not enable features by default that won't work on almost 20% of a major platform like iPhone, since it says only 82% of all iPhones are at 15. (I don't see a reason to focus on just those released in the last 4 years @dschuff ?)

Also just 72% of iPads, which is a smaller market, but still that's almost 30%.

I guess iOS ties major Safari updates to OS updates? Especially unfortunate as apps can't ship their own browser engines.

kripken avatar Oct 19 '22 15:10 kripken

Technically, on ios & mac, safari updates are not always connected to os upgrades.

fgmccabe avatar Oct 19 '22 16:10 fgmccabe

@fgmccabe Major versions, or security updates? (I did some searching and can't find a clear answer, but I'm not an Apple user so maybe I don't know the right terms.)

kripken avatar Oct 19 '22 17:10 kripken

Definitely both. It's a mostly transparent process on ios: apps are 'just updated' every so often, whenever the developer releases a new version. This appears similar to how chrome is updated in the background too.

fgmccabe avatar Oct 19 '22 17:10 fgmccabe

@fgmccabe, that seems to contradict the information that apple supplies on how to update safari: https://support.apple.com/en-us/HT204416: "If a Safari update is available, you can get it by following the steps to update or upgrade macOS, iOS, or iPadOS." I'm not an iOS user so don't have first hand information, but are you sure? Where are you getting your information about this from?

sbc100 avatar Oct 19 '22 17:10 sbc100

Well, I have seen those message too. I have also experienced it being upgraded without (esp on ios). But, my experience is stricly anecdotal.

fgmccabe avatar Oct 19 '22 17:10 fgmccabe

On macOS, it's definitely possible (at least in recent times) to update just Safari alone (though not always to the latest Safari version if your version of macOS is old enough that support has been dropped). For example, if I'm on macOS major version N - 1 (where N is the latest), sometimes the latest Safari is available as a standalone update. The Safari version history on Wikipedia shows that each release is available for multiple macOS versions:

image

On iOS, as far as I've seen over the last ~5 years at least, Safari is always tied to the overall iOS system version. I have iOS app auto-updates disabled and review each app updates manually before installing them. I do not recall seeing a Safari standalone update on iOS. Once again, the Safari version history on Wikipedia supports this by showing each Safari is connected to an iOS version:

image

So to summarise, AFAIK only macOS allows installing Safari separately from the overall OS version. In recent times, only the previous 1 or 2 macOS versions have been supported by the latest version of Safari.

@fgmccabe, that seems to contradict the information that apple supplies on how to update safari: support.apple.com/en-us/HT204416: "If a Safari update is available, you can get it by following the steps to update or upgrade macOS, iOS, or iPadOS."

That wording doesn't really help with this particular question because (at least on macOS where I have seen standalone Safari updates before), they are delivered through the same settings UI flow for upgrading the overall system version. You have to manually choose to install only the Safari update and not the latest macOS (they appear as separate line items that can each be unchecked).

jryans avatar Oct 19 '22 20:10 jryans

As an update here, D125729 updating LLVM to enable mutable-globals and signext has now landed.

sunfishcode avatar Nov 09 '22 20:11 sunfishcode

multivalue and mutable globals might be eligible to be turned on by default. If so, it would be nice to get that in before LLVM 12 is cut

While this didn't happen, what about enabling multi-value by default in LLVM 18 or 19 (can look into a PR if this might be a good idea)? Considering the guideline that was added in D125729 about what to enable by default, implementation support as well as the utility value (see for instance this comment):

// This includes features that have achieved phase 4 of the standards process, // and that are expected to work for most users in the current time, with // consideration given to available support in relevant engines and tools, and // the importance of the features.

fornwall avatar Dec 06 '23 10:12 fornwall

Regarding multivalue specifically, it would be good to verify that enabling it does not cause any regressions. My specific concern is that wasm-opt's handling of multivalue is not yet optimal (though it has improved).

kripken avatar Dec 06 '23 19:12 kripken

Regarding multivalue specifically, it would be good to verify that enabling it does not cause any regressions. My specific concern is that wasm-opt's handling of multivalue is not yet optimal (though it has https://github.com/WebAssembly/binaryen/pull/5937).

Good point! I'll experiment a bit with wasm-opt and multivalue to see code size and benchmark differences. Would be good if anyone has input or experience with the readiness of the webassembly ecosystem in general, regarding potentially enabling multivalue by default in LLVM next year.

For rust https://github.com/rust-lang/rust/issues/73755 is (finally!) resolved, but wasm-bindgen support remains: https://github.com/rustwasm/wasm-bindgen/issues/3552.

fornwall avatar Dec 07 '23 11:12 fornwall

I might recommend opening a dedicated issue for enabling multi-value for discussion there since this issue itself isn't necessarily about that specifically. Multi-value is tricky because if it changes the default ABI then it's a breaking change, unlike many other features in LLVM which aren't breaking like sign-extension-ops which only enables a few extra instructions to get emitted. If the intention is to not change the default ABI, however, then compatibility shouldn't be necessary since using multi-value in the ABI would be opt-in.

alexcrichton avatar Dec 07 '23 15:12 alexcrichton

I happened to have an offline discussion w/ some people here today about enabling more features including multivalue by default in LLVM. Syncing Binaryen sounds good too, if people can always fall back to --mvp or equivalent.

One thing @tlively pointed out was enabling multivalue feature by default in clang does NOT automatically cause LLVM to use the multivalue ABI and thus change the code quality. Enabling multivalue feature in the features section is separate from opting to use the multivalue ABI, which is currently controlled by a separate option and not very much used or tested. Given that it is not gonna cause the changes some people here were concerned about, I don't see much downsides in enabling some more features that have been standardized (= reached Phase 5) for years at this point.

I think we can probably enable these by default at this point:

  • multivalue
  • nontrapping-fptoint

How do people feel about these? reference-types seems harmless. Does enabling bulk-memory change something in generated code by default?

  • reference-types
  • bulk-memory

aheejin avatar Feb 05 '24 22:02 aheejin

Enabling bulk-memory does change how memset and memcpy calls are lowered, but that should be fine. It may change how small on-stack memory copies are lowered as well, but I don't remember the details there.

tlively avatar Feb 05 '24 23:02 tlively

I tried enabling four more features (multivalue, nontrapping-fptoint, reference-types, and bulk-memory) in https://github.com/llvm/llvm-project/pull/80923. Comments will be appreciated!

aheejin avatar Feb 07 '24 02:02 aheejin