Home | History | Annotate | Download | only in OpenMP
      1 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
      2 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
      3 // RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
      4 // RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
      5 // RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
      6 // RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
      7 // expected-no-diagnostics
      8 #ifndef ARRAY
      9 #ifndef HEADER
     10 #define HEADER
     11 
     12 struct St {
     13   int a, b;
     14   St() : a(0), b(0) {}
     15   St(const St &st) : a(st.a + st.b), b(0) {}
     16   ~St() {}
     17 };
     18 
     19 volatile int g __attribute__((aligned(128))) = 1212;
     20 
     21 template <class T>
     22 struct S {
     23   T f;
     24   S(T a) : f(a + g) {}
     25   S() : f(g) {}
     26   S(const S &s, St t = St()) : f(s.f + t.a) {}
     27   operator T() { return T(); }
     28   ~S() {}
     29 };
     30 
     31 // CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
     32 // CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
     33 // CHECK-DAG: [[ST_TY:%.+]] = type { i{{[0-9]+}}, i{{[0-9]+}} }
     34 // CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
     35 
     36 template <typename T>
     37 T tmain() {
     38   S<T> test;
     39   T t_var __attribute__((aligned(128))) = T();
     40   T vec[] __attribute__((aligned(128))) = {1, 2};
     41   S<T> s_arr[] __attribute__((aligned(128))) = {1, 2};
     42   S<T> var __attribute__((aligned(128))) (3);
     43 #pragma omp parallel firstprivate(t_var, vec, s_arr, var)
     44   {
     45     vec[0] = t_var;
     46     s_arr[0] = var;
     47   }
     48 #pragma omp parallel firstprivate(t_var)
     49   {}
     50   return T();
     51 }
     52 
     53 int main() {
     54   static int sivar;
     55 #ifdef LAMBDA
     56   // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
     57   // LAMBDA-LABEL: @main
     58   // LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
     59   [&]() {
     60   // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
     61   // LAMBDA: call {{.*}}void {{.+}} @__kmpc_fork_call({{.+}}, i32 2, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i32* [[G]], {{.+}})
     62 #pragma omp parallel firstprivate(g, sivar)
     63   {
     64     // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}})
     65     // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, align 128
     66     // LAMBDA: [[SIVAR_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
     67     // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR:%.+]]
     68     // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_REF_ADDR:%.+]]
     69     // LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G_REF]], align 128
     70     // LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]], align 128
     71     // LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]]
     72     // LAMBDA: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
     73     // LAMBDA: call {{.*}}void @__kmpc_barrier(
     74     g = 1;
     75     sivar = 2;
     76     // LAMBDA: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
     77     // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]],
     78     // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
     79     // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** [[G_PRIVATE_ADDR_REF]]
     80     // LAMBDA: [[SIVAR_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
     81     // LAMBDA: store i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]], i{{[0-9]+}}** [[SIVAR_PRIVATE_ADDR_REF]]
     82     // LAMBDA: call{{.*}} void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]])
     83     [&]() {
     84       // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
     85       // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
     86       g = 2;
     87       sivar = 4;
     88       // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
     89       // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
     90       // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
     91       // LAMBDA: [[SIVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
     92       // LAMBDA: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_PTR_REF]]
     93       // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SIVAR_REF]]
     94     }();
     95   }
     96   }();
     97   return 0;
     98 #elif defined(BLOCKS)
     99   // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
    100   // BLOCKS-LABEL: @main
    101   // BLOCKS: call {{.*}}void {{%.+}}(i8
    102   ^{
    103   // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
    104   // BLOCKS: call {{.*}}void {{.+}} @__kmpc_fork_call({{.+}}, i32 2, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i32* [[G]], {{.+}})
    105 #pragma omp parallel firstprivate(g, sivar)
    106   {
    107     // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}})
    108     // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, align 128
    109     // BLOCKS: [[SIVAR_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
    110     // BLOCKS: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR:%.+]]
    111     // BLOCKS: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_REF_ADDR:%.+]]
    112     // BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G_REF]], align 128
    113     // BLOCKS: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]], align 128
    114     // BLOCK: [[SIVAR_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
    115     // BLOCK: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_REF_ADDR]]
    116     // BLOCKS: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]],
    117     // BLOCKS: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]],
    118     // BLOCKS: call {{.*}}void @__kmpc_barrier(
    119     g = 1;
    120     sivar = 2;
    121     // BLOCKS: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
    122     // BLOCKS: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]],
    123     // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
    124     // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
    125     // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
    126     // BLOCKS-NOT: [[SIVAR]]{{[[^:word:]]}}
    127     // BLOCKS: i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
    128     // BLOCKS-NOT: [[SIVAR]]{{[[^:word:]]}}
    129     // BLOCKS: call {{.*}}void {{%.+}}(i8
    130     ^{
    131       // BLOCKS: define {{.+}} void {{@.+}}(i8*
    132       g = 2;
    133       sivar = 4;
    134       // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
    135       // BLOCKS: store i{{[0-9]+}} 2, i{{[0-9]+}}*
    136       // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
    137       // BLOCKS-NOT: [[SIVAR]]{{[[^:word:]]}}
    138       // BLOCKS: store i{{[0-9]+}} 4, i{{[0-9]+}}*
    139       // BLOCKS-NOT: [[SIVAR]]{{[[^:word:]]}}
    140       // BLOCKS: ret
    141     }();
    142   }
    143   }();
    144   return 0;
    145 #else
    146   S<float> test;
    147   int t_var = 0;
    148   int vec[] = {1, 2};
    149   S<float> s_arr[] = {1, 2};
    150   S<float> var(3);
    151 #pragma omp parallel firstprivate(t_var, vec, s_arr, var, sivar)
    152   {
    153     vec[0] = t_var;
    154     s_arr[0] = var;
    155     sivar = 2;
    156   }
    157 #pragma omp parallel firstprivate(t_var)
    158   {}
    159   return tmain<int>();
    160 #endif
    161 }
    162 
    163 // CHECK: define {{.*}}i{{[0-9]+}} @main()
    164 // CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]],
    165 // CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
    166 // CHECK: call {{.*}}void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 5, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x i32]*, i32*, [2 x [[S_FLOAT_TY]]]*, [[S_FLOAT_TY]]*, i{{[0-9]+}}*)* [[MAIN_MICROTASK:@.+]] to void
    167 // CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
    168 // CHECK: call {{.*}} [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]*
    169 // CHECK: ret
    170 //
    171 // CHECK: define internal {{.*}}void [[MAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x i32]* dereferenceable(8) %{{.+}}, i32* dereferenceable(4) %{{.+}}, [2 x [[S_FLOAT_TY]]]* dereferenceable(8) %{{.+}}, [[S_FLOAT_TY]]* dereferenceable(4) %{{.+}}, i32* dereferenceable(4) [[SIVAR:%.+]])
    172 // CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
    173 // CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
    174 // CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
    175 // CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
    176 // CHECK: [[SIVAR7_PRIV:%.+]] = alloca i{{[0-9]+}},
    177 // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
    178 
    179 // CHECK: [[VEC_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** %
    180 // CHECK: [[T_VAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %
    181 // CHECK: [[S_ARR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** %
    182 // CHECK: [[VAR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %
    183 // CHECK: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}},
    184 // CHECK: [[T_VAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR_REF]],
    185 // CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]],
    186 // CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
    187 // CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
    188 // CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
    189 // CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
    190 // CHECK: [[S_ARR_BEGIN:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[S_ARR_REF]] to [[S_FLOAT_TY]]*
    191 // CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
    192 // CHECK: [[IS_EMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_PRIV_BEGIN]], [[S_ARR_PRIV_END]]
    193 // CHECK: br i1 [[IS_EMPTY]], label %[[S_ARR_BODY_DONE:.+]], label %[[S_ARR_BODY:.+]]
    194 // CHECK: [[S_ARR_BODY]]
    195 // CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR:@.+]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
    196 // CHECK: call {{.*}} [[S_FLOAT_TY_COPY_CONSTR:@.+]]([[S_FLOAT_TY]]* {{.+}}, [[S_FLOAT_TY]]* {{.+}}, [[ST_TY]]* [[ST_TY_TEMP]])
    197 // CHECK: call {{.*}} [[ST_TY_DESTR:@.+]]([[ST_TY]]* [[ST_TY_TEMP]])
    198 // CHECK: br i1 {{.+}}, label %{{.+}}, label %[[S_ARR_BODY]]
    199 // CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
    200 // CHECK: call {{.*}} [[S_FLOAT_TY_COPY_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
    201 // CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
    202 
    203 // CHECK: [[SIVAR_REF_ADDR:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]],
    204 // CHECK: store i{{[0-9]+}} [[SIVAR_REF_ADDR]], i{{[0-9]+}}* [[SIVAR7_PRIV]],
    205 // CHECK: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[SIVAR7_PRIV]],
    206 
    207 // CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
    208 // CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
    209 // CHECK: ret void
    210 // CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
    211 // CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
    212 // CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
    213 // CHECK: call {{.*}}void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x i32]*, i32*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void
    214 // CHECK: call {{.*}} [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
    215 // CHECK: ret
    216 //
    217 // CHECK: define internal {{.*}}void [[TMAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x i32]* dereferenceable(8) %{{.+}}, i32* dereferenceable(4) %{{.+}}, [2 x [[S_INT_TY]]]* dereferenceable(8) %{{.+}}, [[S_INT_TY]]* dereferenceable(4) %{{.+}})
    218 // CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}}, align 128
    219 // CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}], align 128
    220 // CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]], align 128
    221 // CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]], align 128
    222 // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
    223 
    224 // CHECK: [[VEC_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** %
    225 // CHECK: [[T_VAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %
    226 // CHECK: [[S_ARR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** %
    227 // CHECK: [[VAR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** %
    228 
    229 // CHECK: [[T_VAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR_REF]], align 128
    230 // CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]], align 128
    231 // CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
    232 // CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
    233 // CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]], i{{[0-9]+}} {{[0-9]+}}, i{{[0-9]+}} 128,
    234 // CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
    235 // CHECK: [[S_ARR_BEGIN:%.+]] = bitcast [2 x [[S_INT_TY]]]* [[S_ARR_REF]] to [[S_INT_TY]]*
    236 // CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
    237 // CHECK: [[IS_EMPTY:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_PRIV_BEGIN]], [[S_ARR_PRIV_END]]
    238 // CHECK: br i1 [[IS_EMPTY]], label %[[S_ARR_BODY_DONE:.+]], label %[[S_ARR_BODY:.+]]
    239 // CHECK: [[S_ARR_BODY]]
    240 // CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
    241 // CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR:@.+]]([[S_INT_TY]]* {{.+}}, [[S_INT_TY]]* {{.+}}, [[ST_TY]]* [[ST_TY_TEMP]])
    242 // CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
    243 // CHECK: br i1 {{.+}}, label %{{.+}}, label %[[S_ARR_BODY]]
    244 // CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
    245 // CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
    246 // CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
    247 // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
    248 // CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
    249 // CHECK: call {{.*}}void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
    250 // CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
    251 // CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
    252 // CHECK: ret void
    253 
    254 #endif
    255 #else
    256 struct St {
    257   int a, b;
    258   St() : a(0), b(0) {}
    259   St(const St &) { }
    260   ~St() {}
    261   void St_func(St s[2], int n, long double vla1[n]) {
    262     double vla2[n][n] __attribute__((aligned(128)));
    263     a = b;
    264 #pragma omp parallel firstprivate(s, vla1, vla2)
    265     vla1[b] = vla2[1][n - 1] = a = b;
    266   }
    267 };
    268 
    269 // ARRAY-LABEL: array_func
    270 void array_func(float a[3], St s[2], int n, long double vla1[n]) {
    271   double vla2[n][n] __attribute__((aligned(128)));
    272 // ARRAY: @__kmpc_fork_call(
    273 // ARRAY-DAG: [[PRIV_A:%.+]] = alloca float**,
    274 // ARRAY-DAG: [[PRIV_S:%.+]] = alloca %struct.St**,
    275 // ARRAY-DAG: [[PRIV_VLA1:%.+]] = alloca x86_fp80**,
    276 // ARRAY-DAG: [[PRIV_VLA2:%.+]] = alloca double*,
    277 // ARRAY-DAG: store float** %{{.+}}, float*** [[PRIV_A]],
    278 // ARRAY-DAG: store %struct.St** %{{.+}}, %struct.St*** [[PRIV_S]],
    279 // ARRAY-DAG: store x86_fp80** %{{.+}}, x86_fp80*** [[PRIV_VLA1]],
    280 // ARRAY-DAG: store double* %{{.+}}, double** [[PRIV_VLA2]],
    281 // ARRAY: call i8* @llvm.stacksave()
    282 // ARRAY: [[SIZE:%.+]] = mul nuw i64 %{{.+}}, 8
    283 // ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 [[SIZE]], i32 128, i1 false)
    284 #pragma omp parallel firstprivate(a, s, vla1, vla2)
    285   s[0].St_func(s, n, vla1);
    286   ;
    287 }
    288 
    289 // ARRAY-LABEL: St_func
    290 // ARRAY: @__kmpc_fork_call(
    291 // ARRAY-DAG: [[PRIV_S:%.+]] = alloca %struct.St**,
    292 // ARRAY-DAG: [[PRIV_VLA1:%.+]] = alloca x86_fp80**,
    293 // ARRAY-DAG: [[PRIV_VLA2:%.+]] = alloca double*,
    294 // ARRAY-DAG: store %struct.St** %{{.+}}, %struct.St*** [[PRIV_S]],
    295 // ARRAY-DAG: store x86_fp80** %{{.+}}, x86_fp80*** [[PRIV_VLA1]],
    296 // ARRAY-DAG: store double* %{{.+}}, double** [[PRIV_VLA2]],
    297 // ARRAY: call i8* @llvm.stacksave()
    298 // ARRAY: [[SIZE:%.+]] = mul nuw i64 %{{.+}}, 8
    299 // ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 [[SIZE]], i32 128, i1 false)
    300 #endif
    301 
    302 
    303