Skip to content

Commit d222c5e

Browse files
authored
[C API] Fix LLVMGetOrdering/LLVMIsAtomicSingleThread for fence/memory instrs (#65228)
Fixes #65227 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. It happened to work out since the relevant types all have their synch scope ID at the same offset, but it still should be fixed 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 ----- From what I can tell, there's no unified API to pull `getOrdering`/`getSyncScopeID` from, and instead requires casting to individual types: if there is a better way of handling this I can switch to that
1 parent dc1dc60 commit d222c5e

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

llvm/lib/IR/Core.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3753,6 +3753,8 @@ LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemAccessInst) {
37533753
O = LI->getOrdering();
37543754
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
37553755
O = SI->getOrdering();
3756+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
3757+
O = FI->getOrdering();
37563758
else
37573759
O = cast<AtomicRMWInst>(P)->getOrdering();
37583760
return mapToLLVMOrdering(O);
@@ -3764,6 +3766,10 @@ void LLVMSetOrdering(LLVMValueRef MemAccessInst, LLVMAtomicOrdering Ordering) {
37643766

37653767
if (LoadInst *LI = dyn_cast<LoadInst>(P))
37663768
return LI->setOrdering(O);
3769+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
3770+
return FI->setOrdering(O);
3771+
else if (AtomicRMWInst *ARWI = dyn_cast<AtomicRMWInst>(P))
3772+
return ARWI->setOrdering(O);
37673773
return cast<StoreInst>(P)->setOrdering(O);
37683774
}
37693775

@@ -4034,6 +4040,12 @@ LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
40344040

40354041
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
40364042
return I->getSyncScopeID() == SyncScope::SingleThread;
4043+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
4044+
return FI->getSyncScopeID() == SyncScope::SingleThread;
4045+
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
4046+
return SI->getSyncScopeID() == SyncScope::SingleThread;
4047+
else if (LoadInst *LI = dyn_cast<LoadInst>(P))
4048+
return LI->getSyncScopeID() == SyncScope::SingleThread;
40374049
return cast<AtomicCmpXchgInst>(P)->getSyncScopeID() ==
40384050
SyncScope::SingleThread;
40394051
}
@@ -4044,6 +4056,12 @@ void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
40444056

40454057
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
40464058
return I->setSyncScopeID(SSID);
4059+
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
4060+
return FI->setSyncScopeID(SSID);
4061+
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
4062+
return SI->setSyncScopeID(SSID);
4063+
else if (LoadInst *LI = dyn_cast<LoadInst>(P))
4064+
return LI->setSyncScopeID(SSID);
40474065
return cast<AtomicCmpXchgInst>(P)->setSyncScopeID(SSID);
40484066
}
40494067

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)