aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorMon P Wang <wangmp@apple.com>2008-05-09 22:40:52 +0000
committerMon P Wang <wangmp@apple.com>2008-05-09 22:40:52 +0000
commitb84407d6ec8a9596a51fae6076f6d6bac66ae057 (patch)
tree3f6a6ef660f223849e38bc254d041a7ca8e0a55e /clang/lib/CodeGen
parent961339bbdb641f423ba192ad1f6662ced39a7b52 (diff)
downloadllvm-b84407d6ec8a9596a51fae6076f6d6bac66ae057.zip
llvm-b84407d6ec8a9596a51fae6076f6d6bac66ae057.tar.gz
llvm-b84407d6ec8a9596a51fae6076f6d6bac66ae057.tar.bz2
Added support to generate some atomic operators (add, sub, and, or etc..)
llvm-svn: 50919
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f320313..1574ae1 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -25,6 +25,17 @@ using namespace clang;
using namespace CodeGen;
using namespace llvm;
+/// Utility to insert an atomic instruction based Instrinsic::ID and
+// the expression node
+static RValue EmitBinaryAtomic(CodeGenFunction& CFG,
+ Intrinsic::ID Id, const CallExpr *E) {
+ const llvm::Type *ResType = CFG.ConvertType(E->getType());
+ Value *AtomF = CFG.CGM.getIntrinsic(Id, &ResType, 1);
+ return RValue::get(CFG.Builder.CreateCall2(AtomF,
+ CFG.EmitScalarExpr(E->getArg(0)),
+ CFG.EmitScalarExpr(E->getArg(1))));
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
switch (BuiltinID) {
default: {
@@ -241,7 +252,35 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
return RValue::get(Builder.CreateAlloca(llvm::Type::Int8Ty,
EmitScalarExpr(E->getArg(0)),
"tmp"));
+ case Builtin::BI__sync_fetch_and_add:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_las, E);
+ case Builtin::BI__sync_fetch_and_sub:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_lss, E);
+ case Builtin::BI__sync_fetch_and_min:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_min, E);
+ case Builtin::BI__sync_fetch_and_max:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_max, E);
+ case Builtin::BI__sync_fetch_and_umin:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umin, E);
+ case Builtin::BI__sync_fetch_and_umax:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umax, E);
+ case Builtin::BI__sync_fetch_and_and:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_and, E);
+ case Builtin::BI__sync_fetch_and_or:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_or, E);
+ case Builtin::BI__sync_fetch_and_xor:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_xor, E);
+ case Builtin::BI__sync_val_compare_and_swap: {
+ Value *Args[3];
+ Args[0]= EmitScalarExpr(E->getArg(0));
+ Args[1] = EmitScalarExpr(E->getArg(1));
+ Args[2] = EmitScalarExpr(E->getArg(2));
+ const llvm::Type *ResType = ConvertType(E->getType());
+ Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_lcs, &ResType, 1);
+ return RValue::get(Builder.CreateCall(AtomF, &Args[0], &Args[1]+2));
}
+ case Builtin::BI__sync_lock_test_and_set:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E); }
return RValue::get(0);
}