Skip to content

Commit b20e1a3

Browse files
committed
[C API] Fix LLVMGetOrdering/LLVMIsAtomicSingleThread for fence/memory instrs
LLVMGetOrdering previously did not support Fence instructions, and calling it on a fence would lead to a bad cast as it assumed a load/store, or an AtomicRMWInst. This would either read a garbage memory order, or assertion LLVMIsAtomicSingleThread did not support either Fence instructions, loads, or stores, and would similarly lead to a bad cast These cases are now fixed for the C API, and tests for these instructions are added. The echo test utility now also supports cloning Fence instructions, which it did not previously
1 parent c2bee1e commit b20e1a3

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

llvm/lib/IR/Core.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3758,6 +3758,8 @@ LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemAccessInst) {
37583758
O = LI->getOrdering();
37593759
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
37603760
O = SI->getOrdering();
3761+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
3762+
O = FI->getOrdering();
37613763
else
37623764
O = cast<AtomicRMWInst>(P)->getOrdering();
37633765
return mapToLLVMOrdering(O);
@@ -3769,6 +3771,8 @@ void LLVMSetOrdering(LLVMValueRef MemAccessInst, LLVMAtomicOrdering Ordering) {
37693771

37703772
if (LoadInst *LI = dyn_cast<LoadInst>(P))
37713773
return LI->setOrdering(O);
3774+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
3775+
return FI->setOrdering(O);
37723776
return cast<StoreInst>(P)->setOrdering(O);
37733777
}
37743778

@@ -4039,6 +4043,12 @@ LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
40394043

40404044
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
40414045
return I->getSyncScopeID() == SyncScope::SingleThread;
4046+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
4047+
return FI->getSyncScopeID() == SyncScope::SingleThread;
4048+
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
4049+
return SI->getSyncScopeID() == SyncScope::SingleThread;
4050+
else if (LoadInst *LI = dyn_cast<LoadInst>(P))
4051+
return LI->getSyncScopeID() == SyncScope::SingleThread;
40424052
return cast<AtomicCmpXchgInst>(P)->getSyncScopeID() ==
40434053
SyncScope::SingleThread;
40444054
}
@@ -4049,6 +4059,12 @@ void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
40494059

40504060
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
40514061
return I->setSyncScopeID(SSID);
4062+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
4063+
return FI->setSyncScopeID(SSID);
4064+
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
4065+
return SI->setSyncScopeID(SSID);
4066+
else if (LoadInst *LI = dyn_cast<LoadInst>(P))
4067+
return LI->setSyncScopeID(SSID);
40524068
return cast<AtomicCmpXchgInst>(P)->setSyncScopeID(SSID);
40534069
}
40544070

llvm/test/Bindings/llvm-c/atomics.ll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,40 @@
22
; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
33
; RUN: diff -w %t.orig %t.echo
44

5+
6+
define void @fence_instrs() {
7+
fence acquire
8+
fence release
9+
fence acq_rel
10+
fence seq_cst
11+
12+
fence syncscope("singlethread") acquire
13+
fence syncscope("singlethread") release
14+
fence syncscope("singlethread") acq_rel
15+
fence syncscope("singlethread") seq_cst
16+
17+
ret void
18+
}
19+
20+
define void @atomic_load_store(ptr %word) {
21+
; Test different atomic loads
22+
%ld.1 = load atomic i32, ptr %word monotonic, align 4
23+
%ld.2 = load atomic volatile i32, ptr %word acquire, align 4
24+
%ld.3 = load atomic volatile i32, ptr %word seq_cst, align 4
25+
%ld.4 = load atomic volatile i32, ptr %word syncscope("singlethread") acquire, align 4
26+
%ld.5 = load atomic volatile i32, ptr %word syncscope("singlethread") seq_cst, align 4
27+
%ld.6 = load atomic i32, ptr %word syncscope("singlethread") seq_cst, align 4
28+
29+
; Test different atomic stores
30+
store atomic i32 1, ptr %word monotonic, align 4
31+
store atomic volatile i32 2, ptr %word release, align 4
32+
store atomic volatile i32 3, ptr %word seq_cst, align 4
33+
store atomic volatile i32 4, ptr %word syncscope("singlethread") release, align 4
34+
store atomic volatile i32 5, ptr %word syncscope("singlethread") seq_cst, align 4
35+
store atomic i32 6, ptr %word syncscope("singlethread") seq_cst, align 4
36+
ret void
37+
}
38+
539
define i32 @main() {
640
%1 = alloca i32, align 4
741
%2 = cmpxchg ptr %1, i32 2, i32 3 seq_cst acquire

llvm/tools/llvm-c-test/echo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ struct FunCloner {
677677
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
678678
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
679679
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
680+
LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
680681
break;
681682
}
682683
case LLVMStore: {
@@ -686,6 +687,7 @@ struct FunCloner {
686687
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
687688
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
688689
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
690+
LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
689691
break;
690692
}
691693
case LLVMGetElementPtr: {
@@ -891,6 +893,12 @@ struct FunCloner {
891893
Dst = LLVMBuildFreeze(Builder, Arg, Name);
892894
break;
893895
}
896+
case LLVMFence: {
897+
LLVMAtomicOrdering Ordering = LLVMGetOrdering(Src);
898+
LLVMBool IsSingleThreaded = LLVMIsAtomicSingleThread(Src);
899+
Dst = LLVMBuildFence(Builder, Ordering, IsSingleThreaded, Name);
900+
break;
901+
}
894902
default:
895903
break;
896904
}

0 commit comments

Comments
 (0)