From e7bf5b9cb16828f9a740fae02c7d9d67916841f8 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 8 May 2022 05:50:07 -0400 Subject: [PATCH 01/23] Initial commit From 01bb9db78bd5a1b44f7dc62b3a152963bfc46fc5 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 8 May 2022 05:50:11 -0400 Subject: [PATCH 02/23] Files generated by PkgTemplates PkgTemplates version: 0.7.26 --- ext/UnsafeAtomicsLLVM/.JuliaFormatter.toml | 1 + ext/UnsafeAtomicsLLVM/.gitignore | 1 + ext/UnsafeAtomicsLLVM/LICENSE | 21 +++++++++++++++++++ ext/UnsafeAtomicsLLVM/Project.toml | 7 +++++++ ext/UnsafeAtomicsLLVM/README.md | 1 + .../src/UnsafeAtomicsLLVM.jl | 11 ++++++++++ ext/UnsafeAtomicsLLVM/test/Project.toml | 2 ++ ext/UnsafeAtomicsLLVM/test/runtests.jl | 6 ++++++ 8 files changed, 50 insertions(+) create mode 100644 ext/UnsafeAtomicsLLVM/.JuliaFormatter.toml create mode 100644 ext/UnsafeAtomicsLLVM/.gitignore create mode 100644 ext/UnsafeAtomicsLLVM/LICENSE create mode 100644 ext/UnsafeAtomicsLLVM/Project.toml create mode 100644 ext/UnsafeAtomicsLLVM/README.md create mode 100644 ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl create mode 100644 ext/UnsafeAtomicsLLVM/test/Project.toml create mode 100644 ext/UnsafeAtomicsLLVM/test/runtests.jl diff --git a/ext/UnsafeAtomicsLLVM/.JuliaFormatter.toml b/ext/UnsafeAtomicsLLVM/.JuliaFormatter.toml new file mode 100644 index 0000000..d9b1069 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/.JuliaFormatter.toml @@ -0,0 +1 @@ +always_for_in = true diff --git a/ext/UnsafeAtomicsLLVM/.gitignore b/ext/UnsafeAtomicsLLVM/.gitignore new file mode 100644 index 0000000..ba39cc5 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/.gitignore @@ -0,0 +1 @@ +Manifest.toml diff --git a/ext/UnsafeAtomicsLLVM/LICENSE b/ext/UnsafeAtomicsLLVM/LICENSE new file mode 100644 index 0000000..02e1d79 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Takafumi Arakaki and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml new file mode 100644 index 0000000..b211dfb --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -0,0 +1,7 @@ +name = "UnsafeAtomicsLLVM" +uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" +authors = ["Takafumi Arakaki and contributors"] +version = "0.1.0-DEV" + +[compat] +julia = "1.6" diff --git a/ext/UnsafeAtomicsLLVM/README.md b/ext/UnsafeAtomicsLLVM/README.md new file mode 100644 index 0000000..aeac5f0 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/README.md @@ -0,0 +1 @@ +# UnsafeAtomicsLLVM diff --git a/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl b/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl new file mode 100644 index 0000000..a6f2da4 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl @@ -0,0 +1,11 @@ +baremodule UnsafeAtomicsLLVM + +module Internal + +using ..UnsafeAtomicsLLVM: UnsafeAtomicsLLVM + +include("internal.jl") + +end # module Internal + +end # baremodule UnsafeAtomicsLLVM diff --git a/ext/UnsafeAtomicsLLVM/test/Project.toml b/ext/UnsafeAtomicsLLVM/test/Project.toml new file mode 100644 index 0000000..0c36332 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/test/Project.toml @@ -0,0 +1,2 @@ +[deps] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/ext/UnsafeAtomicsLLVM/test/runtests.jl b/ext/UnsafeAtomicsLLVM/test/runtests.jl new file mode 100644 index 0000000..56bf12c --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/test/runtests.jl @@ -0,0 +1,6 @@ +using UnsafeAtomicsLLVM +using Test + +@testset "UnsafeAtomicsLLVM.jl" begin + # Write your tests here. +end From 2248f28a9b9c7e143a77b3a691056d2f02feb54b Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 8 May 2022 05:50:11 -0400 Subject: [PATCH 03/23] Initial implementation --- ext/UnsafeAtomicsLLVM/Project.toml | 4 ++ .../src/UnsafeAtomicsLLVM.jl | 4 +- ext/UnsafeAtomicsLLVM/src/internal.jl | 33 +++++++++ ext/UnsafeAtomicsLLVM/test/Project.toml | 4 ++ .../test/UnsafeAtomicsLLVMTests/Project.toml | 12 ++++ .../src/UnsafeAtomicsLLVMTests.jl | 5 ++ .../UnsafeAtomicsLLVMTests/src/test_core.jl | 72 +++++++++++++++++++ ext/UnsafeAtomicsLLVM/test/runtests.jl | 8 +-- 8 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 ext/UnsafeAtomicsLLVM/src/internal.jl create mode 100644 ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml create mode 100644 ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl create mode 100644 ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index b211dfb..72aa8b1 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -3,5 +3,9 @@ uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] version = "0.1.0-DEV" +[deps] +LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" +UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" + [compat] julia = "1.6" diff --git a/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl b/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl index a6f2da4..f0aca14 100644 --- a/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl +++ b/ext/UnsafeAtomicsLLVM/src/UnsafeAtomicsLLVM.jl @@ -2,7 +2,9 @@ baremodule UnsafeAtomicsLLVM module Internal -using ..UnsafeAtomicsLLVM: UnsafeAtomicsLLVM +using Core: LLVMPtr +using LLVM +using UnsafeAtomics: UnsafeAtomics, Ordering include("internal.jl") diff --git a/ext/UnsafeAtomicsLLVM/src/internal.jl b/ext/UnsafeAtomicsLLVM/src/internal.jl new file mode 100644 index 0000000..88d65de --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/src/internal.jl @@ -0,0 +1,33 @@ +# TODO: move this to UnsafeAtomics +julia_ordering_name(::UnsafeAtomics.Internal.LLVMOrdering{name}) where {name} = name +julia_ordering_name(::typeof(UnsafeAtomics.acquire_release)) = :acquire_release +julia_ordering_name(::typeof(UnsafeAtomics.sequentially_consistent)) = + :sequentially_consistent + +@inline UnsafeAtomics.load(ptr::LLVMPtr, order::Ordering) = + LLVM.Interop.atomic_pointerref(ptr, Val{julia_ordering_name(order)}()) + +@inline function UnsafeAtomics.store!(ptr::LLVMPtr, x, order::Ordering) + LLVM.Interop.atomic_pointerset(ptr, x, Val{julia_ordering_name(order)}()) + return +end + +mapop(op::OP) where {OP} = op +mapop(::typeof(UnsafeAtomics.right)) = LLVM.Interop.right + +@inline UnsafeAtomics.modify!(ptr::LLVMPtr, op::OP, x, order::Ordering) where {OP} = + LLVM.Interop.atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}()) + +@inline UnsafeAtomics.cas!( + ptr::LLVMPtr, + expected, + desired, + success_order::Ordering, + failure_order::Ordering, +) = LLVM.Interop.atomic_pointerreplace( + ptr, + expected, + desired, + Val{julia_ordering_name(success_order)}(), + Val{julia_ordering_name(failure_order)}(), +) diff --git a/ext/UnsafeAtomicsLLVM/test/Project.toml b/ext/UnsafeAtomicsLLVM/test/Project.toml index 0c36332..77d6950 100644 --- a/ext/UnsafeAtomicsLLVM/test/Project.toml +++ b/ext/UnsafeAtomicsLLVM/test/Project.toml @@ -1,2 +1,6 @@ [deps] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TestFunctionRunner = "792026f5-ac9a-4a19-adcb-47b0ce2deb5d" + +[compat] +TestFunctionRunner = "0.1" diff --git a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml new file mode 100644 index 0000000..ef96aae --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml @@ -0,0 +1,12 @@ +name = "UnsafeAtomicsLLVMTests" +uuid = "f81c5320-9584-4f93-9445-2842f5246c7e" +authors = ["Takafumi Arakaki and contributors"] +version = "0.1.0-DEV" + +[deps] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" +UnsafeAtomicsLLVM = "d80eeb9a-aca5-4d75-85e5-170c8b632249" + +[compat] +julia = "1.6" diff --git a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl new file mode 100644 index 0000000..78a611c --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl @@ -0,0 +1,5 @@ +module UnsafeAtomicsLLVMTests + +include("test_core.jl") + +end # module UnsafeAtomicsLLVMTests diff --git a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl new file mode 100644 index 0000000..1c83b67 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl @@ -0,0 +1,72 @@ +module TestCore + +import UnsafeAtomicsLLVM + +using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel +using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes +using Test + +llvmptr(xs::Array, i) = reinterpret(Core.LLVMPtr{eltype(xs),0}, pointer(xs, i)) + +function test_default_ordering() + @testset for T in inttypes + check_default_ordering(T) + end +end + +function check_default_ordering(T::Type) + xs = T[rand(T), rand(T)] + x1 = rand(T) + x2 = rand(T) + @debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))" + + ptr = llvmptr(xs, 1) + GC.@preserve xs begin + @test UnsafeAtomics.load(ptr) === xs[1] + UnsafeAtomics.store!(ptr, x1) + @test xs[1] === x1 + desired = (old = x1, success = true) + @test UnsafeAtomics.cas!(ptr, x1, x2) === (old = x1, success = true) + @test xs[1] === x2 + @testset for (op, name) in OP_RMW_TABLE + xs[1] = x1 + @test UnsafeAtomics.modify!(ptr, op, x2) === (x1 => op(x1, x2)) + @test xs[1] === op(x1, x2) + + rmw = getfield(UnsafeAtomics, Symbol(name, :!)) + xs[1] = x1 + @test rmw(ptr, x2) === x1 + @test xs[1] === op(x1, x2) + end + end +end + +function test_explicit_ordering(T::Type = UInt) + xs = T[rand(T), rand(T)] + x1 = rand(T) + x2 = rand(T) + @debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))" + + ptr = llvmptr(xs, 1) + GC.@preserve xs begin + + @test UnsafeAtomics.load(ptr, acquire) === xs[1] + UnsafeAtomics.store!(ptr, x1, release) + @test xs[1] === x1 + desired = (old = x1, success = true) + @test UnsafeAtomics.cas!(ptr, x1, x2, acq_rel, acquire) === desired + @test xs[1] === x2 + @testset for (op, name) in OP_RMW_TABLE + xs[1] = x1 + @test UnsafeAtomics.modify!(ptr, op, x2, acq_rel) === (x1 => op(x1, x2)) + @test xs[1] === op(x1, x2) + + rmw = getfield(UnsafeAtomics, Symbol(name, :!)) + xs[1] = x1 + @test rmw(ptr, x2, acquire) === x1 + @test xs[1] === op(x1, x2) + end + end +end + +end # module diff --git a/ext/UnsafeAtomicsLLVM/test/runtests.jl b/ext/UnsafeAtomicsLLVM/test/runtests.jl index 56bf12c..d358b79 100644 --- a/ext/UnsafeAtomicsLLVM/test/runtests.jl +++ b/ext/UnsafeAtomicsLLVM/test/runtests.jl @@ -1,6 +1,2 @@ -using UnsafeAtomicsLLVM -using Test - -@testset "UnsafeAtomicsLLVM.jl" begin - # Write your tests here. -end +using TestFunctionRunner +TestFunctionRunner.@run From 3a118e1293d650e472121220284eb3ab251d60bd Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 18 May 2022 03:34:14 -0700 Subject: [PATCH 04/23] Setup CI (JuliaConcurrent/UnsafeAtomicsLLVM.jl#1) --- .../.github/workflows/ci.yml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml new file mode 100644 index 0000000..9659a5d --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml @@ -0,0 +1,56 @@ +name: CI + +on: + push: + branches: + - main + tags: '*' + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + julia-version: + - '1' + - '1.6' + - 'nightly' + fail-fast: false + name: Test Julia ${{ matrix.julia-version }} + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.julia-version }} + - name: Install LLVM.jl + run: | + using Pkg + Pkg.activate(".") + Pkg.add(url = "https://github.com/maleadt/LLVM.jl") + shell: julia --color=yes {0} + - uses: julia-actions/julia-runtest@v1 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v2 + with: + file: ./lcov.info + flags: Pkg.test + name: codecov-umbrella + + # https://github.com/tkf/julia-code-style-suggesters + code-style: + if: always() && github.event.pull_request + runs-on: ubuntu-latest + steps: + - uses: tkf/julia-code-style-suggesters@v1 + + # A job that succeeds if and only if all jobs succeed. + all-success: + if: always() && github.event.pull_request + needs: [test, code-style] + runs-on: ubuntu-latest + steps: + # https://github.com/tkf/merge-conclusions-action + - uses: tkf/merge-conclusions-action@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 0c68fbf2a51dd4ecf3d6588c7150558a969c768f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 25 May 2022 00:40:15 -0700 Subject: [PATCH 05/23] Setup Aqua (JuliaConcurrent/UnsafeAtomicsLLVM.jl#2) --- ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml | 18 +++++++++++++++++- ext/UnsafeAtomicsLLVM/Project.toml | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml index 9659a5d..75190d8 100644 --- a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml @@ -37,6 +37,22 @@ jobs: flags: Pkg.test name: codecov-umbrella + aqua: + runs-on: ubuntu-latest + strategy: + matrix: + julia-version: + - '1' + - '1.6' + - 'nightly' + fail-fast: false + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.julia-version }} + - uses: tkf/julia-aqua@v1 + # https://github.com/tkf/julia-code-style-suggesters code-style: if: always() && github.event.pull_request @@ -47,7 +63,7 @@ jobs: # A job that succeeds if and only if all jobs succeed. all-success: if: always() && github.event.pull_request - needs: [test, code-style] + needs: [test, aqua, code-style] runs-on: ubuntu-latest steps: # https://github.com/tkf/merge-conclusions-action diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 72aa8b1..4f83804 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -8,4 +8,6 @@ LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] +LLVM = "4.12" +UnsafeAtomics = "0.2" julia = "1.6" From a5801584f4b12bca5072587e61abfc08c6bff3a0 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 25 May 2022 00:42:35 -0700 Subject: [PATCH 06/23] Setup TagBot (JuliaConcurrent/UnsafeAtomicsLLVM.jl#4) --- .../.github/workflows/TagBot.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml new file mode 100644 index 0000000..5c8d528 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml @@ -0,0 +1,20 @@ +name: TagBot +on: + issue_comment: + types: + - created + push: + branches: + - actions/trigger/TagBot + workflow_dispatch: +jobs: + TagBot: + if: >- + github.event_name == 'workflow_dispatch' || + github.event_name == 'push' || + github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} From 6e8bd319e0e375f1e1403c2696fdfa67cc492676 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 25 May 2022 16:43:22 +0900 Subject: [PATCH 07/23] Bump to 0.1.0 --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 4f83804..f75c11a 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.0-DEV" +version = "0.1.0" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" From 433ece8f7a77d3746f1745a9c5bc6f97bc5c45d3 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 25 May 2022 16:43:25 +0900 Subject: [PATCH 08/23] Bump to 0.1.1-DEV --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index f75c11a..4eead7c 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.0" +version = "0.1.1-DEV" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" From a4e2baa22d26dc219034bceb187aa1448b7d58dd Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 25 May 2022 06:13:21 -0700 Subject: [PATCH 09/23] Install LLVM.jl from General (JuliaConcurrent/UnsafeAtomicsLLVM.jl#5) --- ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml index 75190d8..5207671 100644 --- a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml @@ -23,12 +23,6 @@ jobs: - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.julia-version }} - - name: Install LLVM.jl - run: | - using Pkg - Pkg.activate(".") - Pkg.add(url = "https://github.com/maleadt/LLVM.jl") - shell: julia --color=yes {0} - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v2 From 091d4b7cab56ed8d41700ab8aa02062588ff36ff Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 27 Mar 2023 10:54:08 -0400 Subject: [PATCH 10/23] Move Atomics from LLVM.jl into UnsafeAtomicsLLVM (JuliaConcurrent/UnsafeAtomicsLLVM.jl#8) --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- ext/UnsafeAtomicsLLVM/src/atomics.jl | 523 ++++++++++++++++++++++++++ ext/UnsafeAtomicsLLVM/src/internal.jl | 12 +- 3 files changed, 531 insertions(+), 6 deletions(-) create mode 100644 ext/UnsafeAtomicsLLVM/src/atomics.jl diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 4eead7c..9c5ff82 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.1-DEV" +version = "0.1.2" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" diff --git a/ext/UnsafeAtomicsLLVM/src/atomics.jl b/ext/UnsafeAtomicsLLVM/src/atomics.jl new file mode 100644 index 0000000..a8078fd --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/src/atomics.jl @@ -0,0 +1,523 @@ +using LLVM +using LLVM.Interop + +const MEMORY_ORDERING_EXPLANATION = """ +specified as a symbol (e.g., `:sequentially_consistent`) or a `Val` of a symbol (e.g., +`Val(:sequentially_consistent)`) +""" + +""" + atomic_pointerref(pointer::LLVMPtr{T}, ordering) -> value::T +Load a `value` from `pointer` with the given memory `ordering` atomically. +`ordering` is a Julia atomic ordering $MEMORY_ORDERING_EXPLANATION. +See also: `getproperty`, `getfield` +""" +atomic_pointerref + +""" + LLVM.Interop.atomic_pointerset(pointer::LLVMPtr{T}, x::T, ordering) -> pointer +Store a value `x` in `pointer` with the given memory `ordering` atomically. +`ordering` is a Julia atomic ordering $MEMORY_ORDERING_EXPLANATION. +See also: `setproperty!`, `setfield!` +""" +atomic_pointerset + +""" + atomic_pointermodify( + pointer::LLVMPtr{T}, + op, + x::T, + ordering, + ) -> (old => new)::Pair{T,T} +Replace an `old` value stored at `pointer` with a `new` value comped as `new = op(old, x)` +with the given memory `ordering` atomically. Return a pair `old => new`. +`ordering` is a Julia atomic ordering $MEMORY_ORDERING_EXPLANATION. +See also: `modifyproperty!`, `modifyfield!` +""" +atomic_pointermodify + +""" + atomic_pointerswap(pointer::LLVMPtr{T}, op, new::T, ordering) -> old::T +Replace an `old` value stored at `pointer` with a `new` value with the given memory +`ordering` atomically. Return the `old` value. +`ordering` is a Julia atomic ordering $MEMORY_ORDERING_EXPLANATION. +See also: `modifyproperty!`, `modifyfield!` +""" +atomic_pointerswap + +""" + atomic_pointerreplace( + pointer::LLVMPtr{T}, + expected::T, + desired::T, + success_ordering, + fail_ordering, + ) -> (; old::T, success::Bool) +Try to replace the value of `pointer` from an `expected` value to a `desired` value +atomically with the ordering `success_ordering`. The property `old` of the returned value +is the value stored in the `pointer`. The property `success` of the returned value +indicates if the replacement was successful. The ordering `fail_ordering` specifies the +ordering used for loading the `old` value. +`success_ordering` and `fail_ordering` are Julia atomic orderings +$MEMORY_ORDERING_EXPLANATION. +See also: `replaceproperty!`, `replacefield!` +""" +atomic_pointerreplace + +const _llvm_from_julia_ordering = ( + not_atomic = LLVM.API.LLVMAtomicOrderingNotAtomic, + unordered = LLVM.API.LLVMAtomicOrderingUnordered, + monotonic = LLVM.API.LLVMAtomicOrderingMonotonic, + acquire = LLVM.API.LLVMAtomicOrderingAcquire, + release = LLVM.API.LLVMAtomicOrderingRelease, + acquire_release = LLVM.API.LLVMAtomicOrderingAcquireRelease, + sequentially_consistent = LLVM.API.LLVMAtomicOrderingSequentiallyConsistent, +) + +_julia_ordering(p) = + Union{map(x -> p(x) ? Val{x} : Union{}, keys(_llvm_from_julia_ordering))...} + +const AllOrdering = _julia_ordering(_ -> true) +const AtomicOrdering = _julia_ordering(!=(:not_atomic)) + +const LLVMOrderingVal = Union{map(x -> Val{x}, values(_llvm_from_julia_ordering))...} + +is_stronger_than_monotonic(order::Symbol) = + !(order === :monotonic || order === :unordered || order === :not_atomic) + +for (julia, llvm) in pairs(_llvm_from_julia_ordering) + @eval llvm_from_julia_ordering(::Val{$(QuoteNode(julia))}) = Val{$llvm}() +end + +""" + @dynamic_order(order) do order + ... use order ... + end +It is expanded to an expression similar to: + if order === :not_atomic + let order = Val(:not_atomic) + ... use order ... + end + elseif order === :unordered + let order = Val(:unordered) + ... use order ... + end + elseif ... + ... + else + throw(ConcurrencyViolationError(...)) + end +This is used for helping the compiler to optimize expressions such as +`atomic_pointerref(ptr, :monotonic)` and also to avoid abstract run-time dispatch. +""" +macro dynamic_order(thunk, order) + @assert Meta.isexpr(thunk, :->, 2) && Meta.isexpr(thunk.args[1], :tuple, 1) + ordervar = esc(thunk.args[1].args[1]) + body = esc(thunk.args[2]) + expr = foldr( + keys(_llvm_from_julia_ordering), + init = :(throw(ConcurrencyViolationError("invalid atomic ordering: ", order))), + ) do key, r + quote + if order === $(QuoteNode(key)) + let $ordervar = Val{$(QuoteNode(key))}() + $body + end + else + $r + end + end + end + quote + order = $(esc(order)) + $expr + end +end + +_valueof(::Val{x}) where {x} = x + +@inline function atomic_pointerref(pointer, order::Symbol) + @dynamic_order(order) do order + atomic_pointerref(pointer, order) + end +end + +@inline function atomic_pointerset(pointer, x, order::Symbol) + @dynamic_order(order) do order + atomic_pointerset(pointer, x, order) + end +end + +@generated function atomic_pointerref(ptr::LLVMPtr{T,A}, order::AllOrdering) where {T,A} + sizeof(T) == 0 && return T.instance + llvm_order = _valueof(llvm_from_julia_ordering(order())) + @dispose ctx = Context() begin + eltyp = convert(LLVMType, T; ctx) + + T_ptr = convert(LLVMType, ptr; ctx) + + T_typed_ptr = LLVM.PointerType(eltyp, A) + + # create a function + param_types = [T_ptr] + llvm_f, _ = create_function(eltyp, param_types) + + # generate IR + @dispose builder = Builder(ctx) begin + entry = BasicBlock(llvm_f, "entry"; ctx) + position!(builder, entry) + + typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) + ld = load!(builder, typed_ptr) + ordering!(ld, llvm_order) + + if A != 0 + metadata(ld)[LLVM.MD_tbaa] = tbaa_addrspace(A; ctx) + end + alignment!(ld, sizeof(T)) + + ret!(builder, ld) + end + + call_function(llvm_f, T, Tuple{LLVMPtr{T,A}}, :ptr) + end +end + +@generated function atomic_pointerset( + ptr::LLVMPtr{T,A}, + x::T, + order::AllOrdering, +) where {T,A} + if sizeof(T) == 0 + # Mimicking what `Core.Intrinsics.atomic_pointerset` generates. + # See: https://github.com/JuliaLang/julia/blob/v1.7.2/src/cgutils.cpp#L1570-L1572 + is_stronger_than_monotonic(order) || return :ptr + return quote + Core.Intrinsics.fence($(QuoteNode(order))) + ptr + end + end + llvm_order = _valueof(llvm_from_julia_ordering(order())) + @dispose ctx = Context() begin + eltyp = convert(LLVMType, T; ctx) + T_ptr = convert(LLVMType, ptr; ctx) + T_typed_ptr = LLVM.PointerType(eltyp, A) + + # create a function + param_types = [T_ptr, eltyp] + llvm_f, _ = create_function(LLVM.VoidType(ctx), param_types) + + # generate IR + @dispose builder = Builder(ctx) begin + entry = BasicBlock(llvm_f, "entry"; ctx) + position!(builder, entry) + + typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) + val = parameters(llvm_f)[2] + st = store!(builder, val, typed_ptr) + ordering!(st, llvm_order) + + if A != 0 + metadata(st)[LLVM.MD_tbaa] = tbaa_addrspace(A; ctx) + end + alignment!(st, sizeof(T)) + + ret!(builder) + end + + call = call_function(llvm_f, Cvoid, Tuple{LLVMPtr{T,A},T}, :ptr, :x) + quote + $call + ptr + end + end +end + +right(_, r) = r + +const binoptable = [ + (:xchg, right, LLVM.API.LLVMAtomicRMWBinOpXchg), + (:add, +, LLVM.API.LLVMAtomicRMWBinOpAdd), + (:sub, -, LLVM.API.LLVMAtomicRMWBinOpSub), + (:and, &, LLVM.API.LLVMAtomicRMWBinOpAnd), + (:or, |, LLVM.API.LLVMAtomicRMWBinOpOr), + (:xor, xor, LLVM.API.LLVMAtomicRMWBinOpXor), + (:max, max, LLVM.API.LLVMAtomicRMWBinOpMax), + (:min, min, LLVM.API.LLVMAtomicRMWBinOpMin), + (:umax, max, LLVM.API.LLVMAtomicRMWBinOpUMax), + (:umin, min, LLVM.API.LLVMAtomicRMWBinOpUMin), + (:fadd, +, LLVM.API.LLVMAtomicRMWBinOpFAdd), + (:fsub, -, LLVM.API.LLVMAtomicRMWBinOpFSub), +] + +const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...} + +@generated function llvm_atomic_op( + binop::AtomicRMWBinOpVal, + ptr::LLVMPtr{T,A}, + val::T, + order::LLVMOrderingVal, +) where {T,A} + @dispose ctx = Context() begin + T_val = convert(LLVMType, T; ctx) + T_ptr = convert(LLVMType, ptr; ctx) + + T_typed_ptr = LLVM.PointerType(T_val, A) + + llvm_f, _ = create_function(T_val, [T_ptr, T_val]) + + @dispose builder = Builder(ctx) begin + entry = BasicBlock(llvm_f, "entry"; ctx) + position!(builder, entry) + + typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) + + single_threaded = false + rv = atomic_rmw!( + builder, + _valueof(binop()), + typed_ptr, + parameters(llvm_f)[2], + _valueof(order()), + single_threaded, + ) + + ret!(builder, rv) + end + + call_function(llvm_f, T, Tuple{LLVMPtr{T,A},T}, :ptr, :val) + end +end + +@inline function atomic_pointermodify(pointer, op::OP, x, order::Symbol) where {OP} + @dynamic_order(order) do order + atomic_pointermodify(pointer, op, x, order) + end +end + +@inline function atomic_pointermodify( + ptr::LLVMPtr{T}, + op, + x::T, + ::Val{:not_atomic}, +) where {T} + old = atomic_pointerref(ptr, Val(:not_atomic)) + new = op(old, x) + atomic_pointerset(ptr, new, Val(:not_atomic)) + return old => new +end + +@inline function atomic_pointermodify( + ptr::LLVMPtr{T}, + ::typeof(right), + x::T, + order::AtomicOrdering, +) where {T} + old = llvm_atomic_op( + Val(LLVM.API.LLVMAtomicRMWBinOpXchg), + ptr, + x, + llvm_from_julia_ordering(order), + ) + return old => x +end + +const atomictypes = Any[ + Int8, + Int16, + Int32, + Int64, + Int128, + UInt8, + UInt16, + UInt32, + UInt64, + UInt128, + Float16, + Float32, + Float64, +] + +for (opname, op, llvmop) in binoptable + opname === :xchg && continue + types = if opname in (:min, :max) + filter(t -> t <: Signed, atomictypes) + elseif opname in (:umin, :umax) + filter(t -> t <: Unsigned, atomictypes) + elseif opname in (:fadd, :fsub) + filter(t -> t <: AbstractFloat, atomictypes) + else + filter(t -> t <: Integer, atomictypes) + end + for T in types + @eval @inline function atomic_pointermodify( + ptr::LLVMPtr{$T}, + ::$(typeof(op)), + x::$T, + order::AtomicOrdering, + ) + old = llvm_atomic_op($(Val(llvmop)), ptr, x, llvm_from_julia_ordering(order)) + return old => $op(old, x) + end + end +end + +@inline atomic_pointerswap(pointer, new) = first(atomic_pointermodify(pointer, right, new)) +@inline atomic_pointerswap(pointer, new, order) = + first(atomic_pointermodify(pointer, right, new, order)) + +@inline function atomic_pointermodify( + ptr::LLVMPtr{T}, + op, + x::T, + order::AllOrdering, +) where {T} + # Should `fail_order` be stronger? Ref: https://github.com/JuliaLang/julia/issues/45256 + fail_order = Val(:monotonic) + old = atomic_pointerref(ptr, fail_order) + while true + new = op(old, x) + (old, success) = atomic_pointerreplace(ptr, old, new, order, fail_order) + success && return old => new + end +end + +@generated function llvm_atomic_cas( + ptr::LLVMPtr{T,A}, + cmp::T, + val::T, + success_order::LLVMOrderingVal, + fail_order::LLVMOrderingVal, +) where {T,A} + llvm_success = _valueof(success_order()) + llvm_fail = _valueof(fail_order()) + @dispose ctx = Context() begin + T_val = convert(LLVMType, T; ctx) + T_pointee = T_val + if T_val isa LLVM.FloatingPointType + T_pointee = LLVM.IntType(sizeof(T) * 8; ctx) + end + T_ptr = convert(LLVMType, ptr; ctx) + T_success = convert(LLVMType, Ptr{Int8}; ctx) + + T_typed_ptr = LLVM.PointerType(T_pointee, A) + T_ok_ptr = LLVM.PointerType(convert(LLVMType, Int8; ctx)) + + llvm_f, _ = create_function(T_val, [T_ptr, T_val, T_val, T_success]) + + @dispose builder = Builder(ctx) begin + entry = BasicBlock(llvm_f, "entry"; ctx) + position!(builder, entry) + + typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) + ok_ptr = inttoptr!(builder, parameters(llvm_f)[4], T_ok_ptr) + + cmp_int = parameters(llvm_f)[2] + if T_val isa LLVM.FloatingPointType + cmp_int = bitcast!(builder, cmp_int, T_pointee) + end + + val_int = parameters(llvm_f)[3] + if T_val isa LLVM.FloatingPointType + val_int = bitcast!(builder, val_int, T_pointee) + end + + single_threaded = false + res = atomic_cmpxchg!( + builder, + typed_ptr, + cmp_int, + val_int, + llvm_success, + llvm_fail, + single_threaded, + ) + + rv = extract_value!(builder, res, 0) + ok = extract_value!(builder, res, 1) + ok = zext!(builder, ok, LLVM.Int8Type(ctx)) + store!(builder, ok, ok_ptr) + + if T_val isa LLVM.FloatingPointType + rv = bitcast!(builder, rv, T_val) + end + + ret!(builder, rv) + end + + expr = call_function( + llvm_f, + T, + Tuple{LLVMPtr{T,A},T,T,Ptr{Int8}}, + :ptr, + :cmp, + :val, + :success_ptr, + ) + quote + success = Ref{Int8}() + old = GC.@preserve success begin + success_ptr = Ptr{Int8}(pointer_from_objref(success)) + $expr + end + (; old, success = success[] != zero(Int8)) + end + end +end + +@inline function atomic_pointerreplace( + pointer, + expected, + desired, + success_order::Symbol, + fail_order::Symbol, +) + # This avoids abstract dispatch at run-time but probably too much codegen? + #= + @dynamic_order(success_order) do success_order + @dynamic_order(fail_order) do fail_order + atomic_pointerreplace(pointer, expected, desired, success_order, fail_order) + end + end + =# + + # This avoids excessive codegen while hopefully imposes no cost when const-prop works: + so = @dynamic_order(success_order) do success_order + success_order + end + fo = @dynamic_order(fail_order) do fail_order + fail_order + end + return atomic_pointerreplace(pointer, expected, desired, so, fo) +end + +@inline function atomic_pointerreplace( + ptr::LLVMPtr{T}, + expected::T, + desired::T, + ::Val{:not_atomic}, + ::Val{:not_atomic}, +) where {T} + old = atomic_pointerref(ptr, Val(:not_atomic)) + if old === expected + atomic_pointerset(ptr, desired, Val(:not_atomic)) + success = true + else + success = false + end + return (; old, success) +end + +@inline atomic_pointerreplace( + ptr::LLVMPtr{T}, + expected::T, + desired::T, + success_order::_julia_ordering(∉((:not_atomic, :unordered))), + fail_order::_julia_ordering(∉((:not_atomic, :unordered, :release, :acquire_release))), +) where {T} = llvm_atomic_cas( + ptr, + expected, + desired, + llvm_from_julia_ordering(success_order), + llvm_from_julia_ordering(fail_order), +) diff --git a/ext/UnsafeAtomicsLLVM/src/internal.jl b/ext/UnsafeAtomicsLLVM/src/internal.jl index 88d65de..caaa84e 100644 --- a/ext/UnsafeAtomicsLLVM/src/internal.jl +++ b/ext/UnsafeAtomicsLLVM/src/internal.jl @@ -4,19 +4,21 @@ julia_ordering_name(::typeof(UnsafeAtomics.acquire_release)) = :acquire_release julia_ordering_name(::typeof(UnsafeAtomics.sequentially_consistent)) = :sequentially_consistent +include("atomics.jl") + @inline UnsafeAtomics.load(ptr::LLVMPtr, order::Ordering) = - LLVM.Interop.atomic_pointerref(ptr, Val{julia_ordering_name(order)}()) + atomic_pointerref(ptr, Val{julia_ordering_name(order)}()) @inline function UnsafeAtomics.store!(ptr::LLVMPtr, x, order::Ordering) - LLVM.Interop.atomic_pointerset(ptr, x, Val{julia_ordering_name(order)}()) + atomic_pointerset(ptr, x, Val{julia_ordering_name(order)}()) return end mapop(op::OP) where {OP} = op -mapop(::typeof(UnsafeAtomics.right)) = LLVM.Interop.right +mapop(::typeof(UnsafeAtomics.right)) = right @inline UnsafeAtomics.modify!(ptr::LLVMPtr, op::OP, x, order::Ordering) where {OP} = - LLVM.Interop.atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}()) + atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}()) @inline UnsafeAtomics.cas!( ptr::LLVMPtr, @@ -24,7 +26,7 @@ mapop(::typeof(UnsafeAtomics.right)) = LLVM.Interop.right desired, success_order::Ordering, failure_order::Ordering, -) = LLVM.Interop.atomic_pointerreplace( +) = atomic_pointerreplace( ptr, expected, desired, From 8606e35b9a8f8ddbed6a55291c20be2a2a46c28d Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 27 Mar 2023 10:56:00 -0400 Subject: [PATCH 11/23] Update Project.toml --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 9c5ff82..74db7be 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.2" +version = "0.1.1" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" From 89b63a5b2b5034f45959710faa4b85ba49a444e0 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 28 Mar 2023 13:04:52 +0200 Subject: [PATCH 12/23] Compatibility with LLVM 5. (JuliaConcurrent/UnsafeAtomicsLLVM.jl#9) --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- ext/UnsafeAtomicsLLVM/src/atomics.jl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 74db7be..9fcee6f 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -8,6 +8,6 @@ LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] -LLVM = "4.12" +LLVM = "5" UnsafeAtomics = "0.2" julia = "1.6" diff --git a/ext/UnsafeAtomicsLLVM/src/atomics.jl b/ext/UnsafeAtomicsLLVM/src/atomics.jl index a8078fd..49d52ed 100644 --- a/ext/UnsafeAtomicsLLVM/src/atomics.jl +++ b/ext/UnsafeAtomicsLLVM/src/atomics.jl @@ -163,12 +163,12 @@ end llvm_f, _ = create_function(eltyp, param_types) # generate IR - @dispose builder = Builder(ctx) begin + @dispose builder = IRBuilder(ctx) begin entry = BasicBlock(llvm_f, "entry"; ctx) position!(builder, entry) typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) - ld = load!(builder, typed_ptr) + ld = load!(builder, eltyp, typed_ptr) ordering!(ld, llvm_order) if A != 0 @@ -208,7 +208,7 @@ end llvm_f, _ = create_function(LLVM.VoidType(ctx), param_types) # generate IR - @dispose builder = Builder(ctx) begin + @dispose builder = IRBuilder(ctx) begin entry = BasicBlock(llvm_f, "entry"; ctx) position!(builder, entry) @@ -266,7 +266,7 @@ const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...} llvm_f, _ = create_function(T_val, [T_ptr, T_val]) - @dispose builder = Builder(ctx) begin + @dispose builder = IRBuilder(ctx) begin entry = BasicBlock(llvm_f, "entry"; ctx) position!(builder, entry) @@ -405,7 +405,7 @@ end llvm_f, _ = create_function(T_val, [T_ptr, T_val, T_val, T_success]) - @dispose builder = Builder(ctx) begin + @dispose builder = IRBuilder(ctx) begin entry = BasicBlock(llvm_f, "entry"; ctx) position!(builder, entry) From 00cfcd3f7b75ddc74cd7648a2835fe2da0010c3e Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 28 Mar 2023 13:05:08 +0200 Subject: [PATCH 13/23] Bump version. --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 9fcee6f..5623e99 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.1" +version = "0.1.2" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" From 6f681bd28f0be3967e0be13d47fbed238a86cb3c Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 23 Jun 2023 13:33:11 +0200 Subject: [PATCH 14/23] Compatibility with LLVM 6. --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- ext/UnsafeAtomicsLLVM/src/atomics.jl | 46 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 5623e99..a608345 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -8,6 +8,6 @@ LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] -LLVM = "5" +LLVM = "6" UnsafeAtomics = "0.2" julia = "1.6" diff --git a/ext/UnsafeAtomicsLLVM/src/atomics.jl b/ext/UnsafeAtomicsLLVM/src/atomics.jl index 49d52ed..fa3908e 100644 --- a/ext/UnsafeAtomicsLLVM/src/atomics.jl +++ b/ext/UnsafeAtomicsLLVM/src/atomics.jl @@ -152,9 +152,9 @@ end sizeof(T) == 0 && return T.instance llvm_order = _valueof(llvm_from_julia_ordering(order())) @dispose ctx = Context() begin - eltyp = convert(LLVMType, T; ctx) + eltyp = convert(LLVMType, T) - T_ptr = convert(LLVMType, ptr; ctx) + T_ptr = convert(LLVMType, ptr) T_typed_ptr = LLVM.PointerType(eltyp, A) @@ -163,8 +163,8 @@ end llvm_f, _ = create_function(eltyp, param_types) # generate IR - @dispose builder = IRBuilder(ctx) begin - entry = BasicBlock(llvm_f, "entry"; ctx) + @dispose builder = IRBuilder() begin + entry = BasicBlock(llvm_f, "entry") position!(builder, entry) typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) @@ -172,7 +172,7 @@ end ordering!(ld, llvm_order) if A != 0 - metadata(ld)[LLVM.MD_tbaa] = tbaa_addrspace(A; ctx) + metadata(ld)[LLVM.MD_tbaa] = tbaa_addrspace(A) end alignment!(ld, sizeof(T)) @@ -199,17 +199,17 @@ end end llvm_order = _valueof(llvm_from_julia_ordering(order())) @dispose ctx = Context() begin - eltyp = convert(LLVMType, T; ctx) - T_ptr = convert(LLVMType, ptr; ctx) + eltyp = convert(LLVMType, T) + T_ptr = convert(LLVMType, ptr) T_typed_ptr = LLVM.PointerType(eltyp, A) # create a function param_types = [T_ptr, eltyp] - llvm_f, _ = create_function(LLVM.VoidType(ctx), param_types) + llvm_f, _ = create_function(LLVM.VoidType(), param_types) # generate IR - @dispose builder = IRBuilder(ctx) begin - entry = BasicBlock(llvm_f, "entry"; ctx) + @dispose builder = IRBuilder() begin + entry = BasicBlock(llvm_f, "entry") position!(builder, entry) typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) @@ -218,7 +218,7 @@ end ordering!(st, llvm_order) if A != 0 - metadata(st)[LLVM.MD_tbaa] = tbaa_addrspace(A; ctx) + metadata(st)[LLVM.MD_tbaa] = tbaa_addrspace(A) end alignment!(st, sizeof(T)) @@ -259,15 +259,15 @@ const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...} order::LLVMOrderingVal, ) where {T,A} @dispose ctx = Context() begin - T_val = convert(LLVMType, T; ctx) - T_ptr = convert(LLVMType, ptr; ctx) + T_val = convert(LLVMType, T) + T_ptr = convert(LLVMType, ptr) T_typed_ptr = LLVM.PointerType(T_val, A) llvm_f, _ = create_function(T_val, [T_ptr, T_val]) - @dispose builder = IRBuilder(ctx) begin - entry = BasicBlock(llvm_f, "entry"; ctx) + @dispose builder = IRBuilder() begin + entry = BasicBlock(llvm_f, "entry") position!(builder, entry) typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) @@ -392,21 +392,21 @@ end llvm_success = _valueof(success_order()) llvm_fail = _valueof(fail_order()) @dispose ctx = Context() begin - T_val = convert(LLVMType, T; ctx) + T_val = convert(LLVMType, T) T_pointee = T_val if T_val isa LLVM.FloatingPointType - T_pointee = LLVM.IntType(sizeof(T) * 8; ctx) + T_pointee = LLVM.IntType(sizeof(T) * 8) end - T_ptr = convert(LLVMType, ptr; ctx) - T_success = convert(LLVMType, Ptr{Int8}; ctx) + T_ptr = convert(LLVMType, ptr) + T_success = convert(LLVMType, Ptr{Int8}) T_typed_ptr = LLVM.PointerType(T_pointee, A) - T_ok_ptr = LLVM.PointerType(convert(LLVMType, Int8; ctx)) + T_ok_ptr = LLVM.PointerType(convert(LLVMType, Int8)) llvm_f, _ = create_function(T_val, [T_ptr, T_val, T_val, T_success]) - @dispose builder = IRBuilder(ctx) begin - entry = BasicBlock(llvm_f, "entry"; ctx) + @dispose builder = IRBuilder() begin + entry = BasicBlock(llvm_f, "entry") position!(builder, entry) typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) @@ -435,7 +435,7 @@ end rv = extract_value!(builder, res, 0) ok = extract_value!(builder, res, 1) - ok = zext!(builder, ok, LLVM.Int8Type(ctx)) + ok = zext!(builder, ok, LLVM.Int8Type()) store!(builder, ok, ok_ptr) if T_val isa LLVM.FloatingPointType From 62277da6e162036f0b0de0d885ef42be0557ec27 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 23 Jun 2023 13:33:32 +0200 Subject: [PATCH 15/23] Simplify tests. --- ext/UnsafeAtomicsLLVM/test/Project.toml | 5 +- .../test/UnsafeAtomicsLLVMTests/Project.toml | 12 ---- .../src/UnsafeAtomicsLLVMTests.jl | 5 -- .../UnsafeAtomicsLLVMTests/src/test_core.jl | 72 ------------------- ext/UnsafeAtomicsLLVM/test/runtests.jl | 71 +++++++++++++++++- 5 files changed, 70 insertions(+), 95 deletions(-) delete mode 100644 ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml delete mode 100644 ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl delete mode 100644 ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl diff --git a/ext/UnsafeAtomicsLLVM/test/Project.toml b/ext/UnsafeAtomicsLLVM/test/Project.toml index 77d6950..faacfee 100644 --- a/ext/UnsafeAtomicsLLVM/test/Project.toml +++ b/ext/UnsafeAtomicsLLVM/test/Project.toml @@ -1,6 +1,3 @@ [deps] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -TestFunctionRunner = "792026f5-ac9a-4a19-adcb-47b0ce2deb5d" - -[compat] -TestFunctionRunner = "0.1" +UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" diff --git a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml deleted file mode 100644 index ef96aae..0000000 --- a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/Project.toml +++ /dev/null @@ -1,12 +0,0 @@ -name = "UnsafeAtomicsLLVMTests" -uuid = "f81c5320-9584-4f93-9445-2842f5246c7e" -authors = ["Takafumi Arakaki and contributors"] -version = "0.1.0-DEV" - -[deps] -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" -UnsafeAtomicsLLVM = "d80eeb9a-aca5-4d75-85e5-170c8b632249" - -[compat] -julia = "1.6" diff --git a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl deleted file mode 100644 index 78a611c..0000000 --- a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/UnsafeAtomicsLLVMTests.jl +++ /dev/null @@ -1,5 +0,0 @@ -module UnsafeAtomicsLLVMTests - -include("test_core.jl") - -end # module UnsafeAtomicsLLVMTests diff --git a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl b/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl deleted file mode 100644 index 1c83b67..0000000 --- a/ext/UnsafeAtomicsLLVM/test/UnsafeAtomicsLLVMTests/src/test_core.jl +++ /dev/null @@ -1,72 +0,0 @@ -module TestCore - -import UnsafeAtomicsLLVM - -using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel -using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes -using Test - -llvmptr(xs::Array, i) = reinterpret(Core.LLVMPtr{eltype(xs),0}, pointer(xs, i)) - -function test_default_ordering() - @testset for T in inttypes - check_default_ordering(T) - end -end - -function check_default_ordering(T::Type) - xs = T[rand(T), rand(T)] - x1 = rand(T) - x2 = rand(T) - @debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))" - - ptr = llvmptr(xs, 1) - GC.@preserve xs begin - @test UnsafeAtomics.load(ptr) === xs[1] - UnsafeAtomics.store!(ptr, x1) - @test xs[1] === x1 - desired = (old = x1, success = true) - @test UnsafeAtomics.cas!(ptr, x1, x2) === (old = x1, success = true) - @test xs[1] === x2 - @testset for (op, name) in OP_RMW_TABLE - xs[1] = x1 - @test UnsafeAtomics.modify!(ptr, op, x2) === (x1 => op(x1, x2)) - @test xs[1] === op(x1, x2) - - rmw = getfield(UnsafeAtomics, Symbol(name, :!)) - xs[1] = x1 - @test rmw(ptr, x2) === x1 - @test xs[1] === op(x1, x2) - end - end -end - -function test_explicit_ordering(T::Type = UInt) - xs = T[rand(T), rand(T)] - x1 = rand(T) - x2 = rand(T) - @debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))" - - ptr = llvmptr(xs, 1) - GC.@preserve xs begin - - @test UnsafeAtomics.load(ptr, acquire) === xs[1] - UnsafeAtomics.store!(ptr, x1, release) - @test xs[1] === x1 - desired = (old = x1, success = true) - @test UnsafeAtomics.cas!(ptr, x1, x2, acq_rel, acquire) === desired - @test xs[1] === x2 - @testset for (op, name) in OP_RMW_TABLE - xs[1] = x1 - @test UnsafeAtomics.modify!(ptr, op, x2, acq_rel) === (x1 => op(x1, x2)) - @test xs[1] === op(x1, x2) - - rmw = getfield(UnsafeAtomics, Symbol(name, :!)) - xs[1] = x1 - @test rmw(ptr, x2, acquire) === x1 - @test xs[1] === op(x1, x2) - end - end -end - -end # module diff --git a/ext/UnsafeAtomicsLLVM/test/runtests.jl b/ext/UnsafeAtomicsLLVM/test/runtests.jl index d358b79..b27b351 100644 --- a/ext/UnsafeAtomicsLLVM/test/runtests.jl +++ b/ext/UnsafeAtomicsLLVM/test/runtests.jl @@ -1,2 +1,69 @@ -using TestFunctionRunner -TestFunctionRunner.@run +import UnsafeAtomicsLLVM + +using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel +using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes +using Test + +llvmptr(xs::Array, i) = reinterpret(Core.LLVMPtr{eltype(xs),0}, pointer(xs, i)) + +function check_default_ordering(T::Type) + xs = T[rand(T), rand(T)] + x1 = rand(T) + x2 = rand(T) + @debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))" + + ptr = llvmptr(xs, 1) + GC.@preserve xs begin + @test UnsafeAtomics.load(ptr) === xs[1] + UnsafeAtomics.store!(ptr, x1) + @test xs[1] === x1 + desired = (old = x1, success = true) + @test UnsafeAtomics.cas!(ptr, x1, x2) === (old = x1, success = true) + @test xs[1] === x2 + @testset for (op, name) in OP_RMW_TABLE + xs[1] = x1 + @test UnsafeAtomics.modify!(ptr, op, x2) === (x1 => op(x1, x2)) + @test xs[1] === op(x1, x2) + + rmw = getfield(UnsafeAtomics, Symbol(name, :!)) + xs[1] = x1 + @test rmw(ptr, x2) === x1 + @test xs[1] === op(x1, x2) + end + end +end + +function test_explicit_ordering(T::Type = UInt) + xs = T[rand(T), rand(T)] + x1 = rand(T) + x2 = rand(T) + @debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))" + + ptr = llvmptr(xs, 1) + GC.@preserve xs begin + + @test UnsafeAtomics.load(ptr, acquire) === xs[1] + UnsafeAtomics.store!(ptr, x1, release) + @test xs[1] === x1 + desired = (old = x1, success = true) + @test UnsafeAtomics.cas!(ptr, x1, x2, acq_rel, acquire) === desired + @test xs[1] === x2 + @testset for (op, name) in OP_RMW_TABLE + xs[1] = x1 + @test UnsafeAtomics.modify!(ptr, op, x2, acq_rel) === (x1 => op(x1, x2)) + @test xs[1] === op(x1, x2) + + rmw = getfield(UnsafeAtomics, Symbol(name, :!)) + xs[1] = x1 + @test rmw(ptr, x2, acquire) === x1 + @test xs[1] === op(x1, x2) + end + end +end + +@testset "UnsafeAtomicsLLVM" begin + @testset for T in inttypes + check_default_ordering(T) + test_explicit_ordering(T) + end +end From 26db363574e8d4a6c4aeb17f1d6eab3fe3a094d5 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 23 Jun 2023 13:47:17 +0200 Subject: [PATCH 16/23] Bump version. --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index a608345..3552e93 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.2" +version = "0.1.3" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" From 4c2b0cedb986cc332af75f99a2ecc77d28ac33fc Mon Sep 17 00:00:00 2001 From: Anton Smirnov Date: Tue, 21 May 2024 14:15:48 +0300 Subject: [PATCH 17/23] Add fmin/fmax for Julia 1.10 (JuliaConcurrent/UnsafeAtomicsLLVM.jl#11) --- ext/UnsafeAtomicsLLVM/src/atomics.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/src/atomics.jl b/ext/UnsafeAtomicsLLVM/src/atomics.jl index fa3908e..823e60f 100644 --- a/ext/UnsafeAtomicsLLVM/src/atomics.jl +++ b/ext/UnsafeAtomicsLLVM/src/atomics.jl @@ -249,6 +249,10 @@ const binoptable = [ (:fadd, +, LLVM.API.LLVMAtomicRMWBinOpFAdd), (:fsub, -, LLVM.API.LLVMAtomicRMWBinOpFSub), ] +if VERSION ≥ v"1.10-" + push!(binoptable, (:fmax, max, LLVM.API.LLVMAtomicRMWBinOpFMax)) + push!(binoptable, (:fmin, min, LLVM.API.LLVMAtomicRMWBinOpFMin)) +end const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...} @@ -344,7 +348,7 @@ for (opname, op, llvmop) in binoptable filter(t -> t <: Signed, atomictypes) elseif opname in (:umin, :umax) filter(t -> t <: Unsigned, atomictypes) - elseif opname in (:fadd, :fsub) + elseif opname in (:fadd, :fsub, :fmin, :fmax) filter(t -> t <: AbstractFloat, atomictypes) else filter(t -> t <: Integer, atomictypes) From 519aadcd58eb8f143557421fc64876a33007e0b1 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 21 May 2024 13:17:14 +0200 Subject: [PATCH 18/23] Update GitHub actions. --- .../.github/workflows/CompatHelper.yml | 43 +++++++++++++++++++ .../.github/workflows/TagBot.yml | 24 ++++++++--- 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 ext/UnsafeAtomicsLLVM/.github/workflows/CompatHelper.yml diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/CompatHelper.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/CompatHelper.yml new file mode 100644 index 0000000..8765dd6 --- /dev/null +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/CompatHelper.yml @@ -0,0 +1,43 @@ +name: CompatHelper +on: + schedule: + - cron: 0 0 * * * + workflow_dispatch: +permissions: + contents: write + pull-requests: write +jobs: + CompatHelper: + runs-on: ubuntu-latest + steps: + - name: Check if Julia is already available in the PATH + id: julia_in_path + run: which julia + continue-on-error: true + - name: Install Julia, but only if it is not already available in the PATH + uses: julia-actions/setup-julia@v1 + with: + version: '1' + arch: ${{ runner.arch }} + if: steps.julia_in_path.outcome != 'success' + - name: "Add the General registry via Git" + run: | + import Pkg + ENV["JULIA_PKG_SERVER"] = "" + Pkg.Registry.add("General") + shell: julia --color=yes {0} + - name: "Install CompatHelper" + run: | + import Pkg + name = "CompatHelper" + uuid = "aa819f21-2bde-4658-8897-bab36330d9b7" + version = "3" + Pkg.add(; name, uuid, version) + shell: julia --color=yes {0} + - name: "Run CompatHelper" + run: | + import CompatHelper + CompatHelper.main() + shell: julia --color=yes {0} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml index 5c8d528..a3de268 100644 --- a/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/TagBot.yml @@ -3,16 +3,26 @@ on: issue_comment: types: - created - push: - branches: - - actions/trigger/TagBot workflow_dispatch: + inputs: + lookback: + default: "3" +permissions: + actions: read + checks: read + contents: write + deployments: read + issues: read + discussions: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: read + statuses: read jobs: TagBot: - if: >- - github.event_name == 'workflow_dispatch' || - github.event_name == 'push' || - github.actor == 'JuliaTagBot' + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' runs-on: ubuntu-latest steps: - uses: JuliaRegistries/TagBot@v1 From bcc40d99c1d271e937d4c5427274e1a458332c51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:27:04 +0200 Subject: [PATCH 19/23] CompatHelper: bump compat for LLVM to 7, (keep existing compat) (JuliaConcurrent/UnsafeAtomicsLLVM.jl#12) Co-authored-by: CompatHelper Julia --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 3552e93..cab4438 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -8,6 +8,6 @@ LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] -LLVM = "6" +LLVM = "6, 7" UnsafeAtomics = "0.2" julia = "1.6" From 8a5c9187aff2d32de46a80046d6d4e8e36e9e714 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 21 May 2024 13:27:27 +0200 Subject: [PATCH 20/23] Bump version. --- ext/UnsafeAtomicsLLVM/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index cab4438..d8b1003 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,7 +1,7 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.3" +version = "0.1.4" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" From 594587e0d2bcc3ec8c9eab8678428c70d3bfa377 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Wed, 26 Jun 2024 22:19:09 +0200 Subject: [PATCH 21/23] Bump LLVM compat (JuliaConcurrent/UnsafeAtomicsLLVM.jl#13) --- ext/UnsafeAtomicsLLVM/Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index d8b1003..48d4011 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,13 +1,13 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.4" +version = "0.1.5" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] -LLVM = "6, 7" +LLVM = "6, 7, 8" UnsafeAtomics = "0.2" julia = "1.6" From d6a5432bb237976d7448d3835939be48fd929c4b Mon Sep 17 00:00:00 2001 From: Anton Smirnov Date: Wed, 7 Aug 2024 10:15:29 +0300 Subject: [PATCH 22/23] Expose syncscope parameter for atomic add/sub (JuliaConcurrent/UnsafeAtomicsLLVM.jl#14) --- .../.github/workflows/ci.yml | 6 +- ext/UnsafeAtomicsLLVM/Project.toml | 6 +- ext/UnsafeAtomicsLLVM/src/atomics.jl | 57 +++++++++++++++++-- ext/UnsafeAtomicsLLVM/src/internal.jl | 9 +++ ext/UnsafeAtomicsLLVM/test/runtests.jl | 15 ++++- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml index 5207671..4df1690 100644 --- a/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml +++ b/ext/UnsafeAtomicsLLVM/.github/workflows/ci.yml @@ -13,8 +13,7 @@ jobs: strategy: matrix: julia-version: - - '1' - - '1.6' + - '1.10' - 'nightly' fail-fast: false name: Test Julia ${{ matrix.julia-version }} @@ -36,8 +35,7 @@ jobs: strategy: matrix: julia-version: - - '1' - - '1.6' + - '1.10' - 'nightly' fail-fast: false steps: diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index 48d4011..f0d04dc 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,13 +1,13 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.1.5" +version = "0.2.0" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] -LLVM = "6, 7, 8" +LLVM = "8.1" UnsafeAtomics = "0.2" -julia = "1.6" +julia = "1.10" diff --git a/ext/UnsafeAtomicsLLVM/src/atomics.jl b/ext/UnsafeAtomicsLLVM/src/atomics.jl index 823e60f..9b1e504 100644 --- a/ext/UnsafeAtomicsLLVM/src/atomics.jl +++ b/ext/UnsafeAtomicsLLVM/src/atomics.jl @@ -248,14 +248,15 @@ const binoptable = [ (:umin, min, LLVM.API.LLVMAtomicRMWBinOpUMin), (:fadd, +, LLVM.API.LLVMAtomicRMWBinOpFAdd), (:fsub, -, LLVM.API.LLVMAtomicRMWBinOpFSub), + (:fmax, max, LLVM.API.LLVMAtomicRMWBinOpFMax), + (:fmin, min, LLVM.API.LLVMAtomicRMWBinOpFMin), ] -if VERSION ≥ v"1.10-" - push!(binoptable, (:fmax, max, LLVM.API.LLVMAtomicRMWBinOpFMax)) - push!(binoptable, (:fmin, min, LLVM.API.LLVMAtomicRMWBinOpFMin)) -end const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...} +# LLVM API accepts string literal as a syncscope argument. +@inline syncscope_to_string(::Type{Val{S}}) where {S} = string(S) + @generated function llvm_atomic_op( binop::AtomicRMWBinOpVal, ptr::LLVMPtr{T,A}, @@ -293,6 +294,40 @@ const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...} end end +@generated function llvm_atomic_op( + binop::AtomicRMWBinOpVal, + ptr::LLVMPtr{T,A}, + val::T, + order::LLVMOrderingVal, + syncscope::Val{S}, +) where {T,A,S} + @dispose ctx = Context() begin + T_val = convert(LLVMType, T) + T_ptr = convert(LLVMType, ptr) + + T_typed_ptr = LLVM.PointerType(T_val, A) + llvm_f, _ = create_function(T_val, [T_ptr, T_val]) + + @dispose builder = IRBuilder() begin + entry = BasicBlock(llvm_f, "entry") + position!(builder, entry) + + typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr) + rv = atomic_rmw!( + builder, + _valueof(binop()), + typed_ptr, + parameters(llvm_f)[2], + _valueof(order()), + syncscope_to_string(syncscope), + ) + + ret!(builder, rv) + end + call_function(llvm_f, T, Tuple{LLVMPtr{T,A},T}, :ptr, :val) + end +end + @inline function atomic_pointermodify(pointer, op::OP, x, order::Symbol) where {OP} @dynamic_order(order) do order atomic_pointermodify(pointer, op, x, order) @@ -359,8 +394,18 @@ for (opname, op, llvmop) in binoptable ::$(typeof(op)), x::$T, order::AtomicOrdering, - ) - old = llvm_atomic_op($(Val(llvmop)), ptr, x, llvm_from_julia_ordering(order)) + syncscope::Val{S} = Val{:system}(), + ) where {S} + old = + syncscope isa Val{:system} ? + llvm_atomic_op($(Val(llvmop)), ptr, x, llvm_from_julia_ordering(order)) : + llvm_atomic_op( + $(Val(llvmop)), + ptr, + x, + llvm_from_julia_ordering(order), + syncscope, + ) return old => $op(old, x) end end diff --git a/ext/UnsafeAtomicsLLVM/src/internal.jl b/ext/UnsafeAtomicsLLVM/src/internal.jl index caaa84e..e4ed556 100644 --- a/ext/UnsafeAtomicsLLVM/src/internal.jl +++ b/ext/UnsafeAtomicsLLVM/src/internal.jl @@ -20,6 +20,15 @@ mapop(::typeof(UnsafeAtomics.right)) = right @inline UnsafeAtomics.modify!(ptr::LLVMPtr, op::OP, x, order::Ordering) where {OP} = atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}()) +@inline UnsafeAtomics.modify!( + ptr::LLVMPtr, + op::OP, + x, + order::Ordering, + syncscope::Val{S} = Val(:system), +) where {OP<:Union{typeof(+),typeof(-)},S} = + atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}(), syncscope) + @inline UnsafeAtomics.cas!( ptr::LLVMPtr, expected, diff --git a/ext/UnsafeAtomicsLLVM/test/runtests.jl b/ext/UnsafeAtomicsLLVM/test/runtests.jl index b27b351..9ee4bfe 100644 --- a/ext/UnsafeAtomicsLLVM/test/runtests.jl +++ b/ext/UnsafeAtomicsLLVM/test/runtests.jl @@ -1,6 +1,6 @@ import UnsafeAtomicsLLVM -using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel +using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel, seq_cst using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes using Test @@ -57,6 +57,19 @@ function test_explicit_ordering(T::Type = UInt) xs[1] = x1 @test rmw(ptr, x2, acquire) === x1 @test xs[1] === op(x1, x2) + + # Test syncscopes. + if (op == +) || (op == -) + xs[1] = x1 + @test UnsafeAtomics.modify!(ptr, op, x2, seq_cst, Val(:system)) === + (x1 => op(x1, x2)) + @test xs[1] === op(x1, x2) + + xs[1] = x1 + @test UnsafeAtomics.modify!(ptr, op, x2, seq_cst, Val(:singlethread)) === + (x1 => op(x1, x2)) + @test xs[1] === op(x1, x2) + end end end end From fb9fda02a27ff135419fbf2ca025f5fe67c3da98 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 22 Aug 2024 19:54:52 +0200 Subject: [PATCH 23/23] Update Project.toml (JuliaConcurrent/UnsafeAtomicsLLVM.jl#15) --- ext/UnsafeAtomicsLLVM/Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/UnsafeAtomicsLLVM/Project.toml b/ext/UnsafeAtomicsLLVM/Project.toml index f0d04dc..5c4191f 100644 --- a/ext/UnsafeAtomicsLLVM/Project.toml +++ b/ext/UnsafeAtomicsLLVM/Project.toml @@ -1,13 +1,13 @@ name = "UnsafeAtomicsLLVM" uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" authors = ["Takafumi Arakaki and contributors"] -version = "0.2.0" +version = "0.2.1" [deps] LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" [compat] -LLVM = "8.1" +LLVM = "8.1, 9" UnsafeAtomics = "0.2" julia = "1.10"