From: Derek Schuff Date: Wed, 30 Aug 2017 18:07:45 +0000 (+0000) Subject: [WebAssembly] Add target feature for atomics X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3e170f0a06a4cf975859badcc09eae042be23346;p=llvm [WebAssembly] Add target feature for atomics Summary: This tracks the WebAssembly threads feature proposal at https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md Differential Revision: https://reviews.llvm.org/D37300 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312145 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 4d676c32a09..6a1bd8d0ddb 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -128,6 +128,7 @@ inline unsigned GetDefaultP2Align(unsigned Opcode) { case WebAssembly::LOAD32_S_I64: case WebAssembly::LOAD32_U_I64: case WebAssembly::STORE32_I64: + case WebAssembly::ATOMIC_LOAD_I32: return 2; case WebAssembly::LOAD_I64: case WebAssembly::LOAD_F64: diff --git a/lib/Target/WebAssembly/WebAssembly.td b/lib/Target/WebAssembly/WebAssembly.td index f647349d759..50445b77f18 100644 --- a/lib/Target/WebAssembly/WebAssembly.td +++ b/lib/Target/WebAssembly/WebAssembly.td @@ -25,6 +25,8 @@ include "llvm/Target/Target.td" def FeatureSIMD128 : SubtargetFeature<"simd128", "HasSIMD128", "true", "Enable 128-bit SIMD">; +def FeatureAtomics : SubtargetFeature<"atomics", "HasAtomics", "true", + "Enable Atomics">; //===----------------------------------------------------------------------===// // Architectures. @@ -55,7 +57,8 @@ def : ProcessorModel<"mvp", NoSchedModel, []>; def : ProcessorModel<"generic", NoSchedModel, []>; // Latest and greatest experimental version of WebAssembly. Bugs included! -def : ProcessorModel<"bleeding-edge", NoSchedModel, [FeatureSIMD128]>; +def : ProcessorModel<"bleeding-edge", NoSchedModel, + [FeatureSIMD128, FeatureAtomics]>; //===----------------------------------------------------------------------===// // Target Declaration diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 7724a75bec2..5615ec184d7 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -146,6 +146,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( // Trap lowers to wasm unreachable setOperationAction(ISD::TRAP, MVT::Other, Legal); + + setMaxAtomicSizeInBitsSupported(64); } FastISel *WebAssemblyTargetLowering::createFastISel( diff --git a/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td b/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td index 64415658ed8..fd50f59c44b 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -12,19 +12,23 @@ /// //===----------------------------------------------------------------------===// -// TODO: Implement atomic instructions. - -//===----------------------------------------------------------------------===// -// Atomic fences -//===----------------------------------------------------------------------===// - -// TODO: add atomic fences here... - //===----------------------------------------------------------------------===// // Atomic loads //===----------------------------------------------------------------------===// -// TODO: add atomic loads here... +let Defs = [ARGUMENTS] in { +// TODO: add the rest of the atomic loads +// TODO: factor out 0xfe atomic prefix? +def ATOMIC_LOAD_I32 : ATOMIC_I<(outs I32:$dst), + (ins P2Align:$p2align, offset32_op:$off, I32:$addr), + [], "i32.atomic.load\t$dst, ${off}(${addr})${p2align}", + 0xfe10>; +} // Defs = [ARGUMENTS] + +// Select loads with no constant offset. +let Predicates = [HasAtomics] in { +def : Pat<(i32 (atomic_load I32:$addr)), (ATOMIC_LOAD_I32 0, 0, $addr)>; +} //===----------------------------------------------------------------------===// // Atomic stores @@ -45,3 +49,4 @@ // Store-release-exclusives. // And clear exclusive. + diff --git a/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/lib/Target/WebAssembly/WebAssemblyInstrFormats.td index 5b249840257..4f41fcc232e 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -32,6 +32,10 @@ class SIMD_I pattern, string asmstr = "", bits<32> inst = -1> : I, Requires<[HasSIMD128]>; +class ATOMIC_I pattern, + string asmstr = "", bits<32> inst = -1> + : I, Requires<[HasAtomics]>; + // Unary and binary instructions, for the local types that WebAssembly supports. multiclass UnaryInt i32Inst, bits<32> i64Inst> { def _I32 : I<(outs I32:$dst), (ins I32:$src), diff --git a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index fa2146f7db8..bc4e542c4fb 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -20,6 +20,8 @@ def HasAddr32 : Predicate<"!Subtarget->hasAddr64()">; def HasAddr64 : Predicate<"Subtarget->hasAddr64()">; def HasSIMD128 : Predicate<"Subtarget->hasSIMD128()">, AssemblerPredicate<"FeatureSIMD128", "simd128">; +def HasAtomics : Predicate<"Subtarget->hasAtomics()">, + AssemblerPredicate<"FeatureAtomics", "atomics">; //===----------------------------------------------------------------------===// // WebAssembly-specific DAG Node Types. diff --git a/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp b/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp index b1385f409fd..a418f65e0ee 100644 --- a/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp +++ b/lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp @@ -96,6 +96,7 @@ bool WebAssemblySetP2AlignOperands::runOnMachineFunction(MachineFunction &MF) { case WebAssembly::LOAD16_U_I64: case WebAssembly::LOAD32_S_I64: case WebAssembly::LOAD32_U_I64: + case WebAssembly::ATOMIC_LOAD_I32: RewriteP2Align(MI, WebAssembly::LoadP2AlignOperandNo); break; case WebAssembly::STORE_I32: diff --git a/lib/Target/WebAssembly/WebAssemblySubtarget.cpp b/lib/Target/WebAssembly/WebAssemblySubtarget.cpp index ce39051b055..6fae72cdeae 100644 --- a/lib/Target/WebAssembly/WebAssemblySubtarget.cpp +++ b/lib/Target/WebAssembly/WebAssemblySubtarget.cpp @@ -41,7 +41,7 @@ WebAssemblySubtarget::WebAssemblySubtarget(const Triple &TT, const std::string &FS, const TargetMachine &TM) : WebAssemblyGenSubtargetInfo(TT, CPU, FS), HasSIMD128(false), - CPUString(CPU), TargetTriple(TT), FrameLowering(), + HasAtomics(false), CPUString(CPU), TargetTriple(TT), FrameLowering(), InstrInfo(initializeSubtargetDependencies(FS)), TSInfo(), TLInfo(TM, *this) {} diff --git a/lib/Target/WebAssembly/WebAssemblySubtarget.h b/lib/Target/WebAssembly/WebAssemblySubtarget.h index f530a290fa0..a69989dd955 100644 --- a/lib/Target/WebAssembly/WebAssemblySubtarget.h +++ b/lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -30,6 +30,7 @@ namespace llvm { class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool HasSIMD128; + bool HasAtomics; /// String name of used CPU. std::string CPUString; @@ -74,6 +75,7 @@ public: // Predicates used by WebAssemblyInstrInfo.td. bool hasAddr64() const { return TargetTriple.isArch64Bit(); } bool hasSIMD128() const { return HasSIMD128; } + bool hasAtomics() const { return HasAtomics; } /// Parses features string setting specified subtarget options. Definition of /// function is auto generated by tblgen. diff --git a/test/CodeGen/WebAssembly/atomics.ll b/test/CodeGen/WebAssembly/atomics.ll new file mode 100644 index 00000000000..1845187f505 --- /dev/null +++ b/test/CodeGen/WebAssembly/atomics.ll @@ -0,0 +1,19 @@ +; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -mattr=+atomics | FileCheck %s + +; Test that atomic loads are assembled properly. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +; CHECK-LABEL: load_i32_atomic: +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; CHECK-NEXT: get_local $push[[L0:[0-9]+]]=, 0{{$}} +; CHECK-NEXT: i32.atomic.load $push[[NUM:[0-9]+]]=, 0($pop[[L0]]){{$}} +; CHECK-NEXT: return $pop[[NUM]]{{$}} + +define i32 @load_i32_atomic(i32 *%p) { + %v = load atomic i32, i32* %p seq_cst, align 4 + ret i32 %v +}