This is an archive of the discontinued LLVM Phabricator instance.

[WebAssembly] Merge used feature sets, update atomics linkage policy
ClosedPublic

Authored by tlively on Mar 20 2019, 6:55 PM.

Details

Summary

It does not currently make sense to use WebAssembly features in some functions
but not others, so this CL adds an IR pass that takes the union of all used
feature sets and applies it to each function in the module. This allows us to
prevent atomics from being lowered away if some function has opted in to using
them. When atomics is not enabled anywhere, we detect whether there exists any
atomic operations or thread local storage that would be stripped and disallow
linking with objects that contain atomics if and only if atomics or tls are
stripped. When atomics is enabled, mark it as used but do not require it of
other objects in the link. These changes allow libraries that do not use atomics
to be built once and linked into both single-threaded and multithreaded
binaries.

Event Timeline

tlively created this revision.Mar 20 2019, 6:55 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 20 2019, 6:55 PM
aheejin added inline comments.Mar 21 2019, 5:27 AM
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
292

Does this work in case we don't specify +matomics in the command line but only some of functions contains +matomics in their function attributes? In that case the TM's UsedFeatures set will be updated as we go, but we query the info before we look into any functions here.

(I know it's preexisting; I think I didn't review the previous CL that added this part. And I may not have the full context of your recent target feature section related CLs, in which case this may be a dumb question)

tlively marked an inline comment as done.Mar 21 2019, 11:25 AM
tlively added inline comments.
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
292

You're right that this is kind of subtle and that all the used features are not known at this point, but I think that the code behaves reasonably as written. If +atomics is not provided to the TargetMachine then all atomics and tls will be stripped. If some function later on enables atomics, then atomics will be added to the WebAssemblyTargetMachine's UsedFeatures, but since all atomics will have already been stripped, the output will still not contain any atomics. Since atomics were stripped, the target feature section correctly gets -atomics, even though they were "used".

However, I think a better design would be to add an IR pass to precompute all of the features used in the module. This would allow me to remove the mutable qualifier from UsedFeatures and would make the WebAssemblyTargetMachine safe to use for multiple modules. It would also allow us to strip atomics and tls only if no function in the module enables atomics, which is more consistent with how we treat features in the target features section.

tlively updated this revision to Diff 191809.Mar 21 2019, 5:47 PM
  • Calculate and use union of features used in module before starting instruction selection.
tlively retitled this revision from [WebAssembly] Set "atomics" linkage depending on stripped ops or tls to [WebAssembly] Merge used feature sets, update atomics linkage policy.Mar 21 2019, 6:06 PM
tlively edited the summary of this revision. (Show Details)
tlively updated this revision to Diff 191812.Mar 21 2019, 6:19 PM
  • Remove unnecessary test and small cleanup

Mostly LGTM. Some nits and questions:

llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
237

Then when is the atomics feature 'required' (WASM_FEATURE_PREFIX_REQUIRED) now? Shouldn't it be required when it is in the used the and WasmTM.getAtomicsStripped() is false?

llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
84

Where is this function used?

llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
202

Does this mean the features string always ends with a comma?

207

clang-format?

210
  • Do we need to do this to unify features between functions?
  • Why do we remove target-cpu?
292

I agree that would be probably a better and safer design. By the way is there any case we use an instance of WebAssemblyTargetMachine for multiple modules?

llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
50

The argument here can be const FeatureBitSet &

51–53

If this function is marked const, I guess it is supposed to return const FeatureBitSet &, considering now UsedFeatures is not a mutable member anymore?

52

We may not need that now, but probably this can be

void setAtomicsStripped(bool Value = true) { AtomicsStripped = V; }

to enable turning off the feature too.

tlively planned changes to this revision.Mar 27 2019, 2:53 PM
tlively marked 5 inline comments as done.
tlively added inline comments.
llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
237

Currently WASM_FEATURE_PREFIX_REQUIRED is not used for anything. Originally we were using it as you described, but the problem is that if normal code with atomic ops has =atomics then it would not be linkable with thread-neutral libs like libpng. Using +atomics and -atomics instead of =atomics and -atomics is still safe with respect to stripped atomic ops, but also allows for thread-neutral objects.

We could entirely remove WASM_FEATURE_PREFIX_REQUIRED without breaking anything, but some people (Dan mostly) have expressed interest in a mode where all used features are strictly required. I'm not convinced that's useful, but I don't want to close the door on it either. Another potential use for WASM_FEATURE_PREFIX_REQUIRED would be enforcing ABI compatibility.

llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
84

Called by AtomicExpand::runOnFunction in AtomicExpandPass.cpp to determine whether any work needs to be done for that function. This lets us unconditionally run the AtomicExpandPass when we are setting up IR passes and defer the decision about whether or not to the expand atomics to pass run time.

llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
202

Yes. This doesn't appear to change its semantics and it makes the code slightly simpler.

210

Yes, this is the part where we unify all the features. We remove target-cpu because any features it has enabled will be represented in the new target-features string, so it is redundant.

292

@dschuff just helped me investigate this, and it turns out WebAssemblyTargetMachine can be used to compile multiple modules. This means that we have to store the relevant information somewhere else. I believe attaching the target features as metadata to the Module itself is the best way to go. The Module is already supplied in the WebAssemblyAsmPrinter and obviously the Module is not reused between compilations. This will actually be a big code simplification!

tlively updated this revision to Diff 192542.Mar 27 2019, 4:46 PM
tlively marked an inline comment as done.
  • Switch to storing target feature information as Module metadata
tlively marked an inline comment as done.Mar 27 2019, 4:49 PM
tlively added inline comments.
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
207

Turns out my monorepo did not have my git hooks for this :( Should be fixed now.

aheejin accepted this revision.Mar 28 2019, 11:26 AM

LGTM w/ nits. I like we can use module metadata this way.

llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
199

Nit: Could be const FeatureBitSet &

224

Nit: Can we have {}s for outer loops too, because the inner loop has it?

261

Why is this an error? If module A uses a feature and B does not use it, doesn't the merged module use it? So shouldn't this be Module::ModFlagBehavior::Override too?

292

Just curious. In which case WebAssemblyTargetMachine is used to compile multiple modules?

This revision is now accepted and ready to land.Mar 28 2019, 11:26 AM
tlively updated this revision to Diff 192746.Mar 28 2019, 5:00 PM
tlively marked 6 inline comments as done.
  • Address comments
  • gracefully handle invalid metadata
  • do not emit empty producers sections
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
261

The Error behavior only kicks in if two modules with different values for the same flag are merged. If a module with some flag is merged with another module without that flag, then there is no error. Since I do not emit metadata for unused features, this should not be a problem. Thinking about this more, I think the Override behavior for disallowed atomics should actually be Error to avoid a situation where a merged module uses atomics but also has atomics marked disallowed.

292

In llc there is an option to compile a module twice to make sure the results are the same. This option makes a clone of the input module and uses the same PassRunner (and therefore the same TargetMachine) to compile both of them. In that case this isn't actually a problem because the modules are the same, but it shows that some other tool (maybe a compile server) would be allowed to reuse the same TargetMachine for multiple modules.

This revision was automatically updated to reflect the committed changes.