1 // RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ 2 // RUN: -triple i686--windows -Oz -emit-llvm %s -o - \ 3 // RUN: | FileCheck %s -check-prefixes CHECK,CHECK-I386,CHECK-INTEL 4 // RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ 5 // RUN: -triple thumbv7--windows -Oz -emit-llvm %s -o - \ 6 // RUN: | FileCheck %s --check-prefixes CHECK,CHECK-ARM,CHECK-ARM-X64 7 // RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ 8 // RUN: -triple x86_64--windows -Oz -emit-llvm -target-feature +cx16 %s -o - \ 9 // RUN: | FileCheck %s --check-prefixes CHECK,CHECK-X64,CHECK-ARM-X64,CHECK-INTEL 10 11 // intrin.h needs size_t, but -ffreestanding prevents us from getting it from 12 // stddef.h. Work around it with this typedef. 13 typedef __SIZE_TYPE__ size_t; 14 15 #include <intrin.h> 16 17 #if defined(__i386__) || defined(__x86_64__) 18 void test__stosb(unsigned char *Dest, unsigned char Data, size_t Count) { 19 return __stosb(Dest, Data, Count); 20 } 21 22 // CHECK-I386: define{{.*}}void @test__stosb 23 // CHECK-I386: tail call void @llvm.memset.p0i8.i32(i8* align 1 %Dest, i8 %Data, i32 %Count, i1 true) 24 // CHECK-I386: ret void 25 // CHECK-I386: } 26 27 // CHECK-X64: define{{.*}}void @test__stosb 28 // CHECK-X64: tail call void @llvm.memset.p0i8.i64(i8* align 1 %Dest, i8 %Data, i64 %Count, i1 true) 29 // CHECK-X64: ret void 30 // CHECK-X64: } 31 32 void test__ud2(void) { 33 __ud2(); 34 } 35 // CHECK-INTEL-LABEL: define{{.*}} void @test__ud2() 36 // CHECK-INTEL: call void @llvm.trap() 37 38 void test__int2c(void) { 39 __int2c(); 40 } 41 // CHECK-INTEL-LABEL: define{{.*}} void @test__int2c() 42 // CHECK-INTEL: call void asm sideeffect "int $$0x2c", ""() #[[NORETURN:[0-9]+]] 43 44 45 #endif 46 47 void *test_ReturnAddress() { 48 return _ReturnAddress(); 49 } 50 // CHECK-LABEL: define{{.*}}i8* @test_ReturnAddress() 51 // CHECK: = tail call i8* @llvm.returnaddress(i32 0) 52 // CHECK: ret i8* 53 54 #if defined(__i386__) || defined(__x86_64__) 55 void *test_AddressOfReturnAddress() { 56 return _AddressOfReturnAddress(); 57 } 58 // CHECK-INTEL-LABEL: define dso_local i8* @test_AddressOfReturnAddress() 59 // CHECK-INTEL: = tail call i8* @llvm.addressofreturnaddress() 60 // CHECK-INTEL: ret i8* 61 #endif 62 63 unsigned char test_BitScanForward(unsigned long *Index, unsigned long Mask) { 64 return _BitScanForward(Index, Mask); 65 } 66 // CHECK: define{{.*}}i8 @test_BitScanForward(i32* {{[a-z_ ]*}}%Index, i32 {{[a-z_ ]*}}%Mask){{.*}}{ 67 // CHECK: [[ISNOTZERO:%[a-z0-9._]+]] = icmp eq i32 %Mask, 0 68 // CHECK: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]] 69 // CHECK: [[END_LABEL]]: 70 // CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ] 71 // CHECK: ret i8 [[RESULT]] 72 // CHECK: [[ISNOTZERO_LABEL]]: 73 // CHECK: [[INDEX:%[0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %Mask, i1 true) 74 // CHECK: store i32 [[INDEX]], i32* %Index, align 4 75 // CHECK: br label %[[END_LABEL]] 76 77 unsigned char test_BitScanReverse(unsigned long *Index, unsigned long Mask) { 78 return _BitScanReverse(Index, Mask); 79 } 80 // CHECK: define{{.*}}i8 @test_BitScanReverse(i32* {{[a-z_ ]*}}%Index, i32 {{[a-z_ ]*}}%Mask){{.*}}{ 81 // CHECK: [[ISNOTZERO:%[0-9]+]] = icmp eq i32 %Mask, 0 82 // CHECK: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]] 83 // CHECK: [[END_LABEL]]: 84 // CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ] 85 // CHECK: ret i8 [[RESULT]] 86 // CHECK: [[ISNOTZERO_LABEL]]: 87 // CHECK: [[REVINDEX:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %Mask, i1 true) 88 // CHECK: [[INDEX:%[0-9]+]] = xor i32 [[REVINDEX]], 31 89 // CHECK: store i32 [[INDEX]], i32* %Index, align 4 90 // CHECK: br label %[[END_LABEL]] 91 92 #if defined(__x86_64__) || defined(__arm__) 93 unsigned char test_BitScanForward64(unsigned long *Index, unsigned __int64 Mask) { 94 return _BitScanForward64(Index, Mask); 95 } 96 // CHECK-ARM-X64: define{{.*}}i8 @test_BitScanForward64(i32* {{[a-z_ ]*}}%Index, i64 {{[a-z_ ]*}}%Mask){{.*}}{ 97 // CHECK-ARM-X64: [[ISNOTZERO:%[a-z0-9._]+]] = icmp eq i64 %Mask, 0 98 // CHECK-ARM-X64: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]] 99 // CHECK-ARM-X64: [[END_LABEL]]: 100 // CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ] 101 // CHECK-ARM-X64: ret i8 [[RESULT]] 102 // CHECK-ARM-X64: [[ISNOTZERO_LABEL]]: 103 // CHECK-ARM-X64: [[INDEX:%[0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %Mask, i1 true) 104 // CHECK-ARM-X64: [[TRUNC_INDEX:%[0-9]+]] = trunc i64 [[INDEX]] to i32 105 // CHECK-ARM-X64: store i32 [[TRUNC_INDEX]], i32* %Index, align 4 106 // CHECK-ARM-X64: br label %[[END_LABEL]] 107 108 unsigned char test_BitScanReverse64(unsigned long *Index, unsigned __int64 Mask) { 109 return _BitScanReverse64(Index, Mask); 110 } 111 // CHECK-ARM-X64: define{{.*}}i8 @test_BitScanReverse64(i32* {{[a-z_ ]*}}%Index, i64 {{[a-z_ ]*}}%Mask){{.*}}{ 112 // CHECK-ARM-X64: [[ISNOTZERO:%[0-9]+]] = icmp eq i64 %Mask, 0 113 // CHECK-ARM-X64: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]] 114 // CHECK-ARM-X64: [[END_LABEL]]: 115 // CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ] 116 // CHECK-ARM-X64: ret i8 [[RESULT]] 117 // CHECK-ARM-X64: [[ISNOTZERO_LABEL]]: 118 // CHECK-ARM-X64: [[REVINDEX:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %Mask, i1 true) 119 // CHECK-ARM-X64: [[TRUNC_REVINDEX:%[0-9]+]] = trunc i64 [[REVINDEX]] to i32 120 // CHECK-ARM-X64: [[INDEX:%[0-9]+]] = xor i32 [[TRUNC_REVINDEX]], 63 121 // CHECK-ARM-X64: store i32 [[INDEX]], i32* %Index, align 4 122 // CHECK-ARM-X64: br label %[[END_LABEL]] 123 #endif 124 125 void *test_InterlockedExchangePointer(void * volatile *Target, void *Value) { 126 return _InterlockedExchangePointer(Target, Value); 127 } 128 129 // CHECK: define{{.*}}i8* @test_InterlockedExchangePointer(i8** {{[a-z_ ]*}}%Target, i8* {{[a-z_ ]*}}%Value){{.*}}{ 130 // CHECK: %[[TARGET:[0-9]+]] = bitcast i8** %Target to [[iPTR:i[0-9]+]]* 131 // CHECK: %[[VALUE:[0-9]+]] = ptrtoint i8* %Value to [[iPTR]] 132 // CHECK: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg [[iPTR]]* %[[TARGET]], [[iPTR]] %[[VALUE]] seq_cst 133 // CHECK: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXCHANGE]] to i8* 134 // CHECK: ret i8* %[[RESULT]] 135 // CHECK: } 136 137 void *test_InterlockedCompareExchangePointer(void * volatile *Destination, 138 void *Exchange, void *Comparand) { 139 return _InterlockedCompareExchangePointer(Destination, Exchange, Comparand); 140 } 141 142 // CHECK: define{{.*}}i8* @test_InterlockedCompareExchangePointer(i8** {{[a-z_ ]*}}%Destination, i8* {{[a-z_ ]*}}%Exchange, i8* {{[a-z_ ]*}}%Comparand){{.*}}{ 143 // CHECK: %[[DEST:[0-9]+]] = bitcast i8** %Destination to [[iPTR]]* 144 // CHECK: %[[EXCHANGE:[0-9]+]] = ptrtoint i8* %Exchange to [[iPTR]] 145 // CHECK: %[[COMPARAND:[0-9]+]] = ptrtoint i8* %Comparand to [[iPTR]] 146 // CHECK: %[[XCHG:[0-9]+]] = cmpxchg volatile [[iPTR]]* %[[DEST:[0-9]+]], [[iPTR]] %[[COMPARAND:[0-9]+]], [[iPTR]] %[[EXCHANGE:[0-9]+]] seq_cst seq_cst 147 // CHECK: %[[EXTRACT:[0-9]+]] = extractvalue { [[iPTR]], i1 } %[[XCHG]], 0 148 // CHECK: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to i8* 149 // CHECK: ret i8* %[[RESULT:[0-9]+]] 150 // CHECK: } 151 152 char test_InterlockedExchange8(char volatile *value, char mask) { 153 return _InterlockedExchange8(value, mask); 154 } 155 // CHECK: define{{.*}}i8 @test_InterlockedExchange8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{ 156 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw xchg i8* %value, i8 %mask seq_cst 157 // CHECK: ret i8 [[RESULT:%[0-9]+]] 158 // CHECK: } 159 160 short test_InterlockedExchange16(short volatile *value, short mask) { 161 return _InterlockedExchange16(value, mask); 162 } 163 // CHECK: define{{.*}}i16 @test_InterlockedExchange16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{ 164 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw xchg i16* %value, i16 %mask seq_cst 165 // CHECK: ret i16 [[RESULT:%[0-9]+]] 166 // CHECK: } 167 168 long test_InterlockedExchange(long volatile *value, long mask) { 169 return _InterlockedExchange(value, mask); 170 } 171 // CHECK: define{{.*}}i32 @test_InterlockedExchange(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{ 172 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw xchg i32* %value, i32 %mask seq_cst 173 // CHECK: ret i32 [[RESULT:%[0-9]+]] 174 // CHECK: } 175 176 char test_InterlockedExchangeAdd8(char volatile *value, char mask) { 177 return _InterlockedExchangeAdd8(value, mask); 178 } 179 // CHECK: define{{.*}}i8 @test_InterlockedExchangeAdd8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{ 180 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw add i8* %value, i8 %mask seq_cst 181 // CHECK: ret i8 [[RESULT:%[0-9]+]] 182 // CHECK: } 183 184 short test_InterlockedExchangeAdd16(short volatile *value, short mask) { 185 return _InterlockedExchangeAdd16(value, mask); 186 } 187 // CHECK: define{{.*}}i16 @test_InterlockedExchangeAdd16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{ 188 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw add i16* %value, i16 %mask seq_cst 189 // CHECK: ret i16 [[RESULT:%[0-9]+]] 190 // CHECK: } 191 192 long test_InterlockedExchangeAdd(long volatile *value, long mask) { 193 return _InterlockedExchangeAdd(value, mask); 194 } 195 // CHECK: define{{.*}}i32 @test_InterlockedExchangeAdd(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{ 196 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw add i32* %value, i32 %mask seq_cst 197 // CHECK: ret i32 [[RESULT:%[0-9]+]] 198 // CHECK: } 199 200 char test_InterlockedExchangeSub8(char volatile *value, char mask) { 201 return _InterlockedExchangeSub8(value, mask); 202 } 203 // CHECK: define{{.*}}i8 @test_InterlockedExchangeSub8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{ 204 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw sub i8* %value, i8 %mask seq_cst 205 // CHECK: ret i8 [[RESULT:%[0-9]+]] 206 // CHECK: } 207 208 short test_InterlockedExchangeSub16(short volatile *value, short mask) { 209 return _InterlockedExchangeSub16(value, mask); 210 } 211 // CHECK: define{{.*}}i16 @test_InterlockedExchangeSub16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{ 212 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw sub i16* %value, i16 %mask seq_cst 213 // CHECK: ret i16 [[RESULT:%[0-9]+]] 214 // CHECK: } 215 216 long test_InterlockedExchangeSub(long volatile *value, long mask) { 217 return _InterlockedExchangeSub(value, mask); 218 } 219 // CHECK: define{{.*}}i32 @test_InterlockedExchangeSub(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{ 220 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw sub i32* %value, i32 %mask seq_cst 221 // CHECK: ret i32 [[RESULT:%[0-9]+]] 222 // CHECK: } 223 224 char test_InterlockedOr8(char volatile *value, char mask) { 225 return _InterlockedOr8(value, mask); 226 } 227 // CHECK: define{{.*}}i8 @test_InterlockedOr8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{ 228 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw or i8* %value, i8 %mask seq_cst 229 // CHECK: ret i8 [[RESULT:%[0-9]+]] 230 // CHECK: } 231 232 short test_InterlockedOr16(short volatile *value, short mask) { 233 return _InterlockedOr16(value, mask); 234 } 235 // CHECK: define{{.*}}i16 @test_InterlockedOr16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{ 236 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw or i16* %value, i16 %mask seq_cst 237 // CHECK: ret i16 [[RESULT:%[0-9]+]] 238 // CHECK: } 239 240 long test_InterlockedOr(long volatile *value, long mask) { 241 return _InterlockedOr(value, mask); 242 } 243 // CHECK: define{{.*}}i32 @test_InterlockedOr(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{ 244 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw or i32* %value, i32 %mask seq_cst 245 // CHECK: ret i32 [[RESULT:%[0-9]+]] 246 // CHECK: } 247 248 char test_InterlockedXor8(char volatile *value, char mask) { 249 return _InterlockedXor8(value, mask); 250 } 251 // CHECK: define{{.*}}i8 @test_InterlockedXor8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{ 252 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw xor i8* %value, i8 %mask seq_cst 253 // CHECK: ret i8 [[RESULT:%[0-9]+]] 254 // CHECK: } 255 256 short test_InterlockedXor16(short volatile *value, short mask) { 257 return _InterlockedXor16(value, mask); 258 } 259 // CHECK: define{{.*}}i16 @test_InterlockedXor16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{ 260 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw xor i16* %value, i16 %mask seq_cst 261 // CHECK: ret i16 [[RESULT:%[0-9]+]] 262 // CHECK: } 263 264 long test_InterlockedXor(long volatile *value, long mask) { 265 return _InterlockedXor(value, mask); 266 } 267 // CHECK: define{{.*}}i32 @test_InterlockedXor(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{ 268 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw xor i32* %value, i32 %mask seq_cst 269 // CHECK: ret i32 [[RESULT:%[0-9]+]] 270 // CHECK: } 271 272 char test_InterlockedAnd8(char volatile *value, char mask) { 273 return _InterlockedAnd8(value, mask); 274 } 275 // CHECK: define{{.*}}i8 @test_InterlockedAnd8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{ 276 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw and i8* %value, i8 %mask seq_cst 277 // CHECK: ret i8 [[RESULT:%[0-9]+]] 278 // CHECK: } 279 280 short test_InterlockedAnd16(short volatile *value, short mask) { 281 return _InterlockedAnd16(value, mask); 282 } 283 // CHECK: define{{.*}}i16 @test_InterlockedAnd16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{ 284 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw and i16* %value, i16 %mask seq_cst 285 // CHECK: ret i16 [[RESULT:%[0-9]+]] 286 // CHECK: } 287 288 long test_InterlockedAnd(long volatile *value, long mask) { 289 return _InterlockedAnd(value, mask); 290 } 291 // CHECK: define{{.*}}i32 @test_InterlockedAnd(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{ 292 // CHECK: [[RESULT:%[0-9]+]] = atomicrmw and i32* %value, i32 %mask seq_cst 293 // CHECK: ret i32 [[RESULT:%[0-9]+]] 294 // CHECK: } 295 296 char test_InterlockedCompareExchange8(char volatile *Destination, char Exchange, char Comperand) { 297 return _InterlockedCompareExchange8(Destination, Exchange, Comperand); 298 } 299 // CHECK: define{{.*}}i8 @test_InterlockedCompareExchange8(i8*{{[a-z_ ]*}}%Destination, i8{{[a-z_ ]*}}%Exchange, i8{{[a-z_ ]*}}%Comperand){{.*}}{ 300 // CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i8* %Destination, i8 %Comperand, i8 %Exchange seq_cst seq_cst 301 // CHECK: [[RESULT:%[0-9]+]] = extractvalue { i8, i1 } [[TMP]], 0 302 // CHECK: ret i8 [[RESULT]] 303 // CHECK: } 304 305 short test_InterlockedCompareExchange16(short volatile *Destination, short Exchange, short Comperand) { 306 return _InterlockedCompareExchange16(Destination, Exchange, Comperand); 307 } 308 // CHECK: define{{.*}}i16 @test_InterlockedCompareExchange16(i16*{{[a-z_ ]*}}%Destination, i16{{[a-z_ ]*}}%Exchange, i16{{[a-z_ ]*}}%Comperand){{.*}}{ 309 // CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i16* %Destination, i16 %Comperand, i16 %Exchange seq_cst seq_cst 310 // CHECK: [[RESULT:%[0-9]+]] = extractvalue { i16, i1 } [[TMP]], 0 311 // CHECK: ret i16 [[RESULT]] 312 // CHECK: } 313 314 long test_InterlockedCompareExchange(long volatile *Destination, long Exchange, long Comperand) { 315 return _InterlockedCompareExchange(Destination, Exchange, Comperand); 316 } 317 // CHECK: define{{.*}}i32 @test_InterlockedCompareExchange(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comperand){{.*}}{ 318 // CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i32* %Destination, i32 %Comperand, i32 %Exchange seq_cst seq_cst 319 // CHECK: [[RESULT:%[0-9]+]] = extractvalue { i32, i1 } [[TMP]], 0 320 // CHECK: ret i32 [[RESULT]] 321 // CHECK: } 322 323 __int64 test_InterlockedCompareExchange64(__int64 volatile *Destination, __int64 Exchange, __int64 Comperand) { 324 return _InterlockedCompareExchange64(Destination, Exchange, Comperand); 325 } 326 // CHECK: define{{.*}}i64 @test_InterlockedCompareExchange64(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comperand){{.*}}{ 327 // CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i64* %Destination, i64 %Comperand, i64 %Exchange seq_cst seq_cst 328 // CHECK: [[RESULT:%[0-9]+]] = extractvalue { i64, i1 } [[TMP]], 0 329 // CHECK: ret i64 [[RESULT]] 330 // CHECK: } 331 332 #if defined(__x86_64__) 333 unsigned char test_InterlockedCompareExchange128(__int64 volatile *Destination, __int64 ExchangeHigh, __int64 ExchangeLow, __int64* ComparandResult) { 334 return _InterlockedCompareExchange128(Destination, ExchangeHigh, ExchangeLow, ComparandResult); 335 } 336 // CHECK-X64: define{{.*}}i8 @test_InterlockedCompareExchange128(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%ExchangeHigh, i64{{[a-z_ ]*}}%ExchangeLow, i64*{{[a-z_ ]*}}%ComparandResult){{.*}}{ 337 // CHECK-X64: [[DST:%[0-9]+]] = bitcast i64* %Destination to i128* 338 // CHECK-X64: [[EH:%[0-9]+]] = zext i64 %ExchangeHigh to i128 339 // CHECK-X64: [[EL:%[0-9]+]] = zext i64 %ExchangeLow to i128 340 // CHECK-X64: [[CNR:%[0-9]+]] = bitcast i64* %ComparandResult to i128* 341 // CHECK-X64: [[EHS:%[0-9]+]] = shl nuw i128 [[EH]], 64 342 // CHECK-X64: [[EXP:%[0-9]+]] = or i128 [[EHS]], [[EL]] 343 // CHECK-X64: [[ORG:%[0-9]+]] = load i128, i128* [[CNR]], align 16 344 // CHECK-X64: [[RES:%[0-9]+]] = cmpxchg volatile i128* [[DST]], i128 [[ORG]], i128 [[EXP]] seq_cst seq_cst 345 // CHECK-X64: [[OLD:%[0-9]+]] = extractvalue { i128, i1 } [[RES]], 0 346 // CHECK-X64: store i128 [[OLD]], i128* [[CNR]], align 16 347 // CHECK-X64: [[SUC1:%[0-9]+]] = extractvalue { i128, i1 } [[RES]], 1 348 // CHECK-X64: [[SUC8:%[0-9]+]] = zext i1 [[SUC1]] to i8 349 // CHECK-X64: ret i8 [[SUC8]] 350 // CHECK-X64: } 351 #endif 352 353 short test_InterlockedIncrement16(short volatile *Addend) { 354 return _InterlockedIncrement16(Addend); 355 } 356 // CHECK: define{{.*}}i16 @test_InterlockedIncrement16(i16*{{[a-z_ ]*}}%Addend){{.*}}{ 357 // CHECK: [[TMP:%[0-9]+]] = atomicrmw add i16* %Addend, i16 1 seq_cst 358 // CHECK: [[RESULT:%[0-9]+]] = add i16 [[TMP]], 1 359 // CHECK: ret i16 [[RESULT]] 360 // CHECK: } 361 362 long test_InterlockedIncrement(long volatile *Addend) { 363 return _InterlockedIncrement(Addend); 364 } 365 // CHECK: define{{.*}}i32 @test_InterlockedIncrement(i32*{{[a-z_ ]*}}%Addend){{.*}}{ 366 // CHECK: [[TMP:%[0-9]+]] = atomicrmw add i32* %Addend, i32 1 seq_cst 367 // CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], 1 368 // CHECK: ret i32 [[RESULT]] 369 // CHECK: } 370 371 short test_InterlockedDecrement16(short volatile *Addend) { 372 return _InterlockedDecrement16(Addend); 373 } 374 // CHECK: define{{.*}}i16 @test_InterlockedDecrement16(i16*{{[a-z_ ]*}}%Addend){{.*}}{ 375 // CHECK: [[TMP:%[0-9]+]] = atomicrmw sub i16* %Addend, i16 1 seq_cst 376 // CHECK: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1 377 // CHECK: ret i16 [[RESULT]] 378 // CHECK: } 379 380 long test_InterlockedDecrement(long volatile *Addend) { 381 return _InterlockedDecrement(Addend); 382 } 383 // CHECK: define{{.*}}i32 @test_InterlockedDecrement(i32*{{[a-z_ ]*}}%Addend){{.*}}{ 384 // CHECK: [[TMP:%[0-9]+]] = atomicrmw sub i32* %Addend, i32 1 seq_cst 385 // CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 386 // CHECK: ret i32 [[RESULT]] 387 // CHECK: } 388 389 #if defined(__x86_64__) || defined(__arm__) 390 __int64 test_InterlockedExchange64(__int64 volatile *value, __int64 mask) { 391 return _InterlockedExchange64(value, mask); 392 } 393 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedExchange64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{ 394 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw xchg i64* %value, i64 %mask seq_cst 395 // CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]] 396 // CHECK-ARM-X64: } 397 398 __int64 test_InterlockedExchangeAdd64(__int64 volatile *value, __int64 mask) { 399 return _InterlockedExchangeAdd64(value, mask); 400 } 401 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedExchangeAdd64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{ 402 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw add i64* %value, i64 %mask seq_cst 403 // CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]] 404 // CHECK-ARM-X64: } 405 406 __int64 test_InterlockedExchangeSub64(__int64 volatile *value, __int64 mask) { 407 return _InterlockedExchangeSub64(value, mask); 408 } 409 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedExchangeSub64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{ 410 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw sub i64* %value, i64 %mask seq_cst 411 // CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]] 412 // CHECK-ARM-X64: } 413 414 __int64 test_InterlockedOr64(__int64 volatile *value, __int64 mask) { 415 return _InterlockedOr64(value, mask); 416 } 417 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedOr64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{ 418 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw or i64* %value, i64 %mask seq_cst 419 // CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]] 420 // CHECK-ARM-X64: } 421 422 __int64 test_InterlockedXor64(__int64 volatile *value, __int64 mask) { 423 return _InterlockedXor64(value, mask); 424 } 425 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedXor64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{ 426 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw xor i64* %value, i64 %mask seq_cst 427 // CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]] 428 // CHECK-ARM-X64: } 429 430 __int64 test_InterlockedAnd64(__int64 volatile *value, __int64 mask) { 431 return _InterlockedAnd64(value, mask); 432 } 433 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedAnd64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{ 434 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw and i64* %value, i64 %mask seq_cst 435 // CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]] 436 // CHECK-ARM-X64: } 437 438 __int64 test_InterlockedIncrement64(__int64 volatile *Addend) { 439 return _InterlockedIncrement64(Addend); 440 } 441 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedIncrement64(i64*{{[a-z_ ]*}}%Addend){{.*}}{ 442 // CHECK-ARM-X64: [[TMP:%[0-9]+]] = atomicrmw add i64* %Addend, i64 1 seq_cst 443 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], 1 444 // CHECK-ARM-X64: ret i64 [[RESULT]] 445 // CHECK-ARM-X64: } 446 447 __int64 test_InterlockedDecrement64(__int64 volatile *Addend) { 448 return _InterlockedDecrement64(Addend); 449 } 450 // CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedDecrement64(i64*{{[a-z_ ]*}}%Addend){{.*}}{ 451 // CHECK-ARM-X64: [[TMP:%[0-9]+]] = atomicrmw sub i64* %Addend, i64 1 seq_cst 452 // CHECK-ARM-X64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1 453 // CHECK-ARM-X64: ret i64 [[RESULT]] 454 // CHECK-ARM-X64: } 455 456 #endif 457 458 unsigned char test_interlockedbittestandset(volatile long *ptr, long bit) { 459 return _interlockedbittestandset(ptr, bit); 460 } 461 // CHECK-LABEL: define{{.*}} i8 @test_interlockedbittestandset 462 // CHECK: [[MASKBIT:%[0-9]+]] = shl i32 1, %bit 463 // CHECK: [[OLD:%[0-9]+]] = atomicrmw or i32* %ptr, i32 [[MASKBIT]] seq_cst 464 // CHECK: [[SHIFT:%[0-9]+]] = lshr i32 [[OLD]], %bit 465 // CHECK: [[TRUNC:%[0-9]+]] = trunc i32 [[SHIFT]] to i8 466 // CHECK: [[AND:%[0-9]+]] = and i8 [[TRUNC]], 1 467 // CHECK: ret i8 [[AND]] 468 469 void test__fastfail() { 470 __fastfail(42); 471 } 472 // CHECK-LABEL: define{{.*}} void @test__fastfail() 473 // CHECK-ARM: call void asm sideeffect "udf #251", "{r0}"(i32 42) #[[NORETURN:[0-9]+]] 474 // CHECK-INTEL: call void asm sideeffect "int $$0x29", "{cx}"(i32 42) #[[NORETURN]] 475 476 // Attributes come last. 477 478 // CHECK: attributes #[[NORETURN]] = { noreturn{{.*}} } 479 480