Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
Improve C API support for atomicrmw and cmpxchg.
Browse files Browse the repository at this point in the history
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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@372938 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
nlewycky committed Sep 26, 2019
1 parent 3a2a144 commit 206c4da
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 22 deletions.
21 changes: 17 additions & 4 deletions include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,13 @@ typedef enum {
LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the
original using an unsigned comparison and return
the old one */
LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the
original using an unsigned comparison and return
the old one */
LLVMAtomicRMWBinOpUMin, /**< Sets the value if it's greater than the
original using an unsigned comparison and return
the old one */
LLVMAtomicRMWBinOpFAdd, /**< Add a floating point value and return the
old one */
LLVMAtomicRMWBinOpFSub /**< Subtract a floating point value and return the
old one */
} LLVMAtomicRMWBinOp;

typedef enum {
Expand Down Expand Up @@ -1571,6 +1575,8 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(ResumeInst) \
macro(CleanupReturnInst) \
macro(CatchReturnInst) \
macro(CatchSwitchInst) \
macro(CallBrInst) \
macro(FuncletPadInst) \
macro(CatchPadInst) \
macro(CleanupPadInst) \
Expand All @@ -1592,7 +1598,10 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(ZExtInst) \
macro(ExtractValueInst) \
macro(LoadInst) \
macro(VAArgInst)
macro(VAArgInst) \
macro(AtomicCmpXchgInst) \
macro(AtomicRMWInst) \
macro(FenceInst)

/**
* @defgroup LLVMCCoreValueGeneral General APIs
Expand Down Expand Up @@ -3807,8 +3816,12 @@ LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str,
const char *Name);
LLVMBool LLVMGetVolatile(LLVMValueRef MemoryAccessInst);
void LLVMSetVolatile(LLVMValueRef MemoryAccessInst, LLVMBool IsVolatile);
LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst);
void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool IsWeak);
LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemoryAccessInst);
void LLVMSetOrdering(LLVMValueRef MemoryAccessInst, LLVMAtomicOrdering Ordering);
LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst);
void LLVMSetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst, LLVMAtomicRMWBinOp BinOp);

/* Casts */
LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val,
Expand Down
88 changes: 71 additions & 17 deletions lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3527,6 +3527,47 @@ static LLVMAtomicOrdering mapToLLVMOrdering(AtomicOrdering Ordering) {
llvm_unreachable("Invalid AtomicOrdering value!");
}

static AtomicRMWInst::BinOp mapFromLLVMRMWBinOp(LLVMAtomicRMWBinOp BinOp) {
switch (BinOp) {
case LLVMAtomicRMWBinOpXchg: return AtomicRMWInst::Xchg;
case LLVMAtomicRMWBinOpAdd: return AtomicRMWInst::Add;
case LLVMAtomicRMWBinOpSub: return AtomicRMWInst::Sub;
case LLVMAtomicRMWBinOpAnd: return AtomicRMWInst::And;
case LLVMAtomicRMWBinOpNand: return AtomicRMWInst::Nand;
case LLVMAtomicRMWBinOpOr: return AtomicRMWInst::Or;
case LLVMAtomicRMWBinOpXor: return AtomicRMWInst::Xor;
case LLVMAtomicRMWBinOpMax: return AtomicRMWInst::Max;
case LLVMAtomicRMWBinOpMin: return AtomicRMWInst::Min;
case LLVMAtomicRMWBinOpUMax: return AtomicRMWInst::UMax;
case LLVMAtomicRMWBinOpUMin: return AtomicRMWInst::UMin;
case LLVMAtomicRMWBinOpFAdd: return AtomicRMWInst::FAdd;
case LLVMAtomicRMWBinOpFSub: return AtomicRMWInst::FSub;
}

llvm_unreachable("Invalid LLVMAtomicRMWBinOp value!");
}

static LLVMAtomicRMWBinOp mapToLLVMRMWBinOp(AtomicRMWInst::BinOp BinOp) {
switch (BinOp) {
case AtomicRMWInst::Xchg: return LLVMAtomicRMWBinOpXchg;
case AtomicRMWInst::Add: return LLVMAtomicRMWBinOpAdd;
case AtomicRMWInst::Sub: return LLVMAtomicRMWBinOpSub;
case AtomicRMWInst::And: return LLVMAtomicRMWBinOpAnd;
case AtomicRMWInst::Nand: return LLVMAtomicRMWBinOpNand;
case AtomicRMWInst::Or: return LLVMAtomicRMWBinOpOr;
case AtomicRMWInst::Xor: return LLVMAtomicRMWBinOpXor;
case AtomicRMWInst::Max: return LLVMAtomicRMWBinOpMax;
case AtomicRMWInst::Min: return LLVMAtomicRMWBinOpMin;
case AtomicRMWInst::UMax: return LLVMAtomicRMWBinOpUMax;
case AtomicRMWInst::UMin: return LLVMAtomicRMWBinOpUMin;
case AtomicRMWInst::FAdd: return LLVMAtomicRMWBinOpFAdd;
case AtomicRMWInst::FSub: return LLVMAtomicRMWBinOpFSub;
default: break;
}

llvm_unreachable("Invalid AtomicRMWBinOp value!");
}

// TODO: Should this and other atomic instructions support building with
// "syncscope"?
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
Expand Down Expand Up @@ -3602,23 +3643,41 @@ LLVMBool LLVMGetVolatile(LLVMValueRef MemAccessInst) {
Value *P = unwrap<Value>(MemAccessInst);
if (LoadInst *LI = dyn_cast<LoadInst>(P))
return LI->isVolatile();
return cast<StoreInst>(P)->isVolatile();
if (StoreInst *SI = dyn_cast<StoreInst>(P))
return SI->isVolatile();
if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(P))
return AI->isVolatile();
return cast<AtomicCmpXchgInst>(P)->isVolatile();
}

void LLVMSetVolatile(LLVMValueRef MemAccessInst, LLVMBool isVolatile) {
Value *P = unwrap<Value>(MemAccessInst);
if (LoadInst *LI = dyn_cast<LoadInst>(P))
return LI->setVolatile(isVolatile);
return cast<StoreInst>(P)->setVolatile(isVolatile);
if (StoreInst *SI = dyn_cast<StoreInst>(P))
return SI->setVolatile(isVolatile);
if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(P))
return AI->setVolatile(isVolatile);
return cast<AtomicCmpXchgInst>(P)->setVolatile(isVolatile);
}

LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst) {
return unwrap<AtomicCmpXchgInst>(CmpXchgInst)->isWeak();
}

void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool isWeak) {
return unwrap<AtomicCmpXchgInst>(CmpXchgInst)->setWeak(isWeak);
}

LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemAccessInst) {
Value *P = unwrap<Value>(MemAccessInst);
AtomicOrdering O;
if (LoadInst *LI = dyn_cast<LoadInst>(P))
O = LI->getOrdering();
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
O = SI->getOrdering();
else
O = cast<StoreInst>(P)->getOrdering();
O = cast<AtomicRMWInst>(P)->getOrdering();
return mapToLLVMOrdering(O);
}

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

LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef Inst) {
return mapToLLVMRMWBinOp(unwrap<AtomicRMWInst>(Inst)->getOperation());
}

void LLVMSetAtomicRMWBinOp(LLVMValueRef Inst, LLVMAtomicRMWBinOp BinOp) {
unwrap<AtomicRMWInst>(Inst)->setOperation(mapFromLLVMRMWBinOp(BinOp));
}

/*--.. Casts ...............................................................--*/

LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef B, LLVMValueRef Val,
Expand Down Expand Up @@ -3849,20 +3916,7 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
LLVMValueRef PTR, LLVMValueRef Val,
LLVMAtomicOrdering ordering,
LLVMBool singleThread) {
AtomicRMWInst::BinOp intop;
switch (op) {
case LLVMAtomicRMWBinOpXchg: intop = AtomicRMWInst::Xchg; break;
case LLVMAtomicRMWBinOpAdd: intop = AtomicRMWInst::Add; break;
case LLVMAtomicRMWBinOpSub: intop = AtomicRMWInst::Sub; break;
case LLVMAtomicRMWBinOpAnd: intop = AtomicRMWInst::And; break;
case LLVMAtomicRMWBinOpNand: intop = AtomicRMWInst::Nand; break;
case LLVMAtomicRMWBinOpOr: intop = AtomicRMWInst::Or; break;
case LLVMAtomicRMWBinOpXor: intop = AtomicRMWInst::Xor; break;
case LLVMAtomicRMWBinOpMax: intop = AtomicRMWInst::Max; break;
case LLVMAtomicRMWBinOpMin: intop = AtomicRMWInst::Min; break;
case LLVMAtomicRMWBinOpUMax: intop = AtomicRMWInst::UMax; break;
case LLVMAtomicRMWBinOpUMin: intop = AtomicRMWInst::UMin; break;
}
AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op);
return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
mapFromLLVMOrdering(ordering), singleThread ? SyncScope::SingleThread
: SyncScope::System));
Expand Down
17 changes: 17 additions & 0 deletions test/Bindings/llvm-c/echo.ll
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,23 @@ done:
ret i32 %p
}

define void @memops(i8* %ptr) {
%a = load i8, i8* %ptr
%b = load volatile i8, i8* %ptr
%c = load i8, i8* %ptr, align 8
%d = load atomic i8, i8* %ptr acquire, align 32
store i8 0, i8* %ptr
store volatile i8 0, i8* %ptr
store i8 0, i8* %ptr, align 8
store atomic i8 0, i8* %ptr release, align 32
%e = atomicrmw add i8* %ptr, i8 0 monotonic
%f = atomicrmw volatile xchg i8* %ptr, i8 0 acq_rel
%g = cmpxchg i8* %ptr, i8 1, i8 2 seq_cst acquire
%h = cmpxchg weak i8* %ptr, i8 1, i8 2 seq_cst acquire
%i = cmpxchg volatile i8* %ptr, i8 1, i8 2 monotonic monotonic
ret void
}

declare void @personalityFn()

define void @exn() personality void ()* @personalityFn {
Expand Down
21 changes: 20 additions & 1 deletion tools/llvm-c-test/echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,17 @@ struct FunCloner {
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
Dst = LLVMBuildLoad(Builder, Ptr, Name);
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
break;
}
case LLVMStore: {
LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 1));
Dst = LLVMBuildStore(Builder, Val, Ptr);
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
break;
}
case LLVMGetElementPtr: {
Expand All @@ -597,6 +601,17 @@ struct FunCloner {
Dst = LLVMBuildGEP(Builder, Ptr, Idx.data(), NumIdx, Name);
break;
}
case LLVMAtomicRMW: {
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 1));
LLVMAtomicRMWBinOp BinOp = LLVMGetAtomicRMWBinOp(Src);
LLVMAtomicOrdering Ord = LLVMGetOrdering(Src);
LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread);
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
LLVMSetValueName2(Dst, Name, NameLen);
break;
}
case LLVMAtomicCmpXchg: {
LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0));
LLVMValueRef Cmp = CloneValue(LLVMGetOperand(Src, 1));
Expand All @@ -607,7 +622,11 @@ struct FunCloner {

Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
SingleThread);
} break;
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
LLVMSetWeak(Dst, LLVMGetWeak(Src));
LLVMSetValueName2(Dst, Name, NameLen);
break;
}
case LLVMBitCast: {
LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 0));
Dst = LLVMBuildBitCast(Builder, V, CloneType(Src), Name);
Expand Down

0 comments on commit 206c4da

Please sign in to comment.