Skip to content

Commit 2b67ca6

Browse files
gitoleglanza
authored andcommitted
[CIR][CodeGen] builtins: adds __sync_bool/val_compare_and_swap (#656)
This PR adds support for ` __sync_bool_compare_and_swap` and ` __sync_val_compare_and_swap`.
1 parent f58a3c5 commit 2b67ca6

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,29 @@ static RValue buildBinaryAtomic(CIRGenFunction &CGF,
245245
return RValue::get(makeBinaryAtomicValue(CGF, kind, E));
246246
}
247247

248+
static mlir::Value MakeAtomicCmpXchgValue(CIRGenFunction &cgf,
249+
const CallExpr *expr,
250+
bool returnBool) {
251+
QualType typ = returnBool ? expr->getArg(1)->getType() : expr->getType();
252+
Address destAddr = checkAtomicAlignment(cgf, expr);
253+
auto &builder = cgf.getBuilder();
254+
255+
auto intType = builder.getSIntNTy(cgf.getContext().getTypeSize(typ));
256+
auto cmpVal = cgf.buildScalarExpr(expr->getArg(1));
257+
auto valueType = cmpVal.getType();
258+
cmpVal = buildToInt(cgf, cmpVal, typ, intType);
259+
auto newVal =
260+
buildToInt(cgf, cgf.buildScalarExpr(expr->getArg(2)), typ, intType);
261+
262+
auto op = builder.create<mlir::cir::AtomicCmpXchg>(
263+
cgf.getLoc(expr->getSourceRange()), cmpVal.getType(), builder.getBoolTy(),
264+
destAddr.getPointer(), cmpVal, newVal,
265+
mlir::cir::MemOrder::SequentiallyConsistent,
266+
mlir::cir::MemOrder::SequentiallyConsistent);
267+
268+
return returnBool ? op.getResult(1) : op.getResult(0);
269+
}
270+
248271
RValue CIRGenFunction::buildRotate(const CallExpr *E, bool IsRotateRight) {
249272
auto src = buildScalarExpr(E->getArg(0));
250273
auto shiftAmt = buildScalarExpr(E->getArg(1));
@@ -997,6 +1020,20 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
9971020
return buildBinaryAtomic(*this, mlir::cir::AtomicFetchKind::Add, E);
9981021
}
9991022

1023+
case Builtin::BI__sync_val_compare_and_swap_1:
1024+
case Builtin::BI__sync_val_compare_and_swap_2:
1025+
case Builtin::BI__sync_val_compare_and_swap_4:
1026+
case Builtin::BI__sync_val_compare_and_swap_8:
1027+
case Builtin::BI__sync_val_compare_and_swap_16:
1028+
return RValue::get(MakeAtomicCmpXchgValue(*this, E, false));
1029+
1030+
case Builtin::BI__sync_bool_compare_and_swap_1:
1031+
case Builtin::BI__sync_bool_compare_and_swap_2:
1032+
case Builtin::BI__sync_bool_compare_and_swap_4:
1033+
case Builtin::BI__sync_bool_compare_and_swap_8:
1034+
case Builtin::BI__sync_bool_compare_and_swap_16:
1035+
return RValue::get(MakeAtomicCmpXchgValue(*this, E, true));
1036+
10001037
case Builtin::BI__builtin_add_overflow:
10011038
case Builtin::BI__builtin_sub_overflow:
10021039
case Builtin::BI__builtin_mul_overflow: {

clang/test/CIR/CodeGen/atomic.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,4 +378,96 @@ void inc_short(short* a, short b) {
378378
// LLVM: atomicrmw add ptr {{.*}}, i8 {{.*}} seq_cst, align 1
379379
void inc_byte(char* a, char b) {
380380
char c = __sync_fetch_and_add(a, b);
381+
}
382+
383+
384+
// CHECK-LABEL: @_Z12cmp_bool_int
385+
// CHECK: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
386+
// CHECK: %[[CMP:.*]] = cir.load {{.*}} : !cir.ptr<!s32i>, !s32i
387+
// CHECK: %[[UPD:.*]] = cir.load {{.*}} : !cir.ptr<!s32i>, !s32i
388+
// CHECK: %[[OLD:.*]], %[[RES:.*]] = cir.atomic.cmp_xchg(%[[PTR]] : !cir.ptr<!s32i>, %[[CMP]] : !s32i, %[[UPD]] : !s32i, success = seq_cst, failure = seq_cst) : (!s32i, !cir.bool)
389+
// CHECK: cir.store %[[RES]], {{.*}} : !cir.bool, !cir.ptr<!cir.bool>
390+
391+
// LLVM-LABEL: @_Z12cmp_bool_int
392+
// LLVM: %[[PTR:.*]] = load ptr
393+
// LLVM: %[[CMP:.*]] = load i32
394+
// LLVM: %[[UPD:.*]] = load i32
395+
// LLVM: %[[RES:.*]] = cmpxchg ptr %[[PTR]], i32 %[[CMP]], i32 %[[UPD]] seq_cst seq_cst
396+
// LLVM: %[[TMP:.*]] = extractvalue { i32, i1 } %[[RES]], 1
397+
// LLVM: %[[EXT:.*]] = zext i1 %[[TMP]] to i8
398+
// LLVM: store i8 %[[EXT]], ptr {{.*}}
399+
void cmp_bool_int(int* p, int x, int u) {
400+
bool r = __sync_bool_compare_and_swap(p, x, u);
401+
}
402+
403+
// CHECK-LABEL: @_Z13cmp_bool_long
404+
// CHECK: cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!s64i>, {{.*}} : !s64i, {{.*}} : !s64i, success = seq_cst, failure = seq_cst) : (!s64i, !cir.bool)
405+
406+
// LLVM-LABEL: @_Z13cmp_bool_long
407+
// LLVM: cmpxchg ptr {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst
408+
void cmp_bool_long(long* p, long x, long u) {
409+
bool r = __sync_bool_compare_and_swap(p, x, u);
410+
}
411+
412+
// CHECK-LABEL: @_Z14cmp_bool_short
413+
// CHECK: cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!s16i>, {{.*}} : !s16i, {{.*}} : !s16i, success = seq_cst, failure = seq_cst) : (!s16i, !cir.bool)
414+
415+
// LLVM-LABEL: @_Z14cmp_bool_short
416+
// LLVM: cmpxchg ptr {{.*}}, i16 {{.*}}, i16 {{.*}} seq_cst seq_cst
417+
void cmp_bool_short(short* p, short x, short u) {
418+
bool r = __sync_bool_compare_and_swap(p, x, u);
419+
}
420+
421+
// CHECK-LABEL: @_Z13cmp_bool_byte
422+
// CHECK: cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!s8i>, {{.*}} : !s8i, {{.*}} : !s8i, success = seq_cst, failure = seq_cst) : (!s8i, !cir.bool)
423+
424+
// LLVM-LABEL: @_Z13cmp_bool_byte
425+
// LLVM: cmpxchg ptr {{.*}}, i8 {{.*}}, i8 {{.*}} seq_cst seq_cst
426+
void cmp_bool_byte(char* p, char x, char u) {
427+
bool r = __sync_bool_compare_and_swap(p, x, u);
428+
}
429+
430+
// CHECK-LABEL: @_Z11cmp_val_int
431+
// CHECK: %[[PTR:.*]] = cir.load {{.*}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
432+
// CHECK: %[[CMP:.*]] = cir.load {{.*}} : !cir.ptr<!s32i>, !s32i
433+
// CHECK: %[[UPD:.*]] = cir.load {{.*}} : !cir.ptr<!s32i>, !s32i
434+
// CHECK: %[[OLD:.*]], %[[RES:.*]] = cir.atomic.cmp_xchg(%[[PTR]] : !cir.ptr<!s32i>, %[[CMP]] : !s32i, %[[UPD]] : !s32i, success = seq_cst, failure = seq_cst) : (!s32i, !cir.bool)
435+
// CHECK: cir.store %[[OLD]], {{.*}} : !s32i, !cir.ptr<!s32i>
436+
437+
// LLVM-LABEL: @_Z11cmp_val_int
438+
// LLVM: %[[PTR:.*]] = load ptr
439+
// LLVM: %[[CMP:.*]] = load i32
440+
// LLVM: %[[UPD:.*]] = load i32
441+
// LLVM: %[[RES:.*]] = cmpxchg ptr %[[PTR]], i32 %[[CMP]], i32 %[[UPD]] seq_cst seq_cst
442+
// LLVM: %[[TMP:.*]] = extractvalue { i32, i1 } %[[RES]], 0
443+
// LLVM: store i32 %[[TMP]], ptr {{.*}}
444+
void cmp_val_int(int* p, int x, int u) {
445+
int r = __sync_val_compare_and_swap(p, x, u);
446+
}
447+
448+
// CHECK-LABEL: @_Z12cmp_val_long
449+
// CHECK: cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!s64i>, {{.*}} : !s64i, {{.*}} : !s64i, success = seq_cst, failure = seq_cst) : (!s64i, !cir.bool)
450+
451+
// LLVM-LABEL: @_Z12cmp_val_long
452+
// LLVM: cmpxchg ptr {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst
453+
void cmp_val_long(long* p, long x, long u) {
454+
long r = __sync_val_compare_and_swap(p, x, u);
455+
}
456+
457+
// CHECK-LABEL: @_Z13cmp_val_short
458+
// CHECK: cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!s16i>, {{.*}} : !s16i, {{.*}} : !s16i, success = seq_cst, failure = seq_cst) : (!s16i, !cir.bool)
459+
460+
// LLVM-LABEL: @_Z13cmp_val_short
461+
// LLVM: cmpxchg ptr {{.*}}, i16 {{.*}}, i16 {{.*}} seq_cst seq_cst
462+
void cmp_val_short(short* p, short x, short u) {
463+
short r = __sync_val_compare_and_swap(p, x, u);
464+
}
465+
466+
// CHECK-LABEL: @_Z12cmp_val_byte
467+
// CHECK: cir.atomic.cmp_xchg({{.*}} : !cir.ptr<!s8i>, {{.*}} : !s8i, {{.*}} : !s8i, success = seq_cst, failure = seq_cst) : (!s8i, !cir.bool)
468+
469+
// LLVM-LABEL: @_Z12cmp_val_byte
470+
// LLVM: cmpxchg ptr {{.*}}, i8 {{.*}}, i8 {{.*}} seq_cst seq_cst
471+
void cmp_val_byte(char* p, char x, char u) {
472+
char r = __sync_val_compare_and_swap(p, x, u);
381473
}

0 commit comments

Comments
 (0)