Skip to content

Commit f57e968

Browse files
committedSep 26, 2019
Improve C API support for atomicrmw and cmpxchg.
atomicrmw and cmpxchg have a volatile flag, so allow them to be get and set with LLVM{Get,Set}Volatile. atomicrmw and fence have orderings, so allow them to be get and set with LLVM{Get,Set}Ordering. Add missing LLVMAtomicRMWBinOpFAdd and LLVMAtomicRMWBinOpFSub enum constants. AtomicCmpXchg also has a weak flag, add a getter/setter for that too. Add a getter/setter for the binary-op of an atomicrmw. atomicrmw and cmpxchg have a volatile flag, so allow it to be set/get with LLVMGetVolatile and LLVMSetVolatile. Add missing LLVMAtomicRMWBinOpFAdd and LLVMAtomicRMWBinOpFSub enum constants. AtomicCmpXchg also has a weak flag, add a getter/setter for that too. Add a getter/setter for the binary-op of an atomicrmw. Add LLVMIsA## for CatchSwitchInst, CallBrInst and FenceInst, as well as AtomicCmpXchgInst and AtomicRMWInst. Update llvm-c-test to include atomicrmw and fence, and to copy volatile for the four applicable instructions. Differential Revision: https://reviews.llvm.org/D67132 llvm-svn: 372938
1 parent da3cf61 commit f57e968

File tree

4 files changed

+125
-22
lines changed

4 files changed

+125
-22
lines changed
 

‎llvm/include/llvm-c/Core.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,13 @@ typedef enum {
370370
LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the
371371
original using an unsigned comparison and return
372372
the old one */
373-
LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the
374-
original using an unsigned comparison and return
375-
the old one */
373+
LLVMAtomicRMWBinOpUMin, /**< Sets the value if it's greater than the
374+
original using an unsigned comparison and return
375+
the old one */
376+
LLVMAtomicRMWBinOpFAdd, /**< Add a floating point value and return the
377+
old one */
378+
LLVMAtomicRMWBinOpFSub /**< Subtract a floating point value and return the
379+
old one */
376380
} LLVMAtomicRMWBinOp;
377381

378382
typedef enum {
@@ -1571,6 +1575,8 @@ LLVMTypeRef LLVMX86MMXType(void);
15711575
macro(ResumeInst) \
15721576
macro(CleanupReturnInst) \
15731577
macro(CatchReturnInst) \
1578+
macro(CatchSwitchInst) \
1579+
macro(CallBrInst) \
15741580
macro(FuncletPadInst) \
15751581
macro(CatchPadInst) \
15761582
macro(CleanupPadInst) \
@@ -1592,7 +1598,10 @@ LLVMTypeRef LLVMX86MMXType(void);
15921598
macro(ZExtInst) \
15931599
macro(ExtractValueInst) \
15941600
macro(LoadInst) \
1595-
macro(VAArgInst)
1601+
macro(VAArgInst) \
1602+
macro(AtomicCmpXchgInst) \
1603+
macro(AtomicRMWInst) \
1604+
macro(FenceInst)
15961605

15971606
/**
15981607
* @defgroup LLVMCCoreValueGeneral General APIs
@@ -3807,8 +3816,12 @@ LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str,
38073816
const char *Name);
38083817
LLVMBool LLVMGetVolatile(LLVMValueRef MemoryAccessInst);
38093818
void LLVMSetVolatile(LLVMValueRef MemoryAccessInst, LLVMBool IsVolatile);
3819+
LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst);
3820+
void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool IsWeak);
38103821
LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemoryAccessInst);
38113822
void LLVMSetOrdering(LLVMValueRef MemoryAccessInst, LLVMAtomicOrdering Ordering);
3823+
LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst);
3824+
void LLVMSetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst, LLVMAtomicRMWBinOp BinOp);
38123825

38133826
/* Casts */
38143827
LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val,

‎llvm/lib/IR/Core.cpp

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3527,6 +3527,47 @@ static LLVMAtomicOrdering mapToLLVMOrdering(AtomicOrdering Ordering) {
35273527
llvm_unreachable("Invalid AtomicOrdering value!");
35283528
}
35293529

3530+
static AtomicRMWInst::BinOp mapFromLLVMRMWBinOp(LLVMAtomicRMWBinOp BinOp) {
3531+
switch (BinOp) {
3532+
case LLVMAtomicRMWBinOpXchg: return AtomicRMWInst::Xchg;
3533+
case LLVMAtomicRMWBinOpAdd: return AtomicRMWInst::Add;
3534+
case LLVMAtomicRMWBinOpSub: return AtomicRMWInst::Sub;
3535+
case LLVMAtomicRMWBinOpAnd: return AtomicRMWInst::And;
3536+
case LLVMAtomicRMWBinOpNand: return AtomicRMWInst::Nand;
3537+
case LLVMAtomicRMWBinOpOr: return AtomicRMWInst::Or;
3538+
case LLVMAtomicRMWBinOpXor: return AtomicRMWInst::Xor;
3539+
case LLVMAtomicRMWBinOpMax: return AtomicRMWInst::Max;
3540+
case LLVMAtomicRMWBinOpMin: return AtomicRMWInst::Min;
3541+
case LLVMAtomicRMWBinOpUMax: return AtomicRMWInst::UMax;
3542+
case LLVMAtomicRMWBinOpUMin: return AtomicRMWInst::UMin;
3543+
case LLVMAtomicRMWBinOpFAdd: return AtomicRMWInst::FAdd;
3544+
case LLVMAtomicRMWBinOpFSub: return AtomicRMWInst::FSub;
3545+
}
3546+
3547+
llvm_unreachable("Invalid LLVMAtomicRMWBinOp value!");
3548+
}
3549+
3550+
static LLVMAtomicRMWBinOp mapToLLVMRMWBinOp(AtomicRMWInst::BinOp BinOp) {
3551+
switch (BinOp) {
3552+
case AtomicRMWInst::Xchg: return LLVMAtomicRMWBinOpXchg;
3553+
case AtomicRMWInst::Add: return LLVMAtomicRMWBinOpAdd;
3554+
case AtomicRMWInst::Sub: return LLVMAtomicRMWBinOpSub;
3555+
case AtomicRMWInst::And: return LLVMAtomicRMWBinOpAnd;
3556+
case AtomicRMWInst::Nand: return LLVMAtomicRMWBinOpNand;
3557+
case AtomicRMWInst::Or: return LLVMAtomicRMWBinOpOr;
3558+
case AtomicRMWInst::Xor: return LLVMAtomicRMWBinOpXor;
3559+
case AtomicRMWInst::Max: return LLVMAtomicRMWBinOpMax;
3560+
case AtomicRMWInst::Min: return LLVMAtomicRMWBinOpMin;
3561+
case AtomicRMWInst::UMax: return LLVMAtomicRMWBinOpUMax;
3562+
case AtomicRMWInst::UMin: return LLVMAtomicRMWBinOpUMin;
3563+
case AtomicRMWInst::FAdd: return LLVMAtomicRMWBinOpFAdd;
3564+
case AtomicRMWInst::FSub: return LLVMAtomicRMWBinOpFSub;
3565+
default: break;
3566+
}
3567+
3568+
llvm_unreachable("Invalid AtomicRMWBinOp value!");
3569+
}
3570+
35303571
// TODO: Should this and other atomic instructions support building with
35313572
// "syncscope"?
35323573
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
@@ -3602,23 +3643,41 @@ LLVMBool LLVMGetVolatile(LLVMValueRef MemAccessInst) {
36023643
Value *P = unwrap<Value>(MemAccessInst);
36033644
if (LoadInst *LI = dyn_cast<LoadInst>(P))
36043645
return LI->isVolatile();
3605-
return cast<StoreInst>(P)->isVolatile();
3646+
if (StoreInst *SI = dyn_cast<StoreInst>(P))
3647+
return SI->isVolatile();
3648+
if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(P))
3649+
return AI->isVolatile();
3650+
return cast<AtomicCmpXchgInst>(P)->isVolatile();
36063651
}
36073652

36083653
void LLVMSetVolatile(LLVMValueRef MemAccessInst, LLVMBool isVolatile) {
36093654
Value *P = unwrap<Value>(MemAccessInst);
36103655
if (LoadInst *LI = dyn_cast<LoadInst>(P))
36113656
return LI->setVolatile(isVolatile);
3612-
return cast<StoreInst>(P)->setVolatile(isVolatile);
3657+
if (StoreInst *SI = dyn_cast<StoreInst>(P))
3658+
return SI->setVolatile(isVolatile);
3659+
if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(P))
3660+
return AI->setVolatile(isVolatile);
3661+
return cast<AtomicCmpXchgInst>(P)->setVolatile(isVolatile);
3662+
}
3663+
3664+
LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst) {
3665+
return unwrap<AtomicCmpXchgInst>(CmpXchgInst)->isWeak();
3666+
}
3667+
3668+
void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool isWeak) {
3669+
return unwrap<AtomicCmpXchgInst>(CmpXchgInst)->setWeak(isWeak);
36133670
}
36143671

36153672
LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemAccessInst) {
36163673
Value *P = unwrap<Value>(MemAccessInst);
36173674
AtomicOrdering O;
36183675
if (LoadInst *LI = dyn_cast<LoadInst>(P))
36193676
O = LI->getOrdering();
3677+
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
3678+
O = SI->getOrdering();
36203679
else
3621-
O = cast<StoreInst>(P)->getOrdering();
3680+
O = cast<AtomicRMWInst>(P)->getOrdering();
36223681
return mapToLLVMOrdering(O);
36233682
}
36243683

@@ -3631,6 +3690,14 @@ void LLVMSetOrdering(LLVMValueRef MemAccessInst, LLVMAtomicOrdering Ordering) {
36313690
return cast<StoreInst>(P)->setOrdering(O);
36323691
}
36333692

3693+
LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef Inst) {
3694+
return mapToLLVMRMWBinOp(unwrap<AtomicRMWInst>(Inst)->getOperation());
3695+
}
3696+
3697+
void LLVMSetAtomicRMWBinOp(LLVMValueRef Inst, LLVMAtomicRMWBinOp BinOp) {
3698+
unwrap<AtomicRMWInst>(Inst)->setOperation(mapFromLLVMRMWBinOp(BinOp));
3699+
}
3700+
36343701
/*--.. Casts ...............................................................--*/
36353702

36363703
LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef B, LLVMValueRef Val,
@@ -3849,20 +3916,7 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
38493916
LLVMValueRef PTR, LLVMValueRef Val,
38503917
LLVMAtomicOrdering ordering,
38513918
LLVMBool singleThread) {
3852-
AtomicRMWInst::BinOp intop;
3853-
switch (op) {
3854-
case LLVMAtomicRMWBinOpXchg: intop = AtomicRMWInst::Xchg; break;
3855-
case LLVMAtomicRMWBinOpAdd: intop = AtomicRMWInst::Add; break;
3856-
case LLVMAtomicRMWBinOpSub: intop = AtomicRMWInst::Sub; break;
3857-
case LLVMAtomicRMWBinOpAnd: intop = AtomicRMWInst::And; break;
3858-
case LLVMAtomicRMWBinOpNand: intop = AtomicRMWInst::Nand; break;
3859-
case LLVMAtomicRMWBinOpOr: intop = AtomicRMWInst::Or; break;
3860-
case LLVMAtomicRMWBinOpXor: intop = AtomicRMWInst::Xor; break;
3861-
case LLVMAtomicRMWBinOpMax: intop = AtomicRMWInst::Max; break;
3862-
case LLVMAtomicRMWBinOpMin: intop = AtomicRMWInst::Min; break;
3863-
case LLVMAtomicRMWBinOpUMax: intop = AtomicRMWInst::UMax; break;
3864-
case LLVMAtomicRMWBinOpUMin: intop = AtomicRMWInst::UMin; break;
3865-
}
3919+
AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op);
38663920
return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
38673921
mapFromLLVMOrdering(ordering), singleThread ? SyncScope::SingleThread
38683922
: SyncScope::System));

‎llvm/test/Bindings/llvm-c/echo.ll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,23 @@ done:
138138
ret i32 %p
139139
}
140140

141+
define void @memops(i8* %ptr) {
142+
%a = load i8, i8* %ptr
143+
%b = load volatile i8, i8* %ptr
144+
%c = load i8, i8* %ptr, align 8
145+
%d = load atomic i8, i8* %ptr acquire, align 32
146+
store i8 0, i8* %ptr
147+
store volatile i8 0, i8* %ptr
148+
store i8 0, i8* %ptr, align 8
149+
store atomic i8 0, i8* %ptr release, align 32
150+
%e = atomicrmw add i8* %ptr, i8 0 monotonic
151+
%f = atomicrmw volatile xchg i8* %ptr, i8 0 acq_rel
152+
%g = cmpxchg i8* %ptr, i8 1, i8 2 seq_cst acquire
153+
%h = cmpxchg weak i8* %ptr, i8 1, i8 2 seq_cst acquire
154+
%i = cmpxchg volatile i8* %ptr, i8 1, i8 2 monotonic monotonic
155+
ret void
156+
}
157+
141158
declare void @personalityFn()
142159

143160
define void @exn() personality void ()* @personalityFn {

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,13 +576,17 @@ struct FunCloner {
576576
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
577577
Dst = LLVMBuildLoad(Builder, Ptr, Name);
578578
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
579+
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
580+
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
579581
break;
580582
}
581583
case LLVMStore: {
582584
LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 0));
583585
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 1));
584586
Dst = LLVMBuildStore(Builder, Val, Ptr);
585587
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
588+
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
589+
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
586590
break;
587591
}
588592
case LLVMGetElementPtr: {
@@ -597,6 +601,17 @@ struct FunCloner {
597601
Dst = LLVMBuildGEP(Builder, Ptr, Idx.data(), NumIdx, Name);
598602
break;
599603
}
604+
case LLVMAtomicRMW: {
605+
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
606+
LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 1));
607+
LLVMAtomicRMWBinOp BinOp = LLVMGetAtomicRMWBinOp(Src);
608+
LLVMAtomicOrdering Ord = LLVMGetOrdering(Src);
609+
LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
610+
Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread);
611+
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
612+
LLVMSetValueName2(Dst, Name, NameLen);
613+
break;
614+
}
600615
case LLVMAtomicCmpXchg: {
601616
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
602617
LLVMValueRef Cmp = CloneValue(LLVMGetOperand(Src, 1));
@@ -607,7 +622,11 @@ struct FunCloner {
607622

608623
Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
609624
SingleThread);
610-
} break;
625+
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
626+
LLVMSetWeak(Dst, LLVMGetWeak(Src));
627+
LLVMSetValueName2(Dst, Name, NameLen);
628+
break;
629+
}
611630
case LLVMBitCast: {
612631
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 0));
613632
Dst = LLVMBuildBitCast(Builder, V, CloneType(Src), Name);

0 commit comments

Comments
 (0)