
By default the RISC-V target doesn't have the atomics standard extension enabled. The first RUN line in `clang/test/CodeGen/atomic_ops.c` didn't specify a target triple, which meant that on RISC-V Linux hosts it would target RISC-V, but because it used clang cc1 we didn't get the toolchain driver functionality to automatically turn on the extensions implied by the target triple (riscv64-linux includes atomics). This would cause the test to fail on RISC-V hosts. This patch changes the test to have RUN lines for two explicit targets, one with native atomics and one without. To work around FileCheck limitations and more accurately match the output, some tests now have separate prefixes for the two cases. Reviewers: jyknight, eli.friedman, lenary, efriedma Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D74847
110 lines
2.8 KiB
C
110 lines
2.8 KiB
C
// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s \
|
|
// RUN: -o - | FileCheck -check-prefixes=CHECK,NATIVE %s
|
|
// RUN: %clang_cc1 -triple riscv32 -target-feature -a -emit-llvm %s \
|
|
// RUN: -o - | FileCheck -check-prefixes=CHECK,LIBCALL %s
|
|
|
|
void foo(int x)
|
|
{
|
|
_Atomic(int) i = 0;
|
|
_Atomic(short) j = 0;
|
|
// Check that multiply / divides on atomics produce a cmpxchg loop
|
|
i *= 2;
|
|
// NATIVE: mul nsw i32
|
|
// NATIVE: cmpxchg i32*
|
|
// LIBCALL: mul nsw i32
|
|
// LIBCALL: i1 @__atomic_compare_exchange(i32 4,
|
|
i /= 2;
|
|
// NATIVE: sdiv i32
|
|
// NATIVE: cmpxchg i32*
|
|
// LIBCALL: sdiv i32
|
|
// LIBCALL: i1 @__atomic_compare_exchange(i32 4,
|
|
j /= x;
|
|
// NATIVE: sdiv i32
|
|
// NATIVE: cmpxchg i16*
|
|
// LIBCALL: sdiv i32
|
|
// LIBCALL: i1 @__atomic_compare_exchange(i32 2,
|
|
|
|
}
|
|
|
|
extern _Atomic _Bool b;
|
|
|
|
_Bool bar() {
|
|
// NATIVE-LABEL: @bar
|
|
// NATIVE: %[[load:.*]] = load atomic i8, i8* @b seq_cst
|
|
// NATIVE: %[[tobool:.*]] = trunc i8 %[[load]] to i1
|
|
// NATIVE: ret i1 %[[tobool]]
|
|
// LIBCALL-LABEL: @bar
|
|
// LIBCALL: call void @__atomic_load(i32 1, i8* @b, i8* %atomic-temp, i32 5)
|
|
// LIBCALL: %[[load:.*]] = load i8, i8* %atomic-temp
|
|
// LIBCALL: %[[tobool:.*]] = trunc i8 %[[load]] to i1
|
|
// LIBCALL: ret i1 %[[tobool]]
|
|
|
|
return b;
|
|
}
|
|
|
|
extern _Atomic(_Complex int) x;
|
|
|
|
void baz(int y) {
|
|
// NATIVE-LABEL: @baz
|
|
// NATIVE: store atomic
|
|
// LIBCALL-LABEL: @baz
|
|
// LIBCALL: call void @__atomic_store
|
|
|
|
x += y;
|
|
}
|
|
|
|
_Atomic(int) compound_add(_Atomic(int) in) {
|
|
// CHECK-LABEL: @compound_add
|
|
// CHECK: [[OLD:%.*]] = atomicrmw add i32* {{.*}}, i32 5 seq_cst
|
|
// CHECK: [[NEW:%.*]] = add i32 [[OLD]], 5
|
|
// CHECK: ret i32 [[NEW]]
|
|
|
|
return (in += 5);
|
|
}
|
|
|
|
_Atomic(int) compound_sub(_Atomic(int) in) {
|
|
// CHECK-LABEL: @compound_sub
|
|
// CHECK: [[OLD:%.*]] = atomicrmw sub i32* {{.*}}, i32 5 seq_cst
|
|
// CHECK: [[NEW:%.*]] = sub i32 [[OLD]], 5
|
|
// CHECK: ret i32 [[NEW]]
|
|
|
|
return (in -= 5);
|
|
}
|
|
|
|
_Atomic(int) compound_xor(_Atomic(int) in) {
|
|
// CHECK-LABEL: @compound_xor
|
|
// CHECK: [[OLD:%.*]] = atomicrmw xor i32* {{.*}}, i32 5 seq_cst
|
|
// CHECK: [[NEW:%.*]] = xor i32 [[OLD]], 5
|
|
// CHECK: ret i32 [[NEW]]
|
|
|
|
return (in ^= 5);
|
|
}
|
|
|
|
_Atomic(int) compound_or(_Atomic(int) in) {
|
|
// CHECK-LABEL: @compound_or
|
|
// CHECK: [[OLD:%.*]] = atomicrmw or i32* {{.*}}, i32 5 seq_cst
|
|
// CHECK: [[NEW:%.*]] = or i32 [[OLD]], 5
|
|
// CHECK: ret i32 [[NEW]]
|
|
|
|
return (in |= 5);
|
|
}
|
|
|
|
_Atomic(int) compound_and(_Atomic(int) in) {
|
|
// CHECK-LABEL: @compound_and
|
|
// CHECK: [[OLD:%.*]] = atomicrmw and i32* {{.*}}, i32 5 seq_cst
|
|
// CHECK: [[NEW:%.*]] = and i32 [[OLD]], 5
|
|
// CHECK: ret i32 [[NEW]]
|
|
|
|
return (in &= 5);
|
|
}
|
|
|
|
_Atomic(int) compound_mul(_Atomic(int) in) {
|
|
// NATIVE-LABEL: @compound_mul
|
|
// NATIVE: cmpxchg i32* {{%.*}}, i32 {{%.*}}, i32 [[NEW:%.*]] seq_cst seq_cst
|
|
// NATIVE: ret i32 [[NEW]]
|
|
// LIBCALL-LABEL: @compound_mul
|
|
// LIBCALL: i1 @__atomic_compare_exchange(i32 4,
|
|
|
|
return (in *= 5);
|
|
}
|