[cfe-commits] r68482 - in /cfe/trunk: include/clang/AST/Builtins.def lib/CodeGen/CGBuiltin.cpp test/CodeGen/atomic.c

Daniel Dunbar daniel at zuster.org
Mon Apr 6 17:55:52 PDT 2009


Author: ddunbar
Date: Mon Apr  6 19:55:51 2009
New Revision: 68482

URL: http://llvm.org/viewvc/llvm-project?rev=68482&view=rev
Log:
Implement __sync_{add,sub,and,or,xor}_and_fetch and
__sync_bool_compare_and_swap.
 - <rdar://problem/6762223> [sema/irgen] support
   __sync_bool_compare_and_swap and __sync_add_and_fetch

Modified:
    cfe/trunk/include/clang/AST/Builtins.def
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/test/CodeGen/atomic.c

Modified: cfe/trunk/include/clang/AST/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Builtins.def?rev=68482&r1=68481&r2=68482&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Builtins.def (original)
+++ cfe/trunk/include/clang/AST/Builtins.def Mon Apr  6 19:55:51 2009
@@ -176,7 +176,9 @@
 
 BUILTIN(__builtin_alloca, "v*z"   , "n")
 
-// Atomic operators builtin.                                                  
+// Atomic operators builtin.
+
+// FIXME: These should be overloaded for i8, i16, i32, and i64.
 BUILTIN(__sync_fetch_and_add,"ii*i", "n")
 BUILTIN(__sync_fetch_and_sub,"ii*i", "n")
 BUILTIN(__sync_fetch_and_min,"ii*i", "n")
@@ -186,7 +188,17 @@
 BUILTIN(__sync_fetch_and_and,"ii*i", "n")
 BUILTIN(__sync_fetch_and_or,"ii*i", "n")
 BUILTIN(__sync_fetch_and_xor,"ii*i", "n")
+BUILTIN(__sync_add_and_fetch,"ii*i", "n")
+BUILTIN(__sync_sub_and_fetch,"ii*i", "n")
+BUILTIN(__sync_min_and_fetch,"ii*i", "n")
+BUILTIN(__sync_max_and_fetch,"ii*i", "n")
+BUILTIN(__sync_umin_and_fetch,"UiUi*Ui", "n")
+BUILTIN(__sync_umax_and_fetch,"UiUi*Ui", "n")
+BUILTIN(__sync_and_and_fetch,"ii*i", "n")
+BUILTIN(__sync_or_and_fetch,"ii*i", "n")
+BUILTIN(__sync_xor_and_fetch,"ii*i", "n")
 BUILTIN(__sync_lock_test_and_set,"ii*i", "n")
+BUILTIN(__sync_bool_compare_and_swap,"ii*ii", "n")
 BUILTIN(__sync_val_compare_and_swap,"ii*ii", "n")
 
 // LLVM instruction builtin

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=68482&r1=68481&r2=68482&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Apr  6 19:55:51 2009
@@ -23,17 +23,33 @@
 using namespace CodeGen;
 using namespace llvm;
 
-/// Utility to insert an atomic instruction based Instrinsic::ID and
-// the expression node
-static RValue EmitBinaryAtomic(CodeGenFunction& CFG, 
+/// Utility to insert an atomic instruction based on Instrinsic::ID
+/// and the expression node.
+static RValue EmitBinaryAtomic(CodeGenFunction& CGF, 
                                Intrinsic::ID Id, const CallExpr *E) {
   const llvm::Type *ResType[2];
-  ResType[0] = CFG.ConvertType(E->getType());
-  ResType[1] = CFG.ConvertType(E->getArg(0)->getType());
-  Value *AtomF = CFG.CGM.getIntrinsic(Id, ResType, 2);
-  return RValue::get(CFG.Builder.CreateCall2(AtomF,
-                                             CFG.EmitScalarExpr(E->getArg(0)),
-                                             CFG.EmitScalarExpr(E->getArg(1))));
+  ResType[0] = CGF.ConvertType(E->getType());
+  ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
+  Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
+  return RValue::get(CGF.Builder.CreateCall2(AtomF, 
+                                             CGF.EmitScalarExpr(E->getArg(0)), 
+                                             CGF.EmitScalarExpr(E->getArg(1))));
+}
+
+/// Utility to insert an atomic instruction based Instrinsic::ID and
+// the expression node, where the return value is the result of the
+// operation.
+static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, 
+                                   Intrinsic::ID Id, const CallExpr *E,
+                                   Instruction::BinaryOps Op) {
+  const llvm::Type *ResType[2];
+  ResType[0] = CGF.ConvertType(E->getType());
+  ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
+  Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
+  Value *Ptr = CGF.EmitScalarExpr(E->getArg(0));
+  Value *Operand = CGF.EmitScalarExpr(E->getArg(1));
+  Value *Result = CGF.Builder.CreateCall2(AtomF, Ptr, Operand);
+  return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Operand));
 }
 
 RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, 
@@ -295,6 +311,7 @@
     Value *F = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0);
     return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0))));
   }
+
   case Builtin::BI__sync_fetch_and_add:
     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_add, E);
   case Builtin::BI__sync_fetch_and_sub:
@@ -313,6 +330,23 @@
     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_add_and_fetch:
+    return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E, 
+                                llvm::Instruction::Add);
+  case Builtin::BI__sync_sub_and_fetch:
+    return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_sub, E,
+                                llvm::Instruction::Sub);
+  case Builtin::BI__sync_and_and_fetch:
+    return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_and, E,
+                                llvm::Instruction::And);
+  case Builtin::BI__sync_or_and_fetch:
+    return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_or, E,
+                                llvm::Instruction::Or);
+  case Builtin::BI__sync_xor_and_fetch:
+    return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_xor, E,
+                                llvm::Instruction::Xor);
+
   case Builtin::BI__sync_val_compare_and_swap: {
     const llvm::Type *ResType[2];
     ResType[0]= ConvertType(E->getType());
@@ -323,6 +357,22 @@
                                            EmitScalarExpr(E->getArg(1)),
                                            EmitScalarExpr(E->getArg(2))));
   }
+
+  case Builtin::BI__sync_bool_compare_and_swap: {
+    const llvm::Type *ResType[2];
+    ResType[0]= ConvertType(E->getType());
+    ResType[1] = ConvertType(E->getArg(0)->getType());
+    Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
+    Value *OldVal = EmitScalarExpr(E->getArg(1));
+    Value *PrevVal = Builder.CreateCall3(AtomF, 
+                                        EmitScalarExpr(E->getArg(0)),
+                                        OldVal,
+                                        EmitScalarExpr(E->getArg(2)));
+    Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
+    // zext bool to int.
+    return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType())));
+  }
+
   case Builtin::BI__sync_lock_test_and_set:
     return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E);
 

Modified: cfe/trunk/test/CodeGen/atomic.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/atomic.c?rev=68482&r1=68481&r2=68482&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/atomic.c (original)
+++ cfe/trunk/test/CodeGen/atomic.c Mon Apr  6 19:55:51 2009
@@ -1,15 +1,15 @@
 // RUN: clang-cc %s -emit-llvm -o - > %t1 &&
-// RUN: grep @llvm.atomic.load.add.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.sub.i32 %t1 &&
+// RUN: grep @llvm.atomic.load.add.i32 %t1 | count 3 &&
+// RUN: grep @llvm.atomic.load.sub.i32 %t1 | count 3 &&
 // RUN: grep @llvm.atomic.load.min.i32 %t1 &&
 // RUN: grep @llvm.atomic.load.max.i32 %t1 &&
 // RUN: grep @llvm.atomic.load.umin.i32 %t1 &&
 // RUN: grep @llvm.atomic.load.umax.i32 %t1 &&
 // RUN: grep @llvm.atomic.swap.i32 %t1 &&
-// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.and.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.or.i32 %t1 &&
-// RUN: grep @llvm.atomic.load.xor.i32 %t1
+// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 | count 3 &&
+// RUN: grep @llvm.atomic.load.and.i32 %t1 | count 3 &&
+// RUN: grep @llvm.atomic.load.or.i32 %t1 | count 3 &&
+// RUN: grep @llvm.atomic.load.xor.i32 %t1 | count 3
 
 
 int atomic(void)
@@ -28,8 +28,16 @@
   old = __sync_fetch_and_umax(&uval, 6u);
   old = __sync_lock_test_and_set(&val, 7);
   old = __sync_val_compare_and_swap(&val, 4, 1976);
+  old = __sync_bool_compare_and_swap(&val, 4, 1976);
   old = __sync_fetch_and_and(&val, 0x9);
   old = __sync_fetch_and_or(&val, 0xa);
   old = __sync_fetch_and_xor(&val, 0xb);
+
+  old = __sync_add_and_fetch(&val, 1);
+  old = __sync_sub_and_fetch(&val, 2);
+  old = __sync_and_and_fetch(&val, 3);
+  old = __sync_or_and_fetch(&val, 4);
+  old = __sync_xor_and_fetch(&val, 5);
+
   return old;
 }





More information about the cfe-commits mailing list