https://github.com/sunfishcode updated https://github.com/llvm/llvm-project/pull/112035
>From b8f33cd68d11759ad774e16b4d25491a1c9fc3e4 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Fri, 11 Oct 2024 04:30:32 -0700 Subject: [PATCH 1/4] [WebAssembly] Define a new "Trail1" CPU First, define some new target features. These are subsets of existing features that reflect implemenetation concerns: - "call-indirect-overlong" - implied by "reference-types"; just the overlong encoding for the `call_indirect` immediate, and not the actual reference types. - "bulk-memory-opt" - implied by "bulk-memory": just `memory.copy` and `memory.fill`, and not the other instructions in the bulk-memory proposal. Next, define a new target CPU, "Trail1", which enables mutable-globals, bulk-memory-opt, multivalue, sign-ext, nontrapping-fptoint, extended-const, and call-indirect-overlong. Unlike the default "generic" CPU, "trail1" is meant to be frozen, and followed up by "trail2" and so on when new features are desired. --- clang/lib/Basic/Targets/WebAssembly.cpp | 45 +++++++++++++++++++ clang/lib/Basic/Targets/WebAssembly.h | 2 + lld/test/wasm/compress-relocs.ll | 2 +- lld/test/wasm/import-table-explicit.s | 2 +- lld/test/wasm/invalid-mvp-table-use.s | 2 +- lld/wasm/InputFiles.cpp | 11 ++--- lld/wasm/SyntheticSections.cpp | 2 +- .../AsmParser/WebAssemblyAsmParser.cpp | 12 ++--- llvm/lib/Target/WebAssembly/WebAssembly.td | 14 ++++++ .../WebAssembly/WebAssemblyFastISel.cpp | 2 +- .../WebAssembly/WebAssemblyISelLowering.cpp | 2 +- .../WebAssembly/WebAssemblyInstrBulkMemory.td | 15 ++++--- .../WebAssembly/WebAssemblyInstrInfo.td | 8 ++++ .../WebAssemblySelectionDAGInfo.cpp | 4 +- .../Target/WebAssembly/WebAssemblySubtarget.h | 4 ++ .../WebAssembly/WebAssemblyUtilities.cpp | 4 +- llvm/test/CodeGen/WebAssembly/bulk-memory.ll | 6 +-- .../test/CodeGen/WebAssembly/bulk-memory64.ll | 6 +-- 18 files changed, 110 insertions(+), 33 deletions(-) diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index 5ac9421663adea..aa3a2770727c3a 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -47,6 +47,7 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch<bool>(Feature) .Case("atomics", HasAtomics) .Case("bulk-memory", HasBulkMemory) + .Case("bulk-memory-opt", HasBulkMemoryOpt) .Case("exception-handling", HasExceptionHandling) .Case("extended-const", HasExtendedConst) .Case("fp16", HasFP16) @@ -55,6 +56,7 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const { .Case("mutable-globals", HasMutableGlobals) .Case("nontrapping-fptoint", HasNontrappingFPToInt) .Case("reference-types", HasReferenceTypes) + .Case("call-indirect-overlong", HasCallIndirectOverlong) .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD) .Case("sign-ext", HasSignExt) .Case("simd128", SIMDLevel >= SIMD128) @@ -78,6 +80,8 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__wasm_atomics__"); if (HasBulkMemory) Builder.defineMacro("__wasm_bulk_memory__"); + if (HasBulkMemoryOpt) + Builder.defineMacro("__wasm_bulk_memory_opt__"); if (HasExceptionHandling) Builder.defineMacro("__wasm_exception_handling__"); if (HasExtendedConst) @@ -154,12 +158,23 @@ bool WebAssemblyTargetInfo::initFeatureMap( Features["multivalue"] = true; Features["mutable-globals"] = true; Features["reference-types"] = true; + Features["call-indirect-overlong"] = true; Features["sign-ext"] = true; }; + auto addTrail1Features = [&]() { + Features["multivalue"] = true; + Features["mutable-globals"] = true; + Features["call-indirect-overlong"] = true; + Features["sign-ext"] = true; + Features["bulk-memory-opt"] = true; + Features["nontrapping-fptoint"] = true; + Features["extended-const"] = true; + }; auto addBleedingEdgeFeatures = [&]() { addGenericFeatures(); Features["atomics"] = true; Features["bulk-memory"] = true; + Features["bulk-memory-opt"] = true; Features["exception-handling"] = true; Features["extended-const"] = true; Features["fp16"] = true; @@ -170,6 +185,8 @@ bool WebAssemblyTargetInfo::initFeatureMap( }; if (CPU == "generic") { addGenericFeatures(); + } else if (CPU == "trail1") { + addTrail1Features(); } else if (CPU == "bleeding-edge") { addBleedingEdgeFeatures(); } @@ -196,6 +213,14 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( HasBulkMemory = false; continue; } + if (Feature == "+bulk-memory-opt") { + HasBulkMemoryOpt = true; + continue; + } + if (Feature == "-bulk-memory-opt") { + HasBulkMemoryOpt = false; + continue; + } if (Feature == "+exception-handling") { HasExceptionHandling = true; continue; @@ -261,6 +286,14 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( HasReferenceTypes = false; continue; } + if (Feature == "+call-indirect-overlong") { + HasCallIndirectOverlong = true; + continue; + } + if (Feature == "-call-indirect-overlong") { + HasCallIndirectOverlong = false; + continue; + } if (Feature == "+relaxed-simd") { SIMDLevel = std::max(SIMDLevel, RelaxedSIMD); continue; @@ -298,6 +331,18 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( << Feature << "-target-feature"; return false; } + + // The reference-types feature included the change to `call_indirect` + // encodings to support overlong immediates. + if (HasReferenceTypes) { + HasCallIndirectOverlong = true; + } + + // bulk-memory-opt is a subset of bulk-memory. + if (HasBulkMemory) { + HasBulkMemoryOpt = true; + } + return true; } diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 213ec42ca84bb7..b05ad862685ad0 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -55,6 +55,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { bool HasAtomics = false; bool HasBulkMemory = false; + bool HasBulkMemoryOpt = false; bool HasExceptionHandling = false; bool HasExtendedConst = false; bool HasFP16 = false; @@ -63,6 +64,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { bool HasMutableGlobals = false; bool HasNontrappingFPToInt = false; bool HasReferenceTypes = false; + bool HasCallIndirectOverlong = false; bool HasSignExt = false; bool HasTailCall = false; diff --git a/lld/test/wasm/compress-relocs.ll b/lld/test/wasm/compress-relocs.ll index f1faab754cb765..cea9f3476e996a 100644 --- a/lld/test/wasm/compress-relocs.ll +++ b/lld/test/wasm/compress-relocs.ll @@ -1,5 +1,5 @@ ; RUN: llc -filetype=obj %s -o %t.o -; RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o +; RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o ; RUN: wasm-ld --export-dynamic -o %t.wasm %t2.o %t.o ; RUN: obj2yaml %t.wasm | FileCheck %s ; RUN: wasm-ld --export-dynamic -O2 -o %t-opt.wasm %t2.o %t.o diff --git a/lld/test/wasm/import-table-explicit.s b/lld/test/wasm/import-table-explicit.s index 1dc21beba06294..701b7a1dc3e165 100644 --- a/lld/test/wasm/import-table-explicit.s +++ b/lld/test/wasm/import-table-explicit.s @@ -1,4 +1,4 @@ -# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o # RUN: wasm-ld --import-table -o %t.wasm %t.o # RUN: obj2yaml %t.wasm | FileCheck %s diff --git a/lld/test/wasm/invalid-mvp-table-use.s b/lld/test/wasm/invalid-mvp-table-use.s index b4f12a7eeb9a48..58c472e29d1ad4 100644 --- a/lld/test/wasm/invalid-mvp-table-use.s +++ b/lld/test/wasm/invalid-mvp-table-use.s @@ -1,7 +1,7 @@ # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s # # If any table is defined or declared besides the __indirect_function_table, -# the compilation unit should be compiled with -mattr=+reference-types, +# the compilation unit should be compiled with -mattr=+call-indirect-overlong, # causing symbol table entries to be emitted for all tables. # RUN: not wasm-ld --no-entry %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index de8e707ab2b497..604b6e9083e8ca 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -247,10 +247,11 @@ static void setRelocs(const std::vector<T *> &chunks, } } -// An object file can have two approaches to tables. With the reference-types -// feature enabled, input files that define or use tables declare the tables -// using symbols, and record each use with a relocation. This way when the -// linker combines inputs, it can collate the tables used by the inputs, +// An object file can have two approaches to tables. With the +// call-indirect-overlong feature enabled (explicitly, or implied by the +// reference-types feature), input files that define or use tables declare the +// tables using symbols, and record each use with a relocation. This way when +// the linker combines inputs, it can collate the tables used by the inputs, // assigning them distinct table numbers, and renumber all the uses as // appropriate. At the same time, the linker has special logic to build the // indirect function table if it is needed. @@ -276,7 +277,7 @@ void ObjFile::addLegacyIndirectFunctionTableIfNeeded( return; // It's possible for an input to define tables and also use the indirect - // function table, but forget to compile with -mattr=+reference-types. + // function table, but forget to compile with -mattr=+call-indirect-overlong. // For these newer files, we require symbols for all tables, and // relocations for all of their uses. if (tableSymbolCount != 0) { diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index a3bc90cfe759ca..74e3efff4cdfb8 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -326,7 +326,7 @@ void TableSection::addTable(InputTable *table) { // to assign table number 0 to the indirect function table. for (const auto *culprit : out.importSec->importedSymbols) { if (isa<UndefinedTable>(culprit)) { - error("object file not built with 'reference-types' feature " + error("object file not built with 'call-indirect-overlong' feature " "conflicts with import of table " + culprit->getName() + " by file " + toString(culprit->getFile())); diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index ee8686d1166a5b..091b3ffb8b25d2 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -292,7 +292,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { DefaultFunctionTable = getOrCreateFunctionTableSymbol( getContext(), "__indirect_function_table", Is64); - if (!STI->checkFeatures("+reference-types")) + if (!STI->checkFeatures("+call-indirect-overlong")) DefaultFunctionTable->setOmitFromLinkingSection(); } @@ -532,11 +532,11 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { } bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) { - if (STI->checkFeatures("+reference-types")) { - // If the reference-types feature is enabled, there is an explicit table - // operand. To allow the same assembly to be compiled with or without - // reference types, we allow the operand to be omitted, in which case we - // default to __indirect_function_table. + if (STI->checkFeatures("+call-indirect-overlong")) { + // If the call-indirect-overlong feature is enabled, there is an explicit + // table operand. To allow the same assembly to be compiled with or + // without call-indirect overlong, we allow the operand to be omitted, in + // which case we default to __indirect_function_table. auto &Tok = Lexer.getTok(); if (Tok.is(AsmToken::Identifier)) { auto *Sym = diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.td b/llvm/lib/Target/WebAssembly/WebAssembly.td index c632d4a74355d8..7081ee48132a07 100644 --- a/llvm/lib/Target/WebAssembly/WebAssembly.td +++ b/llvm/lib/Target/WebAssembly/WebAssembly.td @@ -29,6 +29,10 @@ def FeatureBulkMemory : SubtargetFeature<"bulk-memory", "HasBulkMemory", "true", "Enable bulk memory operations">; +def FeatureBulkMemoryOpt : + SubtargetFeature<"bulk-memory-opt", "HasBulkMemoryOpt", "true", + "Enable bulk memory optimization operations">; + def FeatureExceptionHandling : SubtargetFeature<"exception-handling", "HasExceptionHandling", "true", "Enable Wasm exception handling">; @@ -63,6 +67,10 @@ def FeatureReferenceTypes : SubtargetFeature<"reference-types", "HasReferenceTypes", "true", "Enable reference types">; +def FeatureCallIndirectOverlong : + SubtargetFeature<"call-indirect-overlong", "HasCallIndirectOverlong", "true", + "Enable overlong encoding for call_indirect immediates">; + def FeatureRelaxedSIMD : SubtargetFeature<"relaxed-simd", "SIMDLevel", "RelaxedSIMD", "Enable relaxed-simd instructions">; @@ -113,6 +121,12 @@ def : ProcessorModel<"generic", NoSchedModel, [FeatureMultivalue, FeatureMutableGlobals, FeatureReferenceTypes, FeatureSignExt]>; +def : ProcessorModel<"trail1", NoSchedModel, + [FeatureMultivalue, FeatureMutableGlobals, + FeatureCallIndirectOverlong, FeatureSignExt, + FeatureBulkMemoryOpt, FeatureNontrappingFPToInt, + FeatureExtendedConst]>; + // Latest and greatest experimental version of WebAssembly. Bugs included! def : ProcessorModel<"bleeding-edge", NoSchedModel, [FeatureAtomics, FeatureBulkMemory, diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 7c90fff2a5c1d7..d84d1f4dedec50 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -899,7 +899,7 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { // The table into which this call_indirect indexes. MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol( MF->getContext(), Subtarget); - if (Subtarget->hasReferenceTypes()) { + if (Subtarget->hasCallIndirectOverlong()) { MIB.addSym(Table); } else { // Otherwise for the MVP there is at most one table whose number is 0, but diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 5f76d666823e28..1b6a7cbf14edfe 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -633,7 +633,7 @@ LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB, MF.getContext(), Subtarget) : WebAssembly::getOrCreateFunctionTableSymbol( MF.getContext(), Subtarget); - if (Subtarget->hasReferenceTypes()) { + if (Subtarget->hasCallIndirectOverlong()) { MIB.addSym(Table); } else { // For the MVP there is at most one table whose number is 0, but we can't diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td index 7aeae54d95a8c9..5ffe0d22d3e112 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td @@ -16,8 +16,7 @@ multiclass BULK_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s, list<dag> pattern_r, string asmstr_r = "", string asmstr_s = "", bits<32> simdop = -1> { defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s, - !or(0xfc00, !and(0xff, simdop))>, - Requires<[HasBulkMemory]>; + !or(0xfc00, !and(0xff, simdop))>; } // Bespoke types and nodes for bulk memory ops @@ -43,13 +42,15 @@ defm MEMORY_INIT_A#B : (outs), (ins i32imm_op:$seg, i32imm_op:$idx), [], "memory.init\t$seg, $idx, $dest, $offset, $size", - "memory.init\t$seg, $idx", 0x08>; + "memory.init\t$seg, $idx", 0x08>, + Requires<[HasBulkMemory]>; let hasSideEffects = 1 in defm DATA_DROP : BULK_I<(outs), (ins i32imm_op:$seg), (outs), (ins i32imm_op:$seg), [], - "data.drop\t$seg", "data.drop\t$seg", 0x09>; + "data.drop\t$seg", "data.drop\t$seg", 0x09>, + Requires<[HasBulkMemory]>; let mayLoad = 1, mayStore = 1 in defm MEMORY_COPY_A#B : @@ -60,7 +61,8 @@ defm MEMORY_COPY_A#B : rc:$dst, rc:$src, rc:$len )], "memory.copy\t$src_idx, $dst_idx, $dst, $src, $len", - "memory.copy\t$src_idx, $dst_idx", 0x0a>; + "memory.copy\t$src_idx, $dst_idx", 0x0a>, + Requires<[HasBulkMemoryOpt]>; let mayStore = 1 in defm MEMORY_FILL_A#B : @@ -68,7 +70,8 @@ defm MEMORY_FILL_A#B : (outs), (ins i32imm_op:$idx), [(wasm_memset (i32 imm:$idx), rc:$dst, I32:$value, rc:$size)], "memory.fill\t$idx, $dst, $value, $size", - "memory.fill\t$idx", 0x0b>; + "memory.fill\t$idx", 0x0b>, + Requires<[HasBulkMemoryOpt]>; } defm : BulkMemoryOps<I32, "32">; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 767ac86f1351b5..05415b658c13aa 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -30,6 +30,10 @@ def HasBulkMemory : Predicate<"Subtarget->hasBulkMemory()">, AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">; +def HasBulkMemoryOpt : + Predicate<"Subtarget->hasBulkMemoryOpt()">, + AssemblerPredicate<(all_of FeatureBulkMemoryOpt), "bulk-memory-opt">; + def HasExceptionHandling : Predicate<"Subtarget->hasExceptionHandling()">, AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">; @@ -68,6 +72,10 @@ def HasReferenceTypes : Predicate<"Subtarget->hasReferenceTypes()">, AssemblerPredicate<(all_of FeatureReferenceTypes), "reference-types">; +def HasCallIndirectOverlong : + Predicate<"Subtarget->hasCallIndirectOverlong()">, + AssemblerPredicate<(all_of FeatureCallIndirectOverlong), "call-indirect-overlong">; + def HasRelaxedSIMD : Predicate<"Subtarget->hasRelaxedSIMD()">, AssemblerPredicate<(all_of FeatureRelaxedSIMD), "relaxed-simd">; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySelectionDAGInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblySelectionDAGInfo.cpp index 74af4c8873f735..3ca0e3f468a6e4 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySelectionDAGInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblySelectionDAGInfo.cpp @@ -23,7 +23,7 @@ SDValue WebAssemblySelectionDAGInfo::EmitTargetCodeForMemcpy( SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { auto &ST = DAG.getMachineFunction().getSubtarget<WebAssemblySubtarget>(); - if (!ST.hasBulkMemory()) + if (!ST.hasBulkMemoryOpt()) return SDValue(); SDValue MemIdx = DAG.getConstant(0, DL, MVT::i32); @@ -47,7 +47,7 @@ SDValue WebAssemblySelectionDAGInfo::EmitTargetCodeForMemset( SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo) const { auto &ST = DAG.getMachineFunction().getSubtarget<WebAssemblySubtarget>(); - if (!ST.hasBulkMemory()) + if (!ST.hasBulkMemoryOpt()) return SDValue(); SDValue MemIdx = DAG.getConstant(0, DL, MVT::i32); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h index f990120775d155..09037436d92dfc 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -41,6 +41,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool HasAtomics = false; bool HasBulkMemory = false; + bool HasBulkMemoryOpt = false; bool HasExceptionHandling = false; bool HasExtendedConst = false; bool HasFP16 = false; @@ -49,6 +50,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool HasMutableGlobals = false; bool HasNontrappingFPToInt = false; bool HasReferenceTypes = false; + bool HasCallIndirectOverlong = false; bool HasSignExt = false; bool HasTailCall = false; @@ -94,6 +96,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasAddr64() const { return TargetTriple.isArch64Bit(); } bool hasAtomics() const { return HasAtomics; } bool hasBulkMemory() const { return HasBulkMemory; } + bool hasBulkMemoryOpt() const { return HasBulkMemoryOpt; } bool hasExceptionHandling() const { return HasExceptionHandling; } bool hasExtendedConst() const { return HasExtendedConst; } bool hasFP16() const { return HasFP16; } @@ -102,6 +105,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasMutableGlobals() const { return HasMutableGlobals; } bool hasNontrappingFPToInt() const { return HasNontrappingFPToInt; } bool hasReferenceTypes() const { return HasReferenceTypes; } + bool hasCallIndirectOverlong() const { return HasCallIndirectOverlong; } bool hasRelaxedSIMD() const { return SIMDLevel >= RelaxedSIMD; } bool hasSignExt() const { return HasSignExt; } bool hasSIMD128() const { return SIMDLevel >= SIMD128; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp index ed186e65a80cf9..ea18caea2b7e1a 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp @@ -117,7 +117,7 @@ MCSymbolWasm *WebAssembly::getOrCreateFunctionTableSymbol( Sym->setUndefined(); } // MVP object files can't have symtab entries for tables. - if (!(Subtarget && Subtarget->hasReferenceTypes())) + if (!(Subtarget && Subtarget->hasCallIndirectOverlong())) Sym->setOmitFromLinkingSection(); return Sym; } @@ -142,7 +142,7 @@ MCSymbolWasm *WebAssembly::getOrCreateFuncrefCallTableSymbol( Sym->setTableType(TableType); } // MVP object files can't have symtab entries for tables. - if (!(Subtarget && Subtarget->hasReferenceTypes())) + if (!(Subtarget && Subtarget->hasCallIndirectOverlong())) Sym->setOmitFromLinkingSection(); return Sym; } diff --git a/llvm/test/CodeGen/WebAssembly/bulk-memory.ll b/llvm/test/CodeGen/WebAssembly/bulk-memory.ll index dc29dc81c13ec2..a2dae3890b1f0e 100644 --- a/llvm/test/CodeGen/WebAssembly/bulk-memory.ll +++ b/llvm/test/CodeGen/WebAssembly/bulk-memory.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+bulk-memory | FileCheck %s --check-prefixes CHECK,BULK-MEM -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=-bulk-memory | FileCheck %s --check-prefixes CHECK,NO-BULK-MEM +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+bulk-memory-opt | FileCheck %s --check-prefixes CHECK,BULK-MEM +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=-bulk-memory-opt | FileCheck %s --check-prefixes CHECK,NO-BULK-MEM -; Test that basic bulk memory codegen works correctly +; Test that basic bulk-memory-opt codegen works correctly target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/CodeGen/WebAssembly/bulk-memory64.ll b/llvm/test/CodeGen/WebAssembly/bulk-memory64.ll index 8ee5f6314381cd..92d66c1abf90b4 100644 --- a/llvm/test/CodeGen/WebAssembly/bulk-memory64.ll +++ b/llvm/test/CodeGen/WebAssembly/bulk-memory64.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+bulk-memory | FileCheck %s --check-prefixes CHECK,BULK-MEM -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=-bulk-memory | FileCheck %s --check-prefixes CHECK,NO-BULK-MEM +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+bulk-memory-opt | FileCheck %s --check-prefixes CHECK,BULK-MEM +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=-bulk-memory-opt | FileCheck %s --check-prefixes CHECK,NO-BULK-MEM -; Test that basic bulk memory codegen works correctly +; Test that basic bulk memory opt codegen works correctly target triple = "wasm64-unknown-unknown" >From 55fc5af799a21f186df2f5a8579da4c6713efe94 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Fri, 11 Oct 2024 17:04:25 -0700 Subject: [PATCH 2/4] Add a target-features-cpus test for trail1. --- .../WebAssembly/target-features-cpus.ll | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll b/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll index 77d1564409f78c..a37abfaf884180 100644 --- a/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll +++ b/llvm/test/CodeGen/WebAssembly/target-features-cpus.ll @@ -1,5 +1,6 @@ ; RUN: llc < %s -mcpu=mvp | FileCheck %s --check-prefixes MVP ; RUN: llc < %s -mcpu=generic | FileCheck %s --check-prefixes GENERIC +; RUN: llc < %s -mcpu=trail1 | FileCheck %s --check-prefixes TRAIL1 ; RUN: llc < %s | FileCheck %s --check-prefixes GENERIC ; RUN: llc < %s -mcpu=bleeding-edge | FileCheck %s --check-prefixes BLEEDING-EDGE @@ -27,6 +28,31 @@ target triple = "wasm32-unknown-unknown" ; GENERIC-NEXT: .int8 8 ; GENERIC-NEXT: .ascii "sign-ext" +; trail1: +bulk-memory-opt, +call-indirect-overlong, +extended-const, +multivalue, +mutable-globals, +nontrapping-fptoint, +sign-ext +; TRAIL1-LABEL: .custom_section.target_features,"",@ +; TRAIL1-NEXT: .int8 6 +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 15 +; TRAIL1-NEXT: .int8 "bulk-memory-opt" +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 22 +; TRAIL1-NEXT: .int8 "call-indirect-overlong" +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 14 +; TRAIL1-NEXT: .ascii "extended-const" +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 10 +; TRAIL1-NEXT: .ascii "multivalue" +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 15 +; TRAIL1-NEXT: .ascii "mutable-globals" +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 19 +; TRAIL1-NEXT: .ascii "nontrapping-fptoint" +; TRAIL1-NEXT: .int8 43 +; TRAIL1-NEXT: .int8 8 +; TRAIL1-NEXT: .ascii "sign-ext" + ; bleeding-edge: +atomics, +bulk-memory, +exception-handling, +extended-const, ; +fp16, +multimemory, +multivalue, +mutable-globals, ; +nontrapping-fptoint, +relaxed-simd, +reference-types, >From 24e58550483c0569e48f9b1e11edaee5acb1ac1e Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Fri, 11 Oct 2024 09:53:30 -0700 Subject: [PATCH 3/4] call-indirect-overlong is implied by reference-types. --- .../AsmParser/WebAssemblyAsmParser.cpp | 15 +++++++++------ llvm/lib/Target/WebAssembly/WebAssembly.td | 9 +++++---- .../lib/Target/WebAssembly/WebAssemblySubtarget.h | 4 ++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index 091b3ffb8b25d2..197d5723804f21 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -292,7 +292,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { DefaultFunctionTable = getOrCreateFunctionTableSymbol( getContext(), "__indirect_function_table", Is64); - if (!STI->checkFeatures("+call-indirect-overlong")) + if (!STI->checkFeatures("+call-indirect-overlong") && + !STI->checkFeatures("+reference-types")) DefaultFunctionTable->setOmitFromLinkingSection(); } @@ -532,11 +533,13 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { } bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) { - if (STI->checkFeatures("+call-indirect-overlong")) { - // If the call-indirect-overlong feature is enabled, there is an explicit - // table operand. To allow the same assembly to be compiled with or - // without call-indirect overlong, we allow the operand to be omitted, in - // which case we default to __indirect_function_table. + if (STI->checkFeatures("+call-indirect-overlong") || + STI->checkFeatures("+reference-types")) { + // If the call-indirect-overlong feature is enabled, or implied by the + // reference-types feature, there is an explicit table operand. To allow + // the same assembly to be compiled with or without + // call-indirect-overlong, we allow the operand to be omitted, in which + // case we default to __indirect_function_table. auto &Tok = Lexer.getTok(); if (Tok.is(AsmToken::Identifier)) { auto *Sym = diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.td b/llvm/lib/Target/WebAssembly/WebAssembly.td index 7081ee48132a07..2f5d2aae00d067 100644 --- a/llvm/lib/Target/WebAssembly/WebAssembly.td +++ b/llvm/lib/Target/WebAssembly/WebAssembly.td @@ -119,7 +119,8 @@ def : ProcessorModel<"mvp", NoSchedModel, []>; // the importance of the features. def : ProcessorModel<"generic", NoSchedModel, [FeatureMultivalue, FeatureMutableGlobals, - FeatureReferenceTypes, FeatureSignExt]>; + FeatureReferenceTypes, FeatureCallIndirectOverlong, + FeatureSignExt]>; def : ProcessorModel<"trail1", NoSchedModel, [FeatureMultivalue, FeatureMutableGlobals, @@ -129,13 +130,13 @@ def : ProcessorModel<"trail1", NoSchedModel, // Latest and greatest experimental version of WebAssembly. Bugs included! def : ProcessorModel<"bleeding-edge", NoSchedModel, - [FeatureAtomics, FeatureBulkMemory, + [FeatureAtomics, FeatureBulkMemory, FeatureBulkMemoryOpt, FeatureExceptionHandling, FeatureExtendedConst, FeatureFP16, FeatureMultiMemory, FeatureMultivalue, FeatureMutableGlobals, FeatureNontrappingFPToInt, FeatureRelaxedSIMD, - FeatureReferenceTypes, FeatureSIMD128, FeatureSignExt, - FeatureTailCall]>; + FeatureReferenceTypes, FeatureCallIndirectOverlong, + FeatureSIMD128, FeatureSignExt, FeatureTailCall]>; //===----------------------------------------------------------------------===// // Target Declaration diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h index 09037436d92dfc..8e623d694d204c 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -96,7 +96,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasAddr64() const { return TargetTriple.isArch64Bit(); } bool hasAtomics() const { return HasAtomics; } bool hasBulkMemory() const { return HasBulkMemory; } - bool hasBulkMemoryOpt() const { return HasBulkMemoryOpt; } + bool hasBulkMemoryOpt() const { return HasBulkMemoryOpt || HasBulkMemory; } bool hasExceptionHandling() const { return HasExceptionHandling; } bool hasExtendedConst() const { return HasExtendedConst; } bool hasFP16() const { return HasFP16; } @@ -105,7 +105,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasMutableGlobals() const { return HasMutableGlobals; } bool hasNontrappingFPToInt() const { return HasNontrappingFPToInt; } bool hasReferenceTypes() const { return HasReferenceTypes; } - bool hasCallIndirectOverlong() const { return HasCallIndirectOverlong; } + bool hasCallIndirectOverlong() const { return HasCallIndirectOverlong || HasReferenceTypes; } bool hasRelaxedSIMD() const { return SIMDLevel >= RelaxedSIMD; } bool hasSignExt() const { return HasSignExt; } bool hasSIMD128() const { return SIMDLevel >= SIMD128; } >From cc803bfbeb7ab01a4a88ffd611d4ab333e1381c4 Mon Sep 17 00:00:00 2001 From: Dan Gohman <dev@sunfishcode.online> Date: Fri, 11 Oct 2024 21:48:34 -0700 Subject: [PATCH 4/4] Handle features implying other features in the Subtarget constructor. --- llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp | 9 +++++++++ llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp index 912f61765579f8..7df15eb767093e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp @@ -34,6 +34,15 @@ WebAssemblySubtarget::initializeSubtargetDependencies(StringRef CPU, CPU = "generic"; ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS); + + // reference-types implies call-indirect-overlong + if (HasReferenceTypes) + HasCallIndirectOverlong = true; + + // bulk-memory implies bulk-memory-opt + if (HasBulkMemory) + HasBulkMemoryOpt = true; + return *this; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h index 8e623d694d204c..09037436d92dfc 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -96,7 +96,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasAddr64() const { return TargetTriple.isArch64Bit(); } bool hasAtomics() const { return HasAtomics; } bool hasBulkMemory() const { return HasBulkMemory; } - bool hasBulkMemoryOpt() const { return HasBulkMemoryOpt || HasBulkMemory; } + bool hasBulkMemoryOpt() const { return HasBulkMemoryOpt; } bool hasExceptionHandling() const { return HasExceptionHandling; } bool hasExtendedConst() const { return HasExtendedConst; } bool hasFP16() const { return HasFP16; } @@ -105,7 +105,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasMutableGlobals() const { return HasMutableGlobals; } bool hasNontrappingFPToInt() const { return HasNontrappingFPToInt; } bool hasReferenceTypes() const { return HasReferenceTypes; } - bool hasCallIndirectOverlong() const { return HasCallIndirectOverlong || HasReferenceTypes; } + bool hasCallIndirectOverlong() const { return HasCallIndirectOverlong; } bool hasRelaxedSIMD() const { return SIMDLevel >= RelaxedSIMD; } bool hasSignExt() const { return HasSignExt; } bool hasSIMD128() const { return SIMDLevel >= SIMD128; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits