From 1d24e0ca7693b39bb93dcdf0ae88761370299332 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 25 Oct 2024 13:52:51 -0700 Subject: [PATCH] [WebAssembly] Enable nontrapping-fptoint and bulk-memory by default. (#112049) We were prepared to enable these features [back in February], but they got pulled for what appear to be unrelated reasons. So let's have another try at enabling them! Another motivation here is that it'd be convenient for the [Lime1 proposal] if "lime1" is close to a subset of "generic" (missing only for extended-const). [back in February]: https://github.com/WebAssembly/tool-conventions/issues/158#issuecomment-1931119512 [Lime1 proposal]: https://github.com/llvm/llvm-project/pull/112035 --- clang/docs/ReleaseNotes.rst | 9 ++++++ clang/lib/Basic/Targets/WebAssembly.cpp | 4 +-- .../test/Preprocessor/wasm-target-features.c | 4 +-- lld/test/wasm/custom-section-name.ll | 2 +- lld/test/wasm/data-segments.ll | 2 +- lld/test/wasm/lto/Inputs/libcall-archive.ll | 4 ++- lld/test/wasm/lto/libcall-archive.ll | 4 ++- lld/test/wasm/lto/stub-library-libcall.s | 4 +-- llvm/docs/ReleaseNotes.md | 9 ++++++ llvm/lib/Target/WebAssembly/WebAssembly.td | 3 +- .../WebAssemblyFixFunctionBitcasts.cpp | 2 ++ .../WebAssembly/WebAssemblyTargetMachine.cpp | 29 +++++++++++++++---- .../WebAssembly/cfg-stackify-eh-legacy.ll | 10 +++---- .../WebAssembly/target-features-cpus.ll | 8 ++++- .../WebAssembly/extern-functype-intrinsic.ll | 4 +-- llvm/test/MC/WebAssembly/libcall.ll | 2 +- 16 files changed, 74 insertions(+), 26 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 170c4cc280537f..6a95337815174b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -690,6 +690,15 @@ NetBSD Support WebAssembly Support ^^^^^^^^^^^^^^^^^^^ +The default target CPU, "generic", now enables the `-mnontrapping-fptoint` +and `-mbulk-memory` flags, which correspond to the [Bulk Memory Operations] +and [Non-trapping float-to-int Conversions] language features, which are +[widely implemented in engines]. + +[Bulk Memory Operations]: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md +[Non-trapping float-to-int Conversions]: https://github.com/WebAssembly/spec/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md +[widely implemented in engines]: https://webassembly.org/features/ + AVR Support ^^^^^^^^^^^ diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index 4c9df6007b7823..0b380bdf835ffb 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -154,20 +154,20 @@ bool WebAssemblyTargetInfo::initFeatureMap( llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector &FeaturesVec) const { auto addGenericFeatures = [&]() { + Features["bulk-memory"] = true; Features["multivalue"] = true; Features["mutable-globals"] = true; + Features["nontrapping-fptoint"] = true; Features["reference-types"] = true; Features["sign-ext"] = true; }; auto addBleedingEdgeFeatures = [&]() { addGenericFeatures(); Features["atomics"] = true; - Features["bulk-memory"] = true; Features["exception-handling"] = true; Features["extended-const"] = true; Features["fp16"] = true; Features["multimemory"] = true; - Features["nontrapping-fptoint"] = true; Features["tail-call"] = true; Features["wide-arithmetic"] = true; setSIMDLevel(Features, RelaxedSIMD, true); diff --git a/clang/test/Preprocessor/wasm-target-features.c b/clang/test/Preprocessor/wasm-target-features.c index 14d2fbf4423d32..71b7cf6a5d43cc 100644 --- a/clang/test/Preprocessor/wasm-target-features.c +++ b/clang/test/Preprocessor/wasm-target-features.c @@ -163,8 +163,10 @@ // RUN: -target wasm64-unknown-unknown -mcpu=generic \ // RUN: | FileCheck %s -check-prefix=GENERIC-INCLUDE // +// GENERIC-INCLUDE-DAG: #define __wasm_bulk_memory__ 1{{$}} // GENERIC-INCLUDE-DAG: #define __wasm_multivalue__ 1{{$}} // GENERIC-INCLUDE-DAG: #define __wasm_mutable_globals__ 1{{$}} +// GENERIC-INCLUDE-DAG: #define __wasm_nontrapping_fptoint__ 1{{$}} // GENERIC-INCLUDE-DAG: #define __wasm_reference_types__ 1{{$}} // GENERIC-INCLUDE-DAG: #define __wasm_sign_ext__ 1{{$}} // @@ -176,12 +178,10 @@ // RUN: | FileCheck %s -check-prefix=GENERIC // // GENERIC-NOT: #define __wasm_atomics__ 1{{$}} -// GENERIC-NOT: #define __wasm_bulk_memory__ 1{{$}} // GENERIC-NOT: #define __wasm_exception_handling__ 1{{$}} // GENERIC-NOT: #define __wasm_extended_const__ 1{{$}} // GENERIC-NOT: #define __wasm__fp16__ 1{{$}} // GENERIC-NOT: #define __wasm_multimemory__ 1{{$}} -// GENERIC-NOT: #define __wasm_nontrapping_fptoint__ 1{{$}} // GENERIC-NOT: #define __wasm_relaxed_simd__ 1{{$}} // GENERIC-NOT: #define __wasm_simd128__ 1{{$}} // GENERIC-NOT: #define __wasm_tail_call__ 1{{$}} diff --git a/lld/test/wasm/custom-section-name.ll b/lld/test/wasm/custom-section-name.ll index b860ef5a83e836..8799fbf36056d1 100644 --- a/lld/test/wasm/custom-section-name.ll +++ b/lld/test/wasm/custom-section-name.ll @@ -1,4 +1,4 @@ -; RUN: llc -filetype=obj %s -o %t.o +; RUN: llc -filetype=obj -mattr=-bulk-memory %s -o %t.o ; RUN: wasm-ld -no-gc-sections --no-entry -o %t.wasm %t.o ; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes=CHECK,NO-BSS ; RUN: wasm-ld -no-gc-sections --no-entry --import-memory -o %t.bss.wasm %t.o diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll index 670ac3c1f373fa..41868a0b2b50b6 100644 --- a/lld/test/wasm/data-segments.ll +++ b/lld/test/wasm/data-segments.ll @@ -1,4 +1,4 @@ -; RUN: llc --mtriple=wasm32-unknown-unknown -filetype=obj %s -o %t.atomics.o -mattr=+atomics +; RUN: llc --mtriple=wasm32-unknown-unknown -filetype=obj %s -o %t.atomics.o -mattr=+atomics,-bulk-memory ; RUN: llc --mtriple=wasm32-unknown-unknown -filetype=obj %s -o %t.bulk-mem.o -mattr=+bulk-memory ; RUN: llc --mtriple=wasm64-unknown-unknown -filetype=obj %s -o %t.bulk-mem64.o -mattr=+bulk-memory ; RUN: llc --mtriple=wasm32-unknown-unknown -filetype=obj %s -o %t.atomics.bulk-mem.o -mattr=+atomics,+bulk-memory diff --git a/lld/test/wasm/lto/Inputs/libcall-archive.ll b/lld/test/wasm/lto/Inputs/libcall-archive.ll index 9d05efdeae0806..7d8c34196dfe49 100644 --- a/lld/test/wasm/lto/Inputs/libcall-archive.ll +++ b/lld/test/wasm/lto/Inputs/libcall-archive.ll @@ -1,6 +1,8 @@ target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target triple = "wasm32-unknown-unknown" -define void @memcpy() { +define void @memcpy() #0 { ret void } + +attributes #0 = { "target-features"="-bulk-memory" } diff --git a/lld/test/wasm/lto/libcall-archive.ll b/lld/test/wasm/lto/libcall-archive.ll index 2f785b98976ec8..5c46d2f7ed7838 100644 --- a/lld/test/wasm/lto/libcall-archive.ll +++ b/lld/test/wasm/lto/libcall-archive.ll @@ -8,7 +8,7 @@ target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20" target triple = "wasm32-unknown-unknown" -define void @_start(ptr %a, ptr %b) { +define void @_start(ptr %a, ptr %b) #0 { entry: call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 1024, i1 false) ret void @@ -16,6 +16,8 @@ entry: declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) +attributes #0 = { "target-features"="-bulk-memory" } + ; CHECK: - Type: CUSTOM ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: diff --git a/lld/test/wasm/lto/stub-library-libcall.s b/lld/test/wasm/lto/stub-library-libcall.s index ce88a32dd99dc7..d65983c0cf5bf5 100644 --- a/lld/test/wasm/lto/stub-library-libcall.s +++ b/lld/test/wasm/lto/stub-library-libcall.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t_main.o %t/main.s # RUN: llvm-as %S/Inputs/foo.ll -o %t_foo.o # RUN: llvm-as %S/Inputs/libcall.ll -o %t_libcall.o -# RUN: wasm-ld %t_main.o %t_libcall.o %t_foo.o %p/Inputs/stub.so -o %t.wasm +# RUN: wasm-ld -mllvm -mattr=-bulk-memory %t_main.o %t_libcall.o %t_foo.o %p/Inputs/stub.so -o %t.wasm # RUN: obj2yaml %t.wasm | FileCheck %s # The function `func_with_libcall` will generate an undefined reference to @@ -12,7 +12,7 @@ # If %t_foo.o is not included in the link we get an undefined symbol reported # to the dependency of memcpy on the foo export: -# RUN: not wasm-ld %t_main.o %t_libcall.o %p/Inputs/stub.so -o %t.wasm 2>&1 | FileCheck --check-prefix=MISSING %s +# RUN: not wasm-ld -mllvm -mattr=-bulk-memory %t_main.o %t_libcall.o %p/Inputs/stub.so -o %t.wasm 2>&1 | FileCheck --check-prefix=MISSING %s # MISSING: stub.so: undefined symbol: foo. Required by memcpy #--- main.s diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index be51b0af56ddbf..e3d93f0dfd0ec5 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -180,6 +180,15 @@ Changes to the RISC-V Backend Changes to the WebAssembly Backend ---------------------------------- +The default target CPU, "generic", now enables the `-mnontrapping-fptoint` +and `-mbulk-memory` flags, which correspond to the [Bulk Memory Operations] +and [Non-trapping float-to-int Conversions] language features, which are +[widely implemented in engines]. + +[Bulk Memory Operations]: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md +[Non-trapping float-to-int Conversions]: https://github.com/WebAssembly/spec/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md +[widely implemented in engines]: https://webassembly.org/features/ + Changes to the Windows Target ----------------------------- diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.td b/llvm/lib/Target/WebAssembly/WebAssembly.td index 37d99690c25b1f..88628f2a793545 100644 --- a/llvm/lib/Target/WebAssembly/WebAssembly.td +++ b/llvm/lib/Target/WebAssembly/WebAssembly.td @@ -114,7 +114,8 @@ def : ProcessorModel<"mvp", NoSchedModel, []>; // consideration given to available support in relevant engines and tools, and // the importance of the features. def : ProcessorModel<"generic", NoSchedModel, - [FeatureMultivalue, FeatureMutableGlobals, + [FeatureBulkMemory, FeatureMultivalue, + FeatureMutableGlobals, FeatureNontrappingFPToInt, FeatureReferenceTypes, FeatureSignExt]>; // Latest and greatest experimental version of WebAssembly. Bugs included! diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp index a3cc9bae470859..7c3e8d18ad276b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp @@ -111,6 +111,7 @@ static Function *createWrapper(Function *F, FunctionType *Ty) { Function *Wrapper = Function::Create(Ty, Function::PrivateLinkage, F->getName() + "_bitcast", M); + Wrapper->setAttributes(F->getAttributes()); BasicBlock *BB = BasicBlock::Create(M->getContext(), "body", Wrapper); const DataLayout &DL = BB->getDataLayout(); @@ -201,6 +202,7 @@ static Function *createWrapper(Function *F, FunctionType *Ty) { Wrapper->eraseFromParent(); Wrapper = Function::Create(Ty, Function::PrivateLinkage, F->getName() + "_bitcast_invalid", M); + Wrapper->setAttributes(F->getAttributes()); BasicBlock *BB = BasicBlock::Create(M->getContext(), "body", Wrapper); new UnreachableInst(M->getContext(), BB); Wrapper->setName(F->getName() + "_bitcast_invalid"); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp index 3fe6ccf1c608e1..83cd57d0bbdd55 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -233,13 +233,30 @@ class CoalesceFeaturesAndStripAtomics final : public ModulePass { private: FeatureBitset coalesceFeatures(const Module &M) { - FeatureBitset Features = - WasmTM - ->getSubtargetImpl(std::string(WasmTM->getTargetCPU()), - std::string(WasmTM->getTargetFeatureString())) - ->getFeatureBits(); - for (auto &F : M) + // Union the features of all defined functions. Start with an empty set, so + // that if a feature is disabled in every function, we'll compute it as + // disabled. If any function lacks a target-features attribute, it'll + // default to the target CPU from the `TargetMachine`. + FeatureBitset Features; + bool AnyDefinedFuncs = false; + for (auto &F : M) { + if (F.isDeclaration()) + continue; + Features |= WasmTM->getSubtargetImpl(F)->getFeatureBits(); + AnyDefinedFuncs = true; + } + + // If we have no defined functions, use the target CPU from the + // `TargetMachine`. + if (!AnyDefinedFuncs) { + Features = + WasmTM + ->getSubtargetImpl(std::string(WasmTM->getTargetCPU()), + std::string(WasmTM->getTargetFeatureString())) + ->getFeatureBits(); + } + return Features; } diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll index cef92f459e4aa3..24a08267db6fbf 100644 --- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll +++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh-legacy.ll @@ -1,9 +1,9 @@ ; REQUIRES: asserts -; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling | FileCheck %s -; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling | FileCheck %s --check-prefix=NOOPT -; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT -; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS +; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,bulk-memory | FileCheck %s +; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,bulk-memory +; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory | FileCheck %s --check-prefix=NOOPT +; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT +; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll b/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll index 77d1564409f78c..ba10dd94a9838d 100644 --- a/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll +++ b/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll @@ -13,7 +13,10 @@ target triple = "wasm32-unknown-unknown" ; generic: +multivalue, +mutable-globals, +reference-types, +sign-ext ; GENERIC-LABEL: .custom_section.target_features,"",@ -; GENERIC-NEXT: .int8 4 +; GENERIC-NEXT: .int8 6 +; GENERIC-NEXT: .int8 43 +; GENERIC-NEXT: .int8 11 +; GENERIC-NEXT: .ascii "bulk-memory" ; GENERIC-NEXT: .int8 43 ; GENERIC-NEXT: .int8 10 ; GENERIC-NEXT: .ascii "multivalue" @@ -21,6 +24,9 @@ target triple = "wasm32-unknown-unknown" ; GENERIC-NEXT: .int8 15 ; GENERIC-NEXT: .ascii "mutable-globals" ; GENERIC-NEXT: .int8 43 +; GENERIC-NEXT: .int8 19 +; GENERIC-NEXT: .ascii "nontrapping-fptoint" +; GENERIC-NEXT: .int8 43 ; GENERIC-NEXT: .int8 15 ; GENERIC-NEXT: .ascii "reference-types" ; GENERIC-NEXT: .int8 43 diff --git a/llvm/test/MC/WebAssembly/extern-functype-intrinsic.ll b/llvm/test/MC/WebAssembly/extern-functype-intrinsic.ll index 320b65356ba9f3..b321c0c82ad4d3 100644 --- a/llvm/test/MC/WebAssembly/extern-functype-intrinsic.ll +++ b/llvm/test/MC/WebAssembly/extern-functype-intrinsic.ll @@ -1,5 +1,5 @@ -; RUN: llc %s -o - | FileCheck %s -; RUN: llc %s -o - | llvm-mc -triple=wasm32-unknown-unknown | FileCheck %s +; RUN: llc %s -mattr=-bulk-memory -o - | FileCheck %s +; RUN: llc %s -mattr=-bulk-memory -o - | llvm-mc -triple=wasm32-unknown-unknown | FileCheck %s ; ModuleID = 'test.c' source_filename = "test.c" diff --git a/llvm/test/MC/WebAssembly/libcall.ll b/llvm/test/MC/WebAssembly/libcall.ll index 8b81f150da892a..ffd32abe2345bc 100644 --- a/llvm/test/MC/WebAssembly/libcall.ll +++ b/llvm/test/MC/WebAssembly/libcall.ll @@ -1,4 +1,4 @@ -; RUN: llc -filetype=obj %s -o - | obj2yaml | FileCheck %s +; RUN: llc -filetype=obj -mattr=-bulk-memory %s -o - | obj2yaml | FileCheck %s target triple = "wasm32-unknown-unknown"