Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -128,6 +128,7 @@ 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: Index: lib/Target/WebAssembly/WebAssembly.td =================================================================== --- lib/Target/WebAssembly/WebAssembly.td +++ lib/Target/WebAssembly/WebAssembly.td @@ -25,6 +25,8 @@ 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<"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 Index: lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -146,6 +146,8 @@ // Trap lowers to wasm unreachable setOperationAction(ISD::TRAP, MVT::Other, Legal); + + setMaxAtomicSizeInBitsSupported(64); } FastISel *WebAssemblyTargetLowering::createFastISel( Index: lib/Target/WebAssembly/WebAssemblyInstrAtomics.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -12,19 +12,24 @@ /// //===----------------------------------------------------------------------===// -// TODO: Implement atomic instructions. - -//===----------------------------------------------------------------------===// -// Atomic fences -//===----------------------------------------------------------------------===// - -// TODO: add atomic fences here... +let Defs = [ARGUMENTS] in { //===----------------------------------------------------------------------===// // Atomic loads //===----------------------------------------------------------------------===// -// TODO: add atomic loads here... +// 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 +50,4 @@ // Store-release-exclusives. // And clear exclusive. + Index: lib/Target/WebAssembly/WebAssemblyInstrFormats.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -32,6 +32,10 @@ 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), Index: lib/Target/WebAssembly/WebAssemblyInstrInfo.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -20,6 +20,8 @@ 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. Index: lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp +++ lib/Target/WebAssembly/WebAssemblySetP2AlignOperands.cpp @@ -96,6 +96,7 @@ 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: Index: lib/Target/WebAssembly/WebAssemblySubtarget.h =================================================================== --- lib/Target/WebAssembly/WebAssemblySubtarget.h +++ lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -30,6 +30,7 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool HasSIMD128; + bool HasAtomics; /// String name of used CPU. std::string CPUString; @@ -74,6 +75,7 @@ // 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. Index: lib/Target/WebAssembly/WebAssemblySubtarget.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblySubtarget.cpp +++ lib/Target/WebAssembly/WebAssemblySubtarget.cpp @@ -41,7 +41,7 @@ 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) {} Index: test/CodeGen/WebAssembly/atomics.ll =================================================================== --- /dev/null +++ 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: ldi32atomic: +; 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 @ldi32atomic(i32 *%p) { + %v = load atomic i32, i32* %p seq_cst, align 4 + ret i32 %v +} Index: test/CodeGen/WebAssembly/load.ll =================================================================== --- test/CodeGen/WebAssembly/load.ll +++ test/CodeGen/WebAssembly/load.ll @@ -49,3 +49,4 @@ %v = load double, double* %p ret double %v } +