-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crucible-llvm: Support atomic operations introduced in LLVM 9+ (#1226)
This adapts `crucible-llvm` to new atomic operations introduced in LLVM 9 and later: * This bumps the `llvm-pretty` submodule to incorporate the changes from GaloisInc/llvm-pretty#138 and GaloisInc/llvm-pretty#140. * This bumps the `llvm-pretty-bc-parser` submodule to incorporate changes from GaloisInc/llvm-pretty-bc-parser#274. * This updates `crucible-llvm`'s semantics for the `atomicrmw` instruction to account for atomic `fadd`, `fsub`, `fmax`, `fmin`, `uinc_wrap`, and `udec_wrap` operations. * This ensures that all atomic operations have a corresponding `crux-llvm` test case.
- Loading branch information
1 parent
8cc5e17
commit b8ff9be
Showing
16 changed files
with
344 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
@.str = private unnamed_addr constant [8 x i8] c"atomics\00" | ||
|
||
declare void @crucible_assert(i8 noundef zeroext, i8* noundef, i32 noundef) | ||
|
||
define float @atomic_fadd(float* %ptr, float %val) { | ||
%old = atomicrmw fadd float* %ptr, float %val acquire | ||
ret float %old | ||
} | ||
|
||
define float @atomic_fsub(float* %ptr, float %val) { | ||
%old = atomicrmw fsub float* %ptr, float %val acquire | ||
ret float %old | ||
} | ||
|
||
define float @atomic_xchg(float* %ptr, float %val) { | ||
%old = atomicrmw xchg float* %ptr, float %val acquire | ||
ret float %old | ||
} | ||
|
||
define void @test_atomic_float_op(float (float*, float)* %atomic_op, float %expected_old, float %val, float %expected_new) { | ||
%ptr = alloca float | ||
store float %expected_old, float* %ptr | ||
%actual_old = call float %atomic_op(float* %ptr, float %val) | ||
%actual_new = load float, float* %ptr | ||
%cmp_old = fcmp oeq float %expected_old, %actual_old | ||
%cmp_new = fcmp oeq float %expected_new, %actual_new | ||
%cmp_old_zext = zext i1 %cmp_old to i8 | ||
%cmp_new_zext = zext i1 %cmp_new to i8 | ||
%str_cast = bitcast [8 x i8]* @.str to i8* | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
ret void | ||
} | ||
|
||
define i32 @main() { | ||
call void @test_atomic_float_op(float (float*, float)* @atomic_fadd, float 2.5, float 3.0, float 5.5) | ||
call void @test_atomic_float_op(float (float*, float)* @atomic_fsub, float 3.5, float 2.0, float 1.5) | ||
call void @test_atomic_float_op(float (float*, float)* @atomic_xchg, float 2.5, float 3.0, float 3.0) | ||
ret i32 0 | ||
} |
4 changes: 4 additions & 0 deletions
4
crux-llvm/test-data/golden/atomicrmw-faddsubxchg.pre-clang9.z3.good
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
SKIP_TEST | ||
|
||
This test case requires the use of atomic `fadd` and `fsub` operations, which | ||
are only available in LLVM 9 or later. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[Crux] Overall status: Valid. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
@.str = private unnamed_addr constant [8 x i8] c"atomics\00" | ||
|
||
declare void @crucible_assert(i8 noundef zeroext, i8* noundef, i32 noundef) | ||
|
||
define float @atomic_fmax(float* %ptr, float %val) { | ||
%old = atomicrmw fmax float* %ptr, float %val acquire | ||
ret float %old | ||
} | ||
|
||
define float @atomic_fmin(float* %ptr, float %val) { | ||
%old = atomicrmw fmin float* %ptr, float %val acquire | ||
ret float %old | ||
} | ||
|
||
define void @test_atomic_float_op(float (float*, float)* %atomic_op, float %expected_old, float %val, float %expected_new) { | ||
%ptr = alloca float | ||
store float %expected_old, float* %ptr | ||
%actual_old = call float %atomic_op(float* %ptr, float %val) | ||
%actual_new = load float, float* %ptr | ||
%cmp_old = fcmp oeq float %expected_old, %actual_old | ||
%cmp_new = fcmp oeq float %expected_new, %actual_new | ||
%cmp_old_zext = zext i1 %cmp_old to i8 | ||
%cmp_new_zext = zext i1 %cmp_new to i8 | ||
%str_cast = bitcast [8 x i8]* @.str to i8* | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
ret void | ||
} | ||
|
||
define i32 @main() { | ||
call void @test_atomic_float_op(float (float*, float)* @atomic_fmax, float 2.5, float 3.0, float 3.0) | ||
call void @test_atomic_float_op(float (float*, float)* @atomic_fmin, float 2.5, float 3.0, float 2.5) | ||
ret i32 0 | ||
} |
4 changes: 4 additions & 0 deletions
4
crux-llvm/test-data/golden/atomicrmw-fmaxmin.pre-clang15.z3.good
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
SKIP_TEST | ||
|
||
This test case requires the use of atomic `fmax` and `fmin` operations, which | ||
are only available in LLVM 15 or later. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[Crux] Overall status: Valid. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
@.str = private unnamed_addr constant [8 x i8] c"atomics\00" | ||
|
||
declare void @crucible_assert(i8 noundef zeroext, i8* noundef, i32 noundef) | ||
|
||
define i32 @atomic_uinc_wrap(i32* %ptr, i32 %val) { | ||
%old = atomicrmw uinc_wrap i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_udec_wrap(i32* %ptr, i32 %val) { | ||
%old = atomicrmw udec_wrap i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define void @test_atomic_i32_op(i32 (i32*, i32)* %atomic_op, i32 %expected_old, i32 %val, i32 %expected_new) { | ||
%ptr = alloca i32 | ||
store i32 %expected_old, i32* %ptr | ||
%actual_old = call i32 %atomic_op(i32* %ptr, i32 %val) | ||
%actual_new = load i32, i32* %ptr | ||
%cmp_old = icmp eq i32 %expected_old, %actual_old | ||
%cmp_new = icmp eq i32 %expected_new, %actual_new | ||
%cmp_old_zext = zext i1 %cmp_old to i8 | ||
%cmp_new_zext = zext i1 %cmp_new to i8 | ||
%str_cast = bitcast [8 x i8]* @.str to i8* | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
ret void | ||
} | ||
|
||
define i32 @main() { | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_uinc_wrap, i32 0, i32 0, i32 0) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_uinc_wrap, i32 3, i32 2, i32 0) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_uinc_wrap, i32 2, i32 3, i32 3) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_udec_wrap, i32 0, i32 0, i32 0) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_udec_wrap, i32 3, i32 2, i32 2) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_udec_wrap, i32 2, i32 3, i32 1) | ||
ret i32 0 | ||
} |
4 changes: 4 additions & 0 deletions
4
crux-llvm/test-data/golden/atomicrmw-uincdecwrap.pre-clang16.z3.good
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
SKIP_TEST | ||
|
||
This test case requires the use of atomic `uinc_wrap` and `udec_wrap` | ||
operations, which are only available in LLVM 16 or later. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[Crux] Overall status: Valid. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
@.str = private unnamed_addr constant [8 x i8] c"atomics\00" | ||
|
||
declare void @crucible_assert(i8 noundef zeroext, i8* noundef, i32 noundef) | ||
|
||
define i32 @atomic_xchg(i32* %ptr, i32 %val) { | ||
%old = atomicrmw xchg i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_add(i32* %ptr, i32 %val) { | ||
%old = atomicrmw add i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_sub(i32* %ptr, i32 %val) { | ||
%old = atomicrmw sub i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_and(i32* %ptr, i32 %val) { | ||
%old = atomicrmw and i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_nand(i32* %ptr, i32 %val) { | ||
%old = atomicrmw nand i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_or(i32* %ptr, i32 %val) { | ||
%old = atomicrmw or i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_xor(i32* %ptr, i32 %val) { | ||
%old = atomicrmw xor i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_max(i32* %ptr, i32 %val) { | ||
%old = atomicrmw max i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_min(i32* %ptr, i32 %val) { | ||
%old = atomicrmw min i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_umax(i32* %ptr, i32 %val) { | ||
%old = atomicrmw umax i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define i32 @atomic_umin(i32* %ptr, i32 %val) { | ||
%old = atomicrmw umin i32* %ptr, i32 %val acquire | ||
ret i32 %old | ||
} | ||
|
||
define void @test_atomic_i32_op(i32 (i32*, i32)* %atomic_op, i32 %expected_old, i32 %val, i32 %expected_new) { | ||
%ptr = alloca i32 | ||
store i32 %expected_old, i32* %ptr | ||
%actual_old = call i32 %atomic_op(i32* %ptr, i32 %val) | ||
%actual_new = load i32, i32* %ptr | ||
%cmp_old = icmp eq i32 %expected_old, %actual_old | ||
%cmp_new = icmp eq i32 %expected_new, %actual_new | ||
%cmp_old_zext = zext i1 %cmp_old to i8 | ||
%cmp_new_zext = zext i1 %cmp_new to i8 | ||
%str_cast = bitcast [8 x i8]* @.str to i8* | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
call void @crucible_assert(i8 noundef zeroext %cmp_old_zext, i8* noundef %str_cast, i32 noundef 0) | ||
ret void | ||
} | ||
|
||
define i32 @main() { | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_xchg, i32 2, i32 3, i32 3) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_add, i32 2, i32 3, i32 5) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_sub, i32 3, i32 2, i32 1) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_and, i32 2, i32 3, i32 2) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_nand, i32 2, i32 3, i32 4294967293) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_or, i32 2, i32 3, i32 3) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_xor, i32 2, i32 3, i32 1) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_max, i32 4294967293, i32 3, i32 3) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_min, i32 4294967293, i32 3, i32 4294967293) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_umax, i32 2, i32 3, i32 3) | ||
call void @test_atomic_i32_op(i32 (i32*, i32)* @atomic_umin, i32 2, i32 3, i32 2) | ||
ret i32 0 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[Crux] Overall status: Valid. |
Oops, something went wrong.