102 lines · cpp
1// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fms-extensions -fms-compatibility -fms-compatibility-version=19 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s2// REQUIRES: asserts3 4struct S {5 S();6 ~S();7};8 9// CHECK-DAG: @"?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer10// CHECK-DAG: @"??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 011// CHECK-DAG: @"?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer12// CHECK-DAG: @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 013// CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 414// CHECK-DAG: @"?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer15// CHECK-DAG: @"??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 016// CHECK-DAG: @"?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer17// CHECK-DAG: @"?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 018// CHECK-DAG: @"?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 419// CHECK-DAG: @"?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 420 21// CHECK-LABEL: define {{.*}} @"?f@@YAAAUS@@XZ"()22// CHECK-SAME: personality ptr @__CxxFrameHandler323extern inline S &f() {24 static thread_local S s;25// CHECK: %[[guard:.*]] = load i32, ptr @"??__J?1??f@@YAAAUS@@XZ@51"26// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], 127// CHECK-NEXT: %[[cmp:.*]] = icmp eq i32 %[[mask]], 028// CHECK-NEXT: br i1 %[[cmp]], label %[[init:.*]], label %[[init_end:.*]], !prof ![[unlikely_threadlocal:.*]]29//30// CHECK: [[init]]:31// CHECK-NEXT: %[[or:.*]] = or i32 %[[guard]], 132// CHECK-NEXT: store i32 %[[or]], ptr @"??__J?1??f@@YAAAUS@@XZ@51"33// CHECK-NEXT: invoke {{.*}} @"??0S@@QAE@XZ"(ptr {{[^,]*}} @"?s@?1??f@@YAAAUS@@XZ@4U2@A")34// CHECK-NEXT: to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]35//36// CHECK: [[invoke_cont]]:37// CHECK-NEXT: call i32 @__tlregdtor(ptr @"??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")38// CHECK-NEXT: br label %[[init_end:.*]]39 40// CHECK: [[init_end]]:41// CHECK: [[S_ADDR:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @"?s@?1??f@@YAAAUS@@XZ@4U2@A")42// CHECK-NEXT: ret ptr [[S_ADDR]]43 44// CHECK: [[lpad:.*]]:45// CHECK-NEXT: cleanuppad within none []46// CHECK: %[[guard:.*]] = load i32, ptr @"??__J?1??f@@YAAAUS@@XZ@51"47// CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], -248// CHECK-NEXT: store i32 %[[mask]], ptr @"??__J?1??f@@YAAAUS@@XZ@51"49// CHECK-NEXT: cleanupret {{.*}} unwind to caller50 return s;51}52 53 54// CHECK-LABEL: define {{.*}} @"?g@@YAAAUS@@XZ"()55extern inline S &g() {56 static S s;57// CHECK: %[[guard:.*]] = load atomic i32, ptr @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 458// CHECK-NEXT: %[[epoch:.*]] = load i32, ptr @_Init_thread_epoch59// CHECK-NEXT: %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]60// CHECK-NEXT: br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]], !prof ![[unlikely_staticlocal:.*]]61//62// CHECK: [[init_attempt]]:63// CHECK-NEXT: call void @_Init_thread_header(ptr @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")64// CHECK-NEXT: %[[guard2:.*]] = load atomic i32, ptr @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 465// CHECK-NEXT: %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -166// CHECK-NEXT: br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]67//68// CHECK: [[init]]:69// CHECK-NEXT: invoke {{.*}} @"??0S@@QAE@XZ"(ptr {{[^,]*}} @"?s@?1??g@@YAAAUS@@XZ@4U2@A")70// CHECK-NEXT: to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]71//72// CHECK: [[invoke_cont]]:73// CHECK-NEXT: call i32 @atexit(ptr @"??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")74// CHECK-NEXT: call void @_Init_thread_footer(ptr @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")75// CHECK-NEXT: br label %init.end76//77// CHECK: [[init_end]]:78// CHECK-NEXT: ret ptr @"?s@?1??g@@YAAAUS@@XZ@4U2@A"79//80// CHECK: [[lpad]]:81// CHECK-NEXT: cleanuppad within none []82// CHECK: call void @_Init_thread_abort(ptr @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")83// CHECK-NEXT: cleanupret {{.*}} unwind to caller84 return s;85}86 87extern inline S&h(bool b) {88 static thread_local S j;89 static S i;90 return b ? j : i;91}92 93// CHECK-LABEL: define dso_local noundef i32 @"?g1@@YAHXZ"()94int f1();95int g1() {96 static int i = f1();97 return i;98}99 100// CHECK-DAG: ![[unlikely_threadlocal]] = !{!"branch_weights", i32 1, i32 1023}101// CHECK-DAG: ![[unlikely_staticlocal]] = !{!"branch_weights", i32 1, i32 1048575}102