Clang Project

clang_source_code/test/CodeGen/bittest-intrin.c
1// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=X64
2// RUN: %clang_cc1 -fms-extensions -triple thumbv7-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
3// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc %s -emit-llvm -o - | FileCheck %s --check-prefix=ARM
4
5volatile unsigned char sink = 0;
6void test32(long *base, long idx) {
7  sink = _bittest(base, idx);
8  sink = _bittestandcomplement(base, idx);
9  sink = _bittestandreset(base, idx);
10  sink = _bittestandset(base, idx);
11  sink = _interlockedbittestandreset(base, idx);
12  sink = _interlockedbittestandset(base, idx);
13  sink = _interlockedbittestandset(base, idx);
14}
15
16void test64(__int64 *base, __int64 idx) {
17  sink = _bittest64(base, idx);
18  sink = _bittestandcomplement64(base, idx);
19  sink = _bittestandreset64(base, idx);
20  sink = _bittestandset64(base, idx);
21  sink = _interlockedbittestandreset64(base, idx);
22  sink = _interlockedbittestandset64(base, idx);
23}
24
25#if defined(_M_ARM) || defined(_M_ARM64)
26void test_arm(long *base, long idx) {
27  sink = _interlockedbittestandreset_acq(base, idx);
28  sink = _interlockedbittestandreset_rel(base, idx);
29  sink = _interlockedbittestandreset_nf(base, idx);
30  sink = _interlockedbittestandset_acq(base, idx);
31  sink = _interlockedbittestandset_rel(base, idx);
32  sink = _interlockedbittestandset_nf(base, idx);
33}
34#endif
35
36// X64-LABEL: define dso_local void @test32(i32* %base, i32 %idx)
37// X64: call i8 asm sideeffect "btl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
38// X64: call i8 asm sideeffect "btcl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
39// X64: call i8 asm sideeffect "btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
40// X64: call i8 asm sideeffect "btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
41// X64: call i8 asm sideeffect "lock btrl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
42// X64: call i8 asm sideeffect "lock btsl $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i32* %{{.*}}, i32 {{.*}})
43
44// X64-LABEL: define dso_local void @test64(i64* %base, i64 %idx)
45// X64: call i8 asm sideeffect "btq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
46// X64: call i8 asm sideeffect "btcq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
47// X64: call i8 asm sideeffect "btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
48// X64: call i8 asm sideeffect "btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
49// X64: call i8 asm sideeffect "lock btrq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
50// X64: call i8 asm sideeffect "lock btsq $2, ($1)\0A\09setc ${0:b}", "=r,r,r,~{{.*}}"(i64* %{{.*}}, i64 {{.*}})
51
52// ARM-LABEL: define dso_local {{.*}}void @test32(i32* %base, i32 %idx)
53// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
54// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
55// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
56// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
57// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
58// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
59// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
60// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
61// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
62
63// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
64// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
65// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
66// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
67// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
68// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
69// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
70// ARM: %[[NEWBYTE:[^ ]*]] = xor i8 %[[BYTE]], %[[MASK]]
71// ARM  store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
72// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
73// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
74// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
75
76// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
77// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
78// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
79// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
80// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
81// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
82// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
83// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1
84// ARM: %[[NEWBYTE:[^ ]*]] = and i8 %[[BYTE]], %[[NOTMASK]]
85// ARM  store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
86// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
87// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
88// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
89
90// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
91// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
92// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
93// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
94// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
95// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
96// ARM: %[[BYTE:[^ ]*]] = load i8, i8* %[[BYTEADDR]], align 1
97// ARM: %[[NEWBYTE:[^ ]*]] = or i8 %[[BYTE]], %[[MASK]]
98// ARM  store i8 %[[NEWBYTE]], i8* %[[BYTEADDR]], align 1
99// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
100// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
101// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
102
103// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
104// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
105// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
106// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
107// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
108// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
109// ARM: %[[NOTMASK:[^ ]*]] = xor i8 %[[MASK]], -1
110// ARM: %[[BYTE:[^ ]*]] = atomicrmw and i8* %[[BYTEADDR]], i8 %[[NOTMASK]] seq_cst
111// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
112// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
113// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
114
115// ARM: %[[IDXHI:[^ ]*]] = ashr i32 %{{.*}}, 3
116// ARM: %[[BASE:[^ ]*]] = bitcast i32* %{{.*}} to i8*
117// ARM: %[[BYTEADDR:[^ ]*]] = getelementptr inbounds i8, i8* %[[BASE]], i32 %[[IDXHI]]
118// ARM: %[[IDX8:[^ ]*]] = trunc i32 %{{.*}} to i8
119// ARM: %[[IDXLO:[^ ]*]] = and i8 %[[IDX8]], 7
120// ARM: %[[MASK:[^ ]*]] = shl i8 1, %[[IDXLO]]
121// ARM: %[[BYTE:[^ ]*]] = atomicrmw or i8* %[[BYTEADDR]], i8 %[[MASK]] seq_cst
122// ARM: %[[BYTESHR:[^ ]*]] = lshr i8 %[[BYTE]], %[[IDXLO]]
123// ARM: %[[RES:[^ ]*]] = and i8 %[[BYTESHR]], 1
124// ARM: store volatile i8 %[[RES]], i8* @sink, align 1
125
126
127// Just look for the atomicrmw instructions.
128
129// ARM-LABEL: define dso_local {{.*}}void @test_arm(i32* %base, i32 %idx)
130// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} acquire
131// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} release
132// ARM: atomicrmw and i8* %{{.*}}, i8 {{.*}} monotonic
133// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} acquire
134// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} release
135// ARM: atomicrmw or i8* %{{.*}}, i8 {{.*}} monotonic
136