1 // RUN: %clang_cc1 -triple x86_64 -emit-llvm %s \ 2 // RUN: -o - | FileCheck -check-prefixes=CHECK,NATIVE %s 3 // RUN: %clang_cc1 -triple riscv32 -target-feature -a -emit-llvm %s \ 4 // RUN: -o - | FileCheck -check-prefixes=CHECK,LIBCALL %s 5 6 void foo(int x) 7 { 8 _Atomic(int) i = 0; 9 _Atomic(short) j = 0; 10 // Check that multiply / divides on atomics produce a cmpxchg loop 11 i *= 2; 12 // NATIVE: mul nsw i32 13 // NATIVE: cmpxchg i32* 14 // LIBCALL: mul nsw i32 15 // LIBCALL: i1 @__atomic_compare_exchange(i32 4, 16 i /= 2; 17 // NATIVE: sdiv i32 18 // NATIVE: cmpxchg i32* 19 // LIBCALL: sdiv i32 20 // LIBCALL: i1 @__atomic_compare_exchange(i32 4, 21 j /= x; 22 // NATIVE: sdiv i32 23 // NATIVE: cmpxchg i16* 24 // LIBCALL: sdiv i32 25 // LIBCALL: i1 @__atomic_compare_exchange(i32 2, 26 27 } 28 29 extern _Atomic _Bool b; 30 31 _Bool bar() { 32 // NATIVE-LABEL: @bar 33 // NATIVE: %[[load:.*]] = load atomic i8, i8* @b seq_cst 34 // NATIVE: %[[tobool:.*]] = trunc i8 %[[load]] to i1 35 // NATIVE: ret i1 %[[tobool]] 36 // LIBCALL-LABEL: @bar 37 // LIBCALL: call void @__atomic_load(i32 1, i8* @b, i8* %atomic-temp, i32 5) 38 // LIBCALL: %[[load:.*]] = load i8, i8* %atomic-temp 39 // LIBCALL: %[[tobool:.*]] = trunc i8 %[[load]] to i1 40 // LIBCALL: ret i1 %[[tobool]] 41 42 return b; 43 } 44 45 extern _Atomic(_Complex int) x; 46 47 void baz(int y) { 48 // NATIVE-LABEL: @baz 49 // NATIVE: store atomic 50 // LIBCALL-LABEL: @baz 51 // LIBCALL: call void @__atomic_store 52 53 x += y; 54 } 55 56 _Atomic(int) compound_add(_Atomic(int) in) { 57 // CHECK-LABEL: @compound_add 58 // CHECK: [[OLD:%.*]] = atomicrmw add i32* {{.*}}, i32 5 seq_cst 59 // CHECK: [[NEW:%.*]] = add i32 [[OLD]], 5 60 // CHECK: ret i32 [[NEW]] 61 62 return (in += 5); 63 } 64 65 _Atomic(int) compound_sub(_Atomic(int) in) { 66 // CHECK-LABEL: @compound_sub 67 // CHECK: [[OLD:%.*]] = atomicrmw sub i32* {{.*}}, i32 5 seq_cst 68 // CHECK: [[NEW:%.*]] = sub i32 [[OLD]], 5 69 // CHECK: ret i32 [[NEW]] 70 71 return (in -= 5); 72 } 73 74 _Atomic(int) compound_xor(_Atomic(int) in) { 75 // CHECK-LABEL: @compound_xor 76 // CHECK: [[OLD:%.*]] = atomicrmw xor i32* {{.*}}, i32 5 seq_cst 77 // CHECK: [[NEW:%.*]] = xor i32 [[OLD]], 5 78 // CHECK: ret i32 [[NEW]] 79 80 return (in ^= 5); 81 } 82 83 _Atomic(int) compound_or(_Atomic(int) in) { 84 // CHECK-LABEL: @compound_or 85 // CHECK: [[OLD:%.*]] = atomicrmw or i32* {{.*}}, i32 5 seq_cst 86 // CHECK: [[NEW:%.*]] = or i32 [[OLD]], 5 87 // CHECK: ret i32 [[NEW]] 88 89 return (in |= 5); 90 } 91 92 _Atomic(int) compound_and(_Atomic(int) in) { 93 // CHECK-LABEL: @compound_and 94 // CHECK: [[OLD:%.*]] = atomicrmw and i32* {{.*}}, i32 5 seq_cst 95 // CHECK: [[NEW:%.*]] = and i32 [[OLD]], 5 96 // CHECK: ret i32 [[NEW]] 97 98 return (in &= 5); 99 } 100 101 _Atomic(int) compound_mul(_Atomic(int) in) { 102 // NATIVE-LABEL: @compound_mul 103 // NATIVE: cmpxchg i32* {{%.*}}, i32 {{%.*}}, i32 [[NEW:%.*]] seq_cst seq_cst 104 // NATIVE: ret i32 [[NEW]] 105 // LIBCALL-LABEL: @compound_mul 106 // LIBCALL: i1 @__atomic_compare_exchange(i32 4, 107 108 return (in *= 5); 109 } 110