IR-change: cmpxchg operations now return { iN, i1 }.

This is a minimal fix for clang. I'll soon add support for generating
weak variants when requested, but that's not really necessary for the
LLVM change in isolation.

llvm-svn: 210907
This commit is contained in:
Tim Northover 2014-06-13 14:24:59 +00:00
parent d7756c5a68
commit b49b04bbe0
6 changed files with 98 additions and 40 deletions

View File

@ -186,13 +186,14 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E,
llvm::LoadInst *Desired = CGF.Builder.CreateLoad(Val2);
Desired->setAlignment(Align);
llvm::AtomicCmpXchgInst *Old = CGF.Builder.CreateAtomicCmpXchg(
llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg(
Ptr, Expected, Desired, SuccessOrder, FailureOrder);
Old->setVolatile(E->isVolatile());
Pair->setVolatile(E->isVolatile());
// Cmp holds the result of the compare-exchange operation: true on success,
// false on failure.
llvm::Value *Cmp = CGF.Builder.CreateICmpEQ(Old, Expected);
llvm::Value *Old = CGF.Builder.CreateExtractValue(Pair, 0);
llvm::Value *Cmp = CGF.Builder.CreateExtractValue(Pair, 1);
// This basic block is used to hold the store instruction if the operation
// failed.

View File

@ -975,6 +975,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Result = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
llvm::SequentiallyConsistent,
llvm::SequentiallyConsistent);
Result = Builder.CreateExtractValue(Result, 0);
Result = EmitFromInt(*this, Result, T, ValueType);
return RValue::get(Result);
}
@ -998,11 +999,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Args[1] = EmitToInt(*this, EmitScalarExpr(E->getArg(1)), T, IntType);
Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType);
Value *OldVal = Args[1];
Value *PrevVal = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
llvm::SequentiallyConsistent,
llvm::SequentiallyConsistent);
Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
Value *Pair = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
llvm::SequentiallyConsistent,
llvm::SequentiallyConsistent);
Value *Result = Builder.CreateExtractValue(Pair, 1);
// zext bool to int.
Result = Builder.CreateZExt(Result, ConvertType(E->getType()));
return RValue::get(Result);
@ -1524,7 +1524,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
SequentiallyConsistent,
SequentiallyConsistent);
CXI->setVolatile(true);
return RValue::get(CXI);
return RValue::get(Builder.CreateExtractValue(CXI, 0));
}
case Builtin::BI_InterlockedIncrement: {
AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(

View File

@ -1732,11 +1732,12 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
llvm::Value *old = Builder.CreateAtomicCmpXchg(
llvm::Value *pair = Builder.CreateAtomicCmpXchg(
LV.getAddress(), atomicPHI, CGF.EmitToMemory(value, type),
llvm::SequentiallyConsistent, llvm::SequentiallyConsistent);
llvm::Value *old = Builder.CreateExtractValue(pair, 0);
llvm::Value *success = Builder.CreateExtractValue(pair, 1);
atomicPHI->addIncoming(old, opBB);
llvm::Value *success = Builder.CreateICmpEQ(old, atomicPHI);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
return isPre ? value : input;
@ -2075,11 +2076,12 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
llvm::Value *old = Builder.CreateAtomicCmpXchg(
llvm::Value *pair = Builder.CreateAtomicCmpXchg(
LHSLV.getAddress(), atomicPHI, CGF.EmitToMemory(Result, LHSTy),
llvm::SequentiallyConsistent, llvm::SequentiallyConsistent);
llvm::Value *old = Builder.CreateExtractValue(pair, 0);
llvm::Value *success = Builder.CreateExtractValue(pair, 1);
atomicPHI->addIncoming(old, opBB);
llvm::Value *success = Builder.CreateICmpEQ(old, atomicPHI);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
return LHSLV;

View File

@ -160,23 +160,70 @@ void test_op_and_fetch (void)
void test_compare_and_swap (void)
{
sc = __sync_val_compare_and_swap (&sc, uc, sc); // CHECK: cmpxchg i8
uc = __sync_val_compare_and_swap (&uc, uc, sc); // CHECK: cmpxchg i8
ss = __sync_val_compare_and_swap (&ss, uc, sc); // CHECK: cmpxchg i16
us = __sync_val_compare_and_swap (&us, uc, sc); // CHECK: cmpxchg i16
si = __sync_val_compare_and_swap (&si, uc, sc); // CHECK: cmpxchg i32
ui = __sync_val_compare_and_swap (&ui, uc, sc); // CHECK: cmpxchg i32
sll = __sync_val_compare_and_swap (&sll, uc, sc); // CHECK: cmpxchg i64
ull = __sync_val_compare_and_swap (&ull, uc, sc); // CHECK: cmpxchg i64
sc = __sync_val_compare_and_swap (&sc, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i8
// CHECK: extractvalue { i8, i1 } [[PAIR]], 0
ui = __sync_bool_compare_and_swap (&sc, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&uc, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&ss, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&us, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&si, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&ui, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&sll, uc, sc); // CHECK: cmpxchg
ui = __sync_bool_compare_and_swap (&ull, uc, sc); // CHECK: cmpxchg
uc = __sync_val_compare_and_swap (&uc, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i8
// CHECK: extractvalue { i8, i1 } [[PAIR]], 0
ss = __sync_val_compare_and_swap (&ss, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i16
// CHECK: extractvalue { i16, i1 } [[PAIR]], 0
us = __sync_val_compare_and_swap (&us, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i16
// CHECK: extractvalue { i16, i1 } [[PAIR]], 0
si = __sync_val_compare_and_swap (&si, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i32
// CHECK: extractvalue { i32, i1 } [[PAIR]], 0
ui = __sync_val_compare_and_swap (&ui, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i32
// CHECK: extractvalue { i32, i1 } [[PAIR]], 0
sll = __sync_val_compare_and_swap (&sll, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i64
// CHECK: extractvalue { i64, i1 } [[PAIR]], 0
ull = __sync_val_compare_and_swap (&ull, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i64
// CHECK: extractvalue { i64, i1 } [[PAIR]], 0
ui = __sync_bool_compare_and_swap (&sc, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i8
// CHECK: extractvalue { i8, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&uc, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i8
// CHECK: extractvalue { i8, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&ss, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i16
// CHECK: extractvalue { i16, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&us, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i16
// CHECK: extractvalue { i16, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&si, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i32
// CHECK: extractvalue { i32, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&ui, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i32
// CHECK: extractvalue { i32, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&sll, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i64
// CHECK: extractvalue { i64, i1 } [[PAIR]], 1
ui = __sync_bool_compare_and_swap (&ull, uc, sc);
// CHECK: [[PAIR:%[a-z0-9._]+]] = cmpxchg i64
// CHECK: extractvalue { i64, i1 } [[PAIR]], 1
}
void test_lock (void)

View File

@ -91,8 +91,9 @@ int fi3d(int *i) {
_Bool fi4(_Atomic(int) *i) {
// CHECK-LABEL: @fi4
// CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
// CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = icmp eq i32 [[OLD]], [[EXPECTED]]
// CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
// CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0
// CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1
// CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]]
// CHECK: store i32 [[OLD]]
int cmp = 0;
@ -101,8 +102,9 @@ _Bool fi4(_Atomic(int) *i) {
_Bool fi4a(int *i) {
// CHECK-LABEL: @fi4
// CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
// CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = icmp eq i32 [[OLD]], [[EXPECTED]]
// CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
// CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0
// CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1
// CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]]
// CHECK: store i32 [[OLD]]
int cmp = 0;
@ -112,8 +114,9 @@ _Bool fi4a(int *i) {
_Bool fi4b(int *i) {
// CHECK-LABEL: @fi4
// CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
// CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = icmp eq i32 [[OLD]], [[EXPECTED]]
// CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]]
// CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0
// CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1
// CHECK: br i1 [[CMP]], label %[[STORE_EXPECTED:[.0-9A-Z_a-z]+]], label %[[CONTINUE:[.0-9A-Z_a-z]+]]
// CHECK: store i32 [[OLD]]
int cmp = 0;

View File

@ -35,10 +35,12 @@ int atomic(void) {
// CHECK: atomicrmw xchg i32* %val, i32 8 seq_cst
old = __sync_val_compare_and_swap(&val, 4, 1976);
// CHECK: cmpxchg i32* %val, i32 4, i32 1976 seq_cst
// CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg i32* %val, i32 4, i32 1976 seq_cst
// CHECK: extractvalue { i32, i1 } [[PAIR]], 0
old = __sync_bool_compare_and_swap(&val, 4, 1976);
// CHECK: cmpxchg i32* %val, i32 4, i32 1976 seq_cst
// CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg i32* %val, i32 4, i32 1976 seq_cst
// CHECK: extractvalue { i32, i1 } [[PAIR]], 1
old = __sync_fetch_and_and(&val, 0x9);
// CHECK: atomicrmw and i32* %val, i32 9 seq_cst
@ -65,10 +67,13 @@ int atomic(void) {
// CHECK: atomicrmw xor i8* %valc, i8 5 seq_cst
__sync_val_compare_and_swap((void **)0, (void *)0, (void *)0);
// CHECK: cmpxchg i32* null, i32 0, i32 0 seq_cst
// CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg i32* null, i32 0, i32 0 seq_cst
// CHECK: extractvalue { i32, i1 } [[PAIR]], 0
if ( __sync_val_compare_and_swap(&valb, 0, 1)) {
// CHECK: cmpxchg i8* %valb, i8 0, i8 1 seq_cst
// CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg i8* %valb, i8 0, i8 1 seq_cst
// CHECK: [[VAL:%[a-z0-9_.]+]] = extractvalue { i8, i1 } [[PAIR]], 0
// CHECK: trunc i8 [[VAL]] to i1
old = 42;
}