David Chisnall | 72c1dba | 2013-03-03 16:02:42 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-freebsd -std=c11 | FileCheck %s |
| 2 | |
| 3 | // Test that we are generating atomicrmw instructions, rather than |
| 4 | // compare-exchange loops for common atomic ops. This makes a big difference |
| 5 | // on RISC platforms, where the compare-exchange loop becomes a ll/sc pair for |
| 6 | // the load and then another ll/sc in the loop, expanding to about 30 |
| 7 | // instructions when it should be only 4. It has a smaller, but still |
| 8 | // noticeable, impact on platforms like x86 and RISC-V, where there are atomic |
| 9 | // RMW instructions. |
| 10 | // |
| 11 | // We currently emit cmpxchg loops for most operations on _Bools, because |
| 12 | // they're sufficiently rare that it's not worth making sure that the semantics |
| 13 | // are correct. |
| 14 | |
| 15 | typedef int __attribute__((vector_size(16))) vector; |
| 16 | |
| 17 | _Atomic(_Bool) b; |
| 18 | _Atomic(int) i; |
| 19 | _Atomic(long long) l; |
| 20 | _Atomic(short) s; |
| 21 | _Atomic(char*) p; |
| 22 | _Atomic(float) f; |
| 23 | _Atomic(vector) v; |
| 24 | |
| 25 | // CHECK-NOT: cmpxchg |
| 26 | |
| 27 | // CHECK: testinc |
| 28 | void testinc(void) |
| 29 | { |
| 30 | // Special case for suffix bool++, sets to true and returns the old value. |
| 31 | // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst |
| 32 | b++; |
| 33 | // CHECK: atomicrmw add i32* @i, i32 1 seq_cst |
| 34 | i++; |
| 35 | // CHECK: atomicrmw add i64* @l, i64 1 seq_cst |
| 36 | l++; |
| 37 | // CHECK: atomicrmw add i16* @s, i16 1 seq_cst |
| 38 | s++; |
| 39 | // Prefix increment |
| 40 | // Special case for bool: set to true and return true |
| 41 | // CHECK: store atomic i8 1, i8* @b seq_cst, align 1 |
| 42 | ++b; |
| 43 | // Currently, we have no variant of atomicrmw that returns the new value, so |
| 44 | // we have to generate an atomic add, which returns the old value, and then a |
| 45 | // non-atomic add. |
| 46 | // CHECK: atomicrmw add i32* @i, i32 1 seq_cst |
| 47 | // CHECK: add i32 |
| 48 | ++i; |
| 49 | // CHECK: atomicrmw add i64* @l, i64 1 seq_cst |
| 50 | // CHECK: add i64 |
| 51 | ++l; |
| 52 | // CHECK: atomicrmw add i16* @s, i16 1 seq_cst |
| 53 | // CHECK: add i16 |
| 54 | ++s; |
| 55 | } |
| 56 | // CHECK: testdec |
| 57 | void testdec(void) |
| 58 | { |
| 59 | // CHECK: cmpxchg i8* @b |
| 60 | b--; |
| 61 | // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst |
| 62 | i--; |
| 63 | // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst |
| 64 | l--; |
| 65 | // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst |
| 66 | s--; |
| 67 | // CHECK: cmpxchg i8* @b |
| 68 | --b; |
| 69 | // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst |
| 70 | // CHECK: sub i32 |
| 71 | --i; |
| 72 | // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst |
| 73 | // CHECK: sub i64 |
| 74 | --l; |
| 75 | // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst |
| 76 | // CHECK: sub i16 |
| 77 | --s; |
| 78 | } |
| 79 | // CHECK: testaddeq |
| 80 | void testaddeq(void) |
| 81 | { |
| 82 | // CHECK: cmpxchg i8* @b |
| 83 | // CHECK: atomicrmw add i32* @i, i32 42 seq_cst |
| 84 | // CHECK: atomicrmw add i64* @l, i64 42 seq_cst |
| 85 | // CHECK: atomicrmw add i16* @s, i16 42 seq_cst |
| 86 | b += 42; |
| 87 | i += 42; |
| 88 | l += 42; |
| 89 | s += 42; |
| 90 | } |
| 91 | // CHECK: testsubeq |
| 92 | void testsubeq(void) |
| 93 | { |
| 94 | // CHECK: cmpxchg i8* @b |
| 95 | // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst |
| 96 | // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst |
| 97 | // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst |
| 98 | b -= 42; |
| 99 | i -= 42; |
| 100 | l -= 42; |
| 101 | s -= 42; |
| 102 | } |
| 103 | // CHECK: testxoreq |
| 104 | void testxoreq(void) |
| 105 | { |
| 106 | // CHECK: cmpxchg i8* @b |
| 107 | // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst |
| 108 | // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst |
| 109 | // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst |
| 110 | b ^= 42; |
| 111 | i ^= 42; |
| 112 | l ^= 42; |
| 113 | s ^= 42; |
| 114 | } |
| 115 | // CHECK: testoreq |
| 116 | void testoreq(void) |
| 117 | { |
| 118 | // CHECK: cmpxchg i8* @b |
| 119 | // CHECK: atomicrmw or i32* @i, i32 42 seq_cst |
| 120 | // CHECK: atomicrmw or i64* @l, i64 42 seq_cst |
| 121 | // CHECK: atomicrmw or i16* @s, i16 42 seq_cst |
| 122 | b |= 42; |
| 123 | i |= 42; |
| 124 | l |= 42; |
| 125 | s |= 42; |
| 126 | } |
| 127 | // CHECK: testandeq |
| 128 | void testandeq(void) |
| 129 | { |
| 130 | // CHECK: cmpxchg i8* @b |
| 131 | // CHECK: atomicrmw and i32* @i, i32 42 seq_cst |
| 132 | // CHECK: atomicrmw and i64* @l, i64 42 seq_cst |
| 133 | // CHECK: atomicrmw and i16* @s, i16 42 seq_cst |
| 134 | b &= 42; |
| 135 | i &= 42; |
| 136 | l &= 42; |
| 137 | s &= 42; |
| 138 | } |
| 139 | |