BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "tn")
BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "tn")
+BUILTIN(__sync_fetch_and_nand, "v.", "t")
+BUILTIN(__sync_fetch_and_nand_1, "ccD*c.", "tn")
+BUILTIN(__sync_fetch_and_nand_2, "ssD*s.", "tn")
+BUILTIN(__sync_fetch_and_nand_4, "iiD*i.", "tn")
+BUILTIN(__sync_fetch_and_nand_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLiD*LLLi.", "tn")
BUILTIN(__sync_add_and_fetch, "v.", "t")
BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "tn")
BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "tn")
BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+BUILTIN(__sync_nand_and_fetch, "v.", "t")
+BUILTIN(__sync_nand_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_nand_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_nand_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_nand_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
BUILTIN(__sync_bool_compare_and_swap, "v.", "t")
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "tn")
BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "tn")
"attribute %0 is already applied with different parameters">,
InGroup<IgnoredAttributes>;
+def warn_sync_fetch_and_nand_semantics_change : Warning<
+ "the semantics of this intrinsic changed with GCC "
+ "version 4.4 - the newer semantics are provided here">,
+ InGroup<DiagGroup<"sync-fetch-and-nand-semantics-changed">>;
+
// Type
def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
def warn_receiver_forward_class : Warning<
static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
llvm::AtomicRMWInst::BinOp Kind,
const CallExpr *E,
- Instruction::BinaryOps Op) {
+ Instruction::BinaryOps Op,
+ bool Invert = false) {
QualType T = E->getType();
assert(E->getArg(0)->getType()->isPointerType());
assert(CGF.getContext().hasSameUnqualifiedType(T,
CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1],
llvm::SequentiallyConsistent);
Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]);
+ if (Invert)
+ Result = CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result,
+ llvm::ConstantInt::get(IntType, -1));
Result = EmitFromInt(CGF, Result, T, ValueType);
return RValue::get(Result);
}
case Builtin::BI__sync_fetch_and_or:
case Builtin::BI__sync_fetch_and_and:
case Builtin::BI__sync_fetch_and_xor:
+ case Builtin::BI__sync_fetch_and_nand:
case Builtin::BI__sync_add_and_fetch:
case Builtin::BI__sync_sub_and_fetch:
case Builtin::BI__sync_and_and_fetch:
case Builtin::BI__sync_or_and_fetch:
case Builtin::BI__sync_xor_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch:
case Builtin::BI__sync_val_compare_and_swap:
case Builtin::BI__sync_bool_compare_and_swap:
case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_fetch_and_xor_8:
case Builtin::BI__sync_fetch_and_xor_16:
return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xor, E);
+ case Builtin::BI__sync_fetch_and_nand_1:
+ case Builtin::BI__sync_fetch_and_nand_2:
+ case Builtin::BI__sync_fetch_and_nand_4:
+ case Builtin::BI__sync_fetch_and_nand_8:
+ case Builtin::BI__sync_fetch_and_nand_16:
+ return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Nand, E);
// Clang extensions: not overloaded yet.
case Builtin::BI__sync_fetch_and_min:
case Builtin::BI__sync_xor_and_fetch_16:
return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Xor, E,
llvm::Instruction::Xor);
+ case Builtin::BI__sync_nand_and_fetch_1:
+ case Builtin::BI__sync_nand_and_fetch_2:
+ case Builtin::BI__sync_nand_and_fetch_4:
+ case Builtin::BI__sync_nand_and_fetch_8:
+ case Builtin::BI__sync_nand_and_fetch_16:
+ return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Nand, E,
+ llvm::Instruction::And, true);
case Builtin::BI__sync_val_compare_and_swap_1:
case Builtin::BI__sync_val_compare_and_swap_2:
case Builtin::BI__sync_fetch_and_xor_4:
case Builtin::BI__sync_fetch_and_xor_8:
case Builtin::BI__sync_fetch_and_xor_16:
+ case Builtin::BI__sync_fetch_and_nand:
+ case Builtin::BI__sync_fetch_and_nand_1:
+ case Builtin::BI__sync_fetch_and_nand_2:
+ case Builtin::BI__sync_fetch_and_nand_4:
+ case Builtin::BI__sync_fetch_and_nand_8:
+ case Builtin::BI__sync_fetch_and_nand_16:
case Builtin::BI__sync_add_and_fetch:
case Builtin::BI__sync_add_and_fetch_1:
case Builtin::BI__sync_add_and_fetch_2:
case Builtin::BI__sync_xor_and_fetch_4:
case Builtin::BI__sync_xor_and_fetch_8:
case Builtin::BI__sync_xor_and_fetch_16:
+ case Builtin::BI__sync_nand_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch_1:
+ case Builtin::BI__sync_nand_and_fetch_2:
+ case Builtin::BI__sync_nand_and_fetch_4:
+ case Builtin::BI__sync_nand_and_fetch_8:
+ case Builtin::BI__sync_nand_and_fetch_16:
case Builtin::BI__sync_val_compare_and_swap:
case Builtin::BI__sync_val_compare_and_swap_1:
case Builtin::BI__sync_val_compare_and_swap_2:
BUILTIN_ROW(__sync_fetch_and_or),
BUILTIN_ROW(__sync_fetch_and_and),
BUILTIN_ROW(__sync_fetch_and_xor),
+ BUILTIN_ROW(__sync_fetch_and_nand),
BUILTIN_ROW(__sync_add_and_fetch),
BUILTIN_ROW(__sync_sub_and_fetch),
BUILTIN_ROW(__sync_and_and_fetch),
BUILTIN_ROW(__sync_or_and_fetch),
BUILTIN_ROW(__sync_xor_and_fetch),
+ BUILTIN_ROW(__sync_nand_and_fetch),
BUILTIN_ROW(__sync_val_compare_and_swap),
BUILTIN_ROW(__sync_bool_compare_and_swap),
// as the number of fixed args.
unsigned BuiltinID = FDecl->getBuiltinID();
unsigned BuiltinIndex, NumFixed = 1;
+ bool WarnAboutSemanticsChange = false;
switch (BuiltinID) {
default: llvm_unreachable("Unknown overloaded atomic builtin!");
case Builtin::BI__sync_fetch_and_add:
BuiltinIndex = 4;
break;
+ case Builtin::BI__sync_fetch_and_nand:
+ case Builtin::BI__sync_fetch_and_nand_1:
+ case Builtin::BI__sync_fetch_and_nand_2:
+ case Builtin::BI__sync_fetch_and_nand_4:
+ case Builtin::BI__sync_fetch_and_nand_8:
+ case Builtin::BI__sync_fetch_and_nand_16:
+ BuiltinIndex = 5;
+ WarnAboutSemanticsChange = true;
+ break;
+
case Builtin::BI__sync_add_and_fetch:
case Builtin::BI__sync_add_and_fetch_1:
case Builtin::BI__sync_add_and_fetch_2:
case Builtin::BI__sync_add_and_fetch_4:
case Builtin::BI__sync_add_and_fetch_8:
case Builtin::BI__sync_add_and_fetch_16:
- BuiltinIndex = 5;
+ BuiltinIndex = 6;
break;
case Builtin::BI__sync_sub_and_fetch:
case Builtin::BI__sync_sub_and_fetch_4:
case Builtin::BI__sync_sub_and_fetch_8:
case Builtin::BI__sync_sub_and_fetch_16:
- BuiltinIndex = 6;
+ BuiltinIndex = 7;
break;
case Builtin::BI__sync_and_and_fetch:
case Builtin::BI__sync_and_and_fetch_4:
case Builtin::BI__sync_and_and_fetch_8:
case Builtin::BI__sync_and_and_fetch_16:
- BuiltinIndex = 7;
+ BuiltinIndex = 8;
break;
case Builtin::BI__sync_or_and_fetch:
case Builtin::BI__sync_or_and_fetch_4:
case Builtin::BI__sync_or_and_fetch_8:
case Builtin::BI__sync_or_and_fetch_16:
- BuiltinIndex = 8;
+ BuiltinIndex = 9;
break;
case Builtin::BI__sync_xor_and_fetch:
case Builtin::BI__sync_xor_and_fetch_4:
case Builtin::BI__sync_xor_and_fetch_8:
case Builtin::BI__sync_xor_and_fetch_16:
- BuiltinIndex = 9;
+ BuiltinIndex = 10;
+ break;
+
+ case Builtin::BI__sync_nand_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch_1:
+ case Builtin::BI__sync_nand_and_fetch_2:
+ case Builtin::BI__sync_nand_and_fetch_4:
+ case Builtin::BI__sync_nand_and_fetch_8:
+ case Builtin::BI__sync_nand_and_fetch_16:
+ BuiltinIndex = 11;
+ WarnAboutSemanticsChange = true;
break;
case Builtin::BI__sync_val_compare_and_swap:
case Builtin::BI__sync_val_compare_and_swap_4:
case Builtin::BI__sync_val_compare_and_swap_8:
case Builtin::BI__sync_val_compare_and_swap_16:
- BuiltinIndex = 10;
+ BuiltinIndex = 12;
NumFixed = 2;
break;
case Builtin::BI__sync_bool_compare_and_swap_4:
case Builtin::BI__sync_bool_compare_and_swap_8:
case Builtin::BI__sync_bool_compare_and_swap_16:
- BuiltinIndex = 11;
+ BuiltinIndex = 13;
NumFixed = 2;
ResultType = Context.BoolTy;
break;
case Builtin::BI__sync_lock_test_and_set_4:
case Builtin::BI__sync_lock_test_and_set_8:
case Builtin::BI__sync_lock_test_and_set_16:
- BuiltinIndex = 12;
+ BuiltinIndex = 14;
break;
case Builtin::BI__sync_lock_release:
case Builtin::BI__sync_lock_release_4:
case Builtin::BI__sync_lock_release_8:
case Builtin::BI__sync_lock_release_16:
- BuiltinIndex = 13;
+ BuiltinIndex = 15;
NumFixed = 0;
ResultType = Context.VoidTy;
break;
case Builtin::BI__sync_swap_4:
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
- BuiltinIndex = 14;
+ BuiltinIndex = 16;
break;
}
return ExprError();
}
+ if (WarnAboutSemanticsChange) {
+ Diag(TheCall->getLocEnd(), diag::warn_sync_fetch_and_nand_semantics_change)
+ << TheCall->getCallee()->getSourceRange();
+ }
+
// Get the decl for the concrete builtin from this, we can tell what the
// concrete integer type we should convert to is.
unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
(void) __sync_fetch_and_xor (&sll, 1); // CHECK: atomicrmw xor i64
(void) __sync_fetch_and_xor (&ull, 1); // CHECK: atomicrmw xor i64
+ (void) __sync_fetch_and_nand (&sc, 1); // CHECK: atomicrmw nand i8
+ (void) __sync_fetch_and_nand (&uc, 1); // CHECK: atomicrmw nand i8
+ (void) __sync_fetch_and_nand (&ss, 1); // CHECK: atomicrmw nand i16
+ (void) __sync_fetch_and_nand (&us, 1); // CHECK: atomicrmw nand i16
+ (void) __sync_fetch_and_nand (&si, 1); // CHECK: atomicrmw nand i32
+ (void) __sync_fetch_and_nand (&ui, 1); // CHECK: atomicrmw nand i32
+ (void) __sync_fetch_and_nand (&sll, 1); // CHECK: atomicrmw nand i64
+ (void) __sync_fetch_and_nand (&ull, 1); // CHECK: atomicrmw nand i64
+
(void) __sync_fetch_and_and (&sc, 1); // CHECK: atomicrmw and i8
(void) __sync_fetch_and_and (&uc, 1); // CHECK: atomicrmw and i8
(void) __sync_fetch_and_and (&ss, 1); // CHECK: atomicrmw and i16
sll = __sync_fetch_and_xor (&sll, 11); // CHECK: atomicrmw xor
ull = __sync_fetch_and_xor (&ull, 11); // CHECK: atomicrmw xor
+ sc = __sync_fetch_and_nand (&sc, 11); // CHECK: atomicrmw nand
+ uc = __sync_fetch_and_nand (&uc, 11); // CHECK: atomicrmw nand
+ ss = __sync_fetch_and_nand (&ss, 11); // CHECK: atomicrmw nand
+ us = __sync_fetch_and_nand (&us, 11); // CHECK: atomicrmw nand
+ si = __sync_fetch_and_nand (&si, 11); // CHECK: atomicrmw nand
+ ui = __sync_fetch_and_nand (&ui, 11); // CHECK: atomicrmw nand
+ sll = __sync_fetch_and_nand (&sll, 11); // CHECK: atomicrmw nand
+ ull = __sync_fetch_and_nand (&ull, 11); // CHECK: atomicrmw nand
+
sc = __sync_fetch_and_and (&sc, 11); // CHECK: atomicrmw and
uc = __sync_fetch_and_and (&uc, 11); // CHECK: atomicrmw and
ss = __sync_fetch_and_and (&ss, 11); // CHECK: atomicrmw and
sll = __sync_xor_and_fetch (&sll, uc); // CHECK: atomicrmw xor
ull = __sync_xor_and_fetch (&ull, uc); // CHECK: atomicrmw xor
+ sc = __sync_nand_and_fetch (&sc, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ uc = __sync_nand_and_fetch (&uc, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ ss = __sync_nand_and_fetch (&ss, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ us = __sync_nand_and_fetch (&us, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ si = __sync_nand_and_fetch (&si, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ ui = __sync_nand_and_fetch (&ui, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ sll = __sync_nand_and_fetch (&sll, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+ ull = __sync_nand_and_fetch (&ull, uc); // CHECK: atomicrmw nand
+ // CHECK: and
+ // CHECK: xor
+
sc = __sync_and_and_fetch (&sc, uc); // CHECK: atomicrmw and
uc = __sync_and_and_fetch (&uc, uc); // CHECK: atomicrmw and
ss = __sync_and_and_fetch (&ss, uc); // CHECK: atomicrmw and
old = __sync_fetch_and_xor(&val, 0xb);
// CHECK: atomicrmw xor i32* %val, i32 11 seq_cst
-
+
+ old = __sync_fetch_and_nand(&val, 0xc);
+ // CHECK: atomicrmw nand i32* %val, i32 12 seq_cst
+
old = __sync_add_and_fetch(&val, 1);
// CHECK: atomicrmw add i32* %val, i32 1 seq_cst
old = __sync_xor_and_fetch(&valc, 5);
// CHECK: atomicrmw xor i8* %valc, i8 5 seq_cst
-
+
+ old = __sync_nand_and_fetch(&valc, 6);
+ // CHECK: atomicrmw nand i8* %valc, i8 6 seq_cst
+
__sync_val_compare_and_swap((void **)0, (void *)0, (void *)0);
// CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg i32* null, i32 0, i32 0 seq_cst
// CHECK: extractvalue { i32, i1 } [[PAIR]], 0
__sync_fetch_and_add_4(ptr, val);
}
+void test9_4(volatile int* ptr, int val) {
+ // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_fetch_and_nand(ptr, val);
+}
+
// rdar://7236819
void test10(void) __attribute__((noreturn));