1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ 2 // RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=IR 3 4 // Check same results after serialization round-trip 5 // RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-pch -o %t %s 6 // RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -include-pch %t -emit-llvm %s -o - | FileCheck %s --check-prefix=IR-PCH 7 8 // expected-no-diagnostics 9 10 #ifndef HEADER 11 #define HEADER 12 int foo() { 13 int i; 14 int j; 15 int sum[10][10]; 16 17 #pragma omp teams loop reduction(+:sum) collapse(2) bind(parallel) \ 18 order(concurrent) lastprivate(j) 19 for(i=0; i<10; i++) 20 for(j=0; j<10; j++) 21 sum[i][j] += i; 22 23 return 0; 24 } 25 #endif 26 // IR-LABEL: define {{[^@]+}}@_Z3foov 27 // IR-SAME: () #[[ATTR0:[0-9]+]] { 28 // IR-NEXT: entry: 29 // IR-NEXT: [[I:%.*]] = alloca i32, align 4 30 // IR-NEXT: [[J:%.*]] = alloca i32, align 4 31 // IR-NEXT: [[SUM:%.*]] = alloca [10 x [10 x i32]], align 16 32 // IR-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB4:[0-9]+]], i32 2, ptr @_Z3foov.omp_outlined, ptr [[J]], ptr [[SUM]]) 33 // IR-NEXT: ret i32 0 34 // 35 // 36 // IR-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined 37 // IR-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[J:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[SUM:%.*]]) #[[ATTR1:[0-9]+]] { 38 // IR-NEXT: entry: 39 // IR-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 40 // IR-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 41 // IR-NEXT: [[J_ADDR:%.*]] = alloca ptr, align 8 42 // IR-NEXT: [[SUM_ADDR:%.*]] = alloca ptr, align 8 43 // IR-NEXT: [[SUM1:%.*]] = alloca [10 x [10 x i32]], align 16 44 // IR-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 45 // IR-NEXT: [[TMP:%.*]] = alloca i32, align 4 46 // IR-NEXT: [[_TMP2:%.*]] = alloca i32, align 4 47 // IR-NEXT: [[DOTOMP_COMB_LB:%.*]] = alloca i32, align 4 48 // IR-NEXT: [[DOTOMP_COMB_UB:%.*]] = alloca i32, align 4 49 // IR-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 50 // IR-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 51 // IR-NEXT: [[J3:%.*]] = alloca i32, align 4 52 // IR-NEXT: [[I:%.*]] = alloca i32, align 4 53 // IR-NEXT: [[J4:%.*]] = alloca i32, align 4 54 // IR-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8 55 // IR-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 56 // IR-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 57 // IR-NEXT: store ptr [[J]], ptr [[J_ADDR]], align 8 58 // IR-NEXT: store ptr [[SUM]], ptr [[SUM_ADDR]], align 8 59 // IR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[J_ADDR]], align 8 60 // IR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SUM_ADDR]], align 8 61 // IR-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [10 x [10 x i32]], ptr [[SUM1]], i32 0, i32 0, i32 0 62 // IR-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[ARRAY_BEGIN]], i64 100 63 // IR-NEXT: [[OMP_ARRAYINIT_ISEMPTY:%.*]] = icmp eq ptr [[ARRAY_BEGIN]], [[TMP2]] 64 // IR-NEXT: br i1 [[OMP_ARRAYINIT_ISEMPTY]], label [[OMP_ARRAYINIT_DONE:%.*]], label [[OMP_ARRAYINIT_BODY:%.*]] 65 // IR: omp.arrayinit.body: 66 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYINIT_BODY]] ] 67 // IR-NEXT: store i32 0, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 68 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 69 // IR-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP2]] 70 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYINIT_DONE]], label [[OMP_ARRAYINIT_BODY]] 71 // IR: omp.arrayinit.done: 72 // IR-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 73 // IR-NEXT: store i32 99, ptr [[DOTOMP_COMB_UB]], align 4 74 // IR-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 75 // IR-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 76 // IR-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 77 // IR-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 78 // IR-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB1:[0-9]+]], i32 [[TMP4]], i32 92, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_COMB_LB]], ptr [[DOTOMP_COMB_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) 79 // IR-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 80 // IR-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 99 81 // IR-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 82 // IR: cond.true: 83 // IR-NEXT: br label [[COND_END:%.*]] 84 // IR: cond.false: 85 // IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 86 // IR-NEXT: br label [[COND_END]] 87 // IR: cond.end: 88 // IR-NEXT: [[COND:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[TMP6]], [[COND_FALSE]] ] 89 // IR-NEXT: store i32 [[COND]], ptr [[DOTOMP_COMB_UB]], align 4 90 // IR-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_COMB_LB]], align 4 91 // IR-NEXT: store i32 [[TMP7]], ptr [[DOTOMP_IV]], align 4 92 // IR-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] 93 // IR: omp.inner.for.cond: 94 // IR-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 95 // IR-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 96 // IR-NEXT: [[CMP5:%.*]] = icmp sle i32 [[TMP8]], [[TMP9]] 97 // IR-NEXT: br i1 [[CMP5]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] 98 // IR: omp.inner.for.body: 99 // IR-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_COMB_LB]], align 4 100 // IR-NEXT: [[TMP11:%.*]] = zext i32 [[TMP10]] to i64 101 // IR-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 102 // IR-NEXT: [[TMP13:%.*]] = zext i32 [[TMP12]] to i64 103 // IR-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB4]], i32 4, ptr @_Z3foov.omp_outlined.omp_outlined, i64 [[TMP11]], i64 [[TMP13]], ptr [[J3]], ptr [[SUM1]]) 104 // IR-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] 105 // IR: omp.inner.for.inc: 106 // IR-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 107 // IR-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4 108 // IR-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP14]], [[TMP15]] 109 // IR-NEXT: store i32 [[ADD]], ptr [[DOTOMP_IV]], align 4 110 // IR-NEXT: br label [[OMP_INNER_FOR_COND]] 111 // IR: omp.inner.for.end: 112 // IR-NEXT: br label [[OMP_LOOP_EXIT:%.*]] 113 // IR: omp.loop.exit: 114 // IR-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 115 // IR-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 116 // IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) 117 // IR-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 118 // IR-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 119 // IR-NEXT: br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] 120 // IR: .omp.lastprivate.then: 121 // IR-NEXT: store i32 10, ptr [[J3]], align 4 122 // IR-NEXT: [[TMP20:%.*]] = load i32, ptr [[J3]], align 4 123 // IR-NEXT: store i32 [[TMP20]], ptr [[TMP0]], align 4 124 // IR-NEXT: br label [[DOTOMP_LASTPRIVATE_DONE]] 125 // IR: .omp.lastprivate.done: 126 // IR-NEXT: [[TMP21:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 127 // IR-NEXT: store ptr [[SUM1]], ptr [[TMP21]], align 8 128 // IR-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 129 // IR-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 130 // IR-NEXT: [[TMP24:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP23]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) 131 // IR-NEXT: switch i32 [[TMP24]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ 132 // IR-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] 133 // IR-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] 134 // IR-NEXT: ] 135 // IR: .omp.reduction.case1: 136 // IR-NEXT: [[TMP25:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 137 // IR-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP1]], [[TMP25]] 138 // IR-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE10:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 139 // IR: omp.arraycpy.body: 140 // IR-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[SUM1]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 141 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST6:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT8:%.*]], [[OMP_ARRAYCPY_BODY]] ] 142 // IR-NEXT: [[TMP26:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST6]], align 4 143 // IR-NEXT: [[TMP27:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 144 // IR-NEXT: [[ADD7:%.*]] = add nsw i32 [[TMP26]], [[TMP27]] 145 // IR-NEXT: store i32 [[ADD7]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST6]], align 4 146 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT8]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST6]], i32 1 147 // IR-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 148 // IR-NEXT: [[OMP_ARRAYCPY_DONE9:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT8]], [[TMP25]] 149 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE9]], label [[OMP_ARRAYCPY_DONE10]], label [[OMP_ARRAYCPY_BODY]] 150 // IR: omp.arraycpy.done10: 151 // IR-NEXT: call void @__kmpc_end_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP23]], ptr @.gomp_critical_user_.reduction.var) 152 // IR-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 153 // IR: .omp.reduction.case2: 154 // IR-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 155 // IR-NEXT: [[OMP_ARRAYCPY_ISEMPTY11:%.*]] = icmp eq ptr [[TMP1]], [[TMP28]] 156 // IR-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY11]], label [[OMP_ARRAYCPY_DONE18:%.*]], label [[OMP_ARRAYCPY_BODY12:%.*]] 157 // IR: omp.arraycpy.body12: 158 // IR-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST13:%.*]] = phi ptr [ [[SUM1]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT16:%.*]], [[OMP_ARRAYCPY_BODY12]] ] 159 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST14:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT15:%.*]], [[OMP_ARRAYCPY_BODY12]] ] 160 // IR-NEXT: [[TMP29:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST13]], align 4 161 // IR-NEXT: [[TMP30:%.*]] = atomicrmw add ptr [[OMP_ARRAYCPY_DESTELEMENTPAST14]], i32 [[TMP29]] monotonic, align 4 162 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT15]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST14]], i32 1 163 // IR-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT16]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST13]], i32 1 164 // IR-NEXT: [[OMP_ARRAYCPY_DONE17:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT15]], [[TMP28]] 165 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE17]], label [[OMP_ARRAYCPY_DONE18]], label [[OMP_ARRAYCPY_BODY12]] 166 // IR: omp.arraycpy.done18: 167 // IR-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 168 // IR: .omp.reduction.default: 169 // IR-NEXT: ret void 170 // 171 // 172 // IR-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined.omp_outlined 173 // IR-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[J:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[SUM:%.*]]) #[[ATTR1]] { 174 // IR-NEXT: entry: 175 // IR-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 176 // IR-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 177 // IR-NEXT: [[DOTPREVIOUS_LB__ADDR:%.*]] = alloca i64, align 8 178 // IR-NEXT: [[DOTPREVIOUS_UB__ADDR:%.*]] = alloca i64, align 8 179 // IR-NEXT: [[J_ADDR:%.*]] = alloca ptr, align 8 180 // IR-NEXT: [[SUM_ADDR:%.*]] = alloca ptr, align 8 181 // IR-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 182 // IR-NEXT: [[TMP:%.*]] = alloca i32, align 4 183 // IR-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 184 // IR-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 185 // IR-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 186 // IR-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 187 // IR-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 188 // IR-NEXT: [[J3:%.*]] = alloca i32, align 4 189 // IR-NEXT: [[SUM4:%.*]] = alloca [10 x [10 x i32]], align 16 190 // IR-NEXT: [[I:%.*]] = alloca i32, align 4 191 // IR-NEXT: [[J5:%.*]] = alloca i32, align 4 192 // IR-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8 193 // IR-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 194 // IR-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 195 // IR-NEXT: store i64 [[DOTPREVIOUS_LB_]], ptr [[DOTPREVIOUS_LB__ADDR]], align 8 196 // IR-NEXT: store i64 [[DOTPREVIOUS_UB_]], ptr [[DOTPREVIOUS_UB__ADDR]], align 8 197 // IR-NEXT: store ptr [[J]], ptr [[J_ADDR]], align 8 198 // IR-NEXT: store ptr [[SUM]], ptr [[SUM_ADDR]], align 8 199 // IR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[J_ADDR]], align 8 200 // IR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SUM_ADDR]], align 8 201 // IR-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 202 // IR-NEXT: store i32 99, ptr [[DOTOMP_UB]], align 4 203 // IR-NEXT: [[TMP2:%.*]] = load i64, ptr [[DOTPREVIOUS_LB__ADDR]], align 8 204 // IR-NEXT: [[CONV:%.*]] = trunc i64 [[TMP2]] to i32 205 // IR-NEXT: [[TMP3:%.*]] = load i64, ptr [[DOTPREVIOUS_UB__ADDR]], align 8 206 // IR-NEXT: [[CONV2:%.*]] = trunc i64 [[TMP3]] to i32 207 // IR-NEXT: store i32 [[CONV]], ptr [[DOTOMP_LB]], align 4 208 // IR-NEXT: store i32 [[CONV2]], ptr [[DOTOMP_UB]], align 4 209 // IR-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 210 // IR-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 211 // IR-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [10 x [10 x i32]], ptr [[SUM4]], i32 0, i32 0, i32 0 212 // IR-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[ARRAY_BEGIN]], i64 100 213 // IR-NEXT: [[OMP_ARRAYINIT_ISEMPTY:%.*]] = icmp eq ptr [[ARRAY_BEGIN]], [[TMP4]] 214 // IR-NEXT: br i1 [[OMP_ARRAYINIT_ISEMPTY]], label [[OMP_ARRAYINIT_DONE:%.*]], label [[OMP_ARRAYINIT_BODY:%.*]] 215 // IR: omp.arrayinit.body: 216 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYINIT_BODY]] ] 217 // IR-NEXT: store i32 0, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 218 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 219 // IR-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP4]] 220 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYINIT_DONE]], label [[OMP_ARRAYINIT_BODY]] 221 // IR: omp.arrayinit.done: 222 // IR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 223 // IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4 224 // IR-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) 225 // IR-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 226 // IR-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP7]], 99 227 // IR-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 228 // IR: cond.true: 229 // IR-NEXT: br label [[COND_END:%.*]] 230 // IR: cond.false: 231 // IR-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 232 // IR-NEXT: br label [[COND_END]] 233 // IR: cond.end: 234 // IR-NEXT: [[COND:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[TMP8]], [[COND_FALSE]] ] 235 // IR-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4 236 // IR-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 237 // IR-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 238 // IR-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] 239 // IR: omp.inner.for.cond: 240 // IR-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3:![0-9]+]] 241 // IR-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !llvm.access.group [[ACC_GRP3]] 242 // IR-NEXT: [[CMP6:%.*]] = icmp sle i32 [[TMP10]], [[TMP11]] 243 // IR-NEXT: br i1 [[CMP6]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] 244 // IR: omp.inner.for.body: 245 // IR-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 246 // IR-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP12]], 10 247 // IR-NEXT: [[MUL:%.*]] = mul nsw i32 [[DIV]], 1 248 // IR-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] 249 // IR-NEXT: store i32 [[ADD]], ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] 250 // IR-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 251 // IR-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 252 // IR-NEXT: [[DIV7:%.*]] = sdiv i32 [[TMP14]], 10 253 // IR-NEXT: [[MUL8:%.*]] = mul nsw i32 [[DIV7]], 10 254 // IR-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP13]], [[MUL8]] 255 // IR-NEXT: [[MUL9:%.*]] = mul nsw i32 [[SUB]], 1 256 // IR-NEXT: [[ADD10:%.*]] = add nsw i32 0, [[MUL9]] 257 // IR-NEXT: store i32 [[ADD10]], ptr [[J3]], align 4, !llvm.access.group [[ACC_GRP3]] 258 // IR-NEXT: [[TMP15:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] 259 // IR-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] 260 // IR-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP16]] to i64 261 // IR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x [10 x i32]], ptr [[SUM4]], i64 0, i64 [[IDXPROM]] 262 // IR-NEXT: [[TMP17:%.*]] = load i32, ptr [[J3]], align 4, !llvm.access.group [[ACC_GRP3]] 263 // IR-NEXT: [[IDXPROM11:%.*]] = sext i32 [[TMP17]] to i64 264 // IR-NEXT: [[ARRAYIDX12:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARRAYIDX]], i64 0, i64 [[IDXPROM11]] 265 // IR-NEXT: [[TMP18:%.*]] = load i32, ptr [[ARRAYIDX12]], align 4, !llvm.access.group [[ACC_GRP3]] 266 // IR-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP18]], [[TMP15]] 267 // IR-NEXT: store i32 [[ADD13]], ptr [[ARRAYIDX12]], align 4, !llvm.access.group [[ACC_GRP3]] 268 // IR-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] 269 // IR: omp.body.continue: 270 // IR-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] 271 // IR: omp.inner.for.inc: 272 // IR-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 273 // IR-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP19]], 1 274 // IR-NEXT: store i32 [[ADD14]], ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 275 // IR-NEXT: br label [[OMP_INNER_FOR_COND]], !llvm.loop [[LOOP4:![0-9]+]] 276 // IR: omp.inner.for.end: 277 // IR-NEXT: br label [[OMP_LOOP_EXIT:%.*]] 278 // IR: omp.loop.exit: 279 // IR-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 280 // IR-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 281 // IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) 282 // IR-NEXT: [[TMP22:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 283 // IR-NEXT: store ptr [[SUM4]], ptr [[TMP22]], align 8 284 // IR-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 285 // IR-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 286 // IR-NEXT: [[TMP25:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) 287 // IR-NEXT: switch i32 [[TMP25]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ 288 // IR-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] 289 // IR-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] 290 // IR-NEXT: ] 291 // IR: .omp.reduction.case1: 292 // IR-NEXT: [[TMP26:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 293 // IR-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP1]], [[TMP26]] 294 // IR-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE19:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 295 // IR: omp.arraycpy.body: 296 // IR-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[SUM4]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 297 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST15:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT17:%.*]], [[OMP_ARRAYCPY_BODY]] ] 298 // IR-NEXT: [[TMP27:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST15]], align 4 299 // IR-NEXT: [[TMP28:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 300 // IR-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP27]], [[TMP28]] 301 // IR-NEXT: store i32 [[ADD16]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST15]], align 4 302 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT17]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST15]], i32 1 303 // IR-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 304 // IR-NEXT: [[OMP_ARRAYCPY_DONE18:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT17]], [[TMP26]] 305 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE18]], label [[OMP_ARRAYCPY_DONE19]], label [[OMP_ARRAYCPY_BODY]] 306 // IR: omp.arraycpy.done19: 307 // IR-NEXT: call void @__kmpc_end_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], ptr @.gomp_critical_user_.reduction.var) 308 // IR-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 309 // IR: .omp.reduction.case2: 310 // IR-NEXT: [[TMP29:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 311 // IR-NEXT: [[OMP_ARRAYCPY_ISEMPTY20:%.*]] = icmp eq ptr [[TMP1]], [[TMP29]] 312 // IR-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY20]], label [[OMP_ARRAYCPY_DONE27:%.*]], label [[OMP_ARRAYCPY_BODY21:%.*]] 313 // IR: omp.arraycpy.body21: 314 // IR-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST22:%.*]] = phi ptr [ [[SUM4]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT25:%.*]], [[OMP_ARRAYCPY_BODY21]] ] 315 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST23:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT24:%.*]], [[OMP_ARRAYCPY_BODY21]] ] 316 // IR-NEXT: [[TMP30:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST22]], align 4 317 // IR-NEXT: [[TMP31:%.*]] = atomicrmw add ptr [[OMP_ARRAYCPY_DESTELEMENTPAST23]], i32 [[TMP30]] monotonic, align 4 318 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT24]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST23]], i32 1 319 // IR-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT25]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST22]], i32 1 320 // IR-NEXT: [[OMP_ARRAYCPY_DONE26:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT24]], [[TMP29]] 321 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE26]], label [[OMP_ARRAYCPY_DONE27]], label [[OMP_ARRAYCPY_BODY21]] 322 // IR: omp.arraycpy.done27: 323 // IR-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 324 // IR: .omp.reduction.default: 325 // IR-NEXT: [[TMP32:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 326 // IR-NEXT: [[TMP33:%.*]] = icmp ne i32 [[TMP32]], 0 327 // IR-NEXT: br i1 [[TMP33]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] 328 // IR: .omp.lastprivate.then: 329 // IR-NEXT: store i32 10, ptr [[J3]], align 4 330 // IR-NEXT: [[TMP34:%.*]] = load i32, ptr [[J3]], align 4 331 // IR-NEXT: store i32 [[TMP34]], ptr [[TMP0]], align 4 332 // IR-NEXT: br label [[DOTOMP_LASTPRIVATE_DONE]] 333 // IR: .omp.lastprivate.done: 334 // IR-NEXT: ret void 335 // 336 // 337 // IR-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func 338 // IR-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { 339 // IR-NEXT: entry: 340 // IR-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 341 // IR-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 342 // IR-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 343 // IR-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 344 // IR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8 345 // IR-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 346 // IR-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0 347 // IR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 348 // IR-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0 349 // IR-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 350 // IR-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[TMP7]], i64 100 351 // IR-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP7]], [[TMP8]] 352 // IR-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE2:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 353 // IR: omp.arraycpy.body: 354 // IR-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP5]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 355 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP7]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 356 // IR-NEXT: [[TMP9:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 357 // IR-NEXT: [[TMP10:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 358 // IR-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] 359 // IR-NEXT: store i32 [[ADD]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 360 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 361 // IR-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 362 // IR-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP8]] 363 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE2]], label [[OMP_ARRAYCPY_BODY]] 364 // IR: omp.arraycpy.done2: 365 // IR-NEXT: ret void 366 // 367 // 368 // IR-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined.omp.reduction.reduction_func 369 // IR-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR3]] { 370 // IR-NEXT: entry: 371 // IR-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 372 // IR-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 373 // IR-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 374 // IR-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 375 // IR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8 376 // IR-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 377 // IR-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0 378 // IR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 379 // IR-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0 380 // IR-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 381 // IR-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[TMP7]], i64 100 382 // IR-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP7]], [[TMP8]] 383 // IR-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE2:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 384 // IR: omp.arraycpy.body: 385 // IR-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP5]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 386 // IR-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP7]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 387 // IR-NEXT: [[TMP9:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 388 // IR-NEXT: [[TMP10:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 389 // IR-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] 390 // IR-NEXT: store i32 [[ADD]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 391 // IR-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 392 // IR-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 393 // IR-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP8]] 394 // IR-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE2]], label [[OMP_ARRAYCPY_BODY]] 395 // IR: omp.arraycpy.done2: 396 // IR-NEXT: ret void 397 // 398 // 399 // IR-PCH-LABEL: define {{[^@]+}}@_Z3foov 400 // IR-PCH-SAME: () #[[ATTR0:[0-9]+]] { 401 // IR-PCH-NEXT: entry: 402 // IR-PCH-NEXT: [[I:%.*]] = alloca i32, align 4 403 // IR-PCH-NEXT: [[J:%.*]] = alloca i32, align 4 404 // IR-PCH-NEXT: [[SUM:%.*]] = alloca [10 x [10 x i32]], align 16 405 // IR-PCH-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB4:[0-9]+]], i32 2, ptr @_Z3foov.omp_outlined, ptr [[J]], ptr [[SUM]]) 406 // IR-PCH-NEXT: ret i32 0 407 // 408 // 409 // IR-PCH-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined 410 // IR-PCH-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[J:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[SUM:%.*]]) #[[ATTR1:[0-9]+]] { 411 // IR-PCH-NEXT: entry: 412 // IR-PCH-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 413 // IR-PCH-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 414 // IR-PCH-NEXT: [[J_ADDR:%.*]] = alloca ptr, align 8 415 // IR-PCH-NEXT: [[SUM_ADDR:%.*]] = alloca ptr, align 8 416 // IR-PCH-NEXT: [[SUM1:%.*]] = alloca [10 x [10 x i32]], align 16 417 // IR-PCH-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 418 // IR-PCH-NEXT: [[TMP:%.*]] = alloca i32, align 4 419 // IR-PCH-NEXT: [[_TMP2:%.*]] = alloca i32, align 4 420 // IR-PCH-NEXT: [[DOTOMP_COMB_LB:%.*]] = alloca i32, align 4 421 // IR-PCH-NEXT: [[DOTOMP_COMB_UB:%.*]] = alloca i32, align 4 422 // IR-PCH-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 423 // IR-PCH-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 424 // IR-PCH-NEXT: [[J3:%.*]] = alloca i32, align 4 425 // IR-PCH-NEXT: [[I:%.*]] = alloca i32, align 4 426 // IR-PCH-NEXT: [[J4:%.*]] = alloca i32, align 4 427 // IR-PCH-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8 428 // IR-PCH-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 429 // IR-PCH-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 430 // IR-PCH-NEXT: store ptr [[J]], ptr [[J_ADDR]], align 8 431 // IR-PCH-NEXT: store ptr [[SUM]], ptr [[SUM_ADDR]], align 8 432 // IR-PCH-NEXT: [[TMP0:%.*]] = load ptr, ptr [[J_ADDR]], align 8 433 // IR-PCH-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SUM_ADDR]], align 8 434 // IR-PCH-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [10 x [10 x i32]], ptr [[SUM1]], i32 0, i32 0, i32 0 435 // IR-PCH-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[ARRAY_BEGIN]], i64 100 436 // IR-PCH-NEXT: [[OMP_ARRAYINIT_ISEMPTY:%.*]] = icmp eq ptr [[ARRAY_BEGIN]], [[TMP2]] 437 // IR-PCH-NEXT: br i1 [[OMP_ARRAYINIT_ISEMPTY]], label [[OMP_ARRAYINIT_DONE:%.*]], label [[OMP_ARRAYINIT_BODY:%.*]] 438 // IR-PCH: omp.arrayinit.body: 439 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYINIT_BODY]] ] 440 // IR-PCH-NEXT: store i32 0, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 441 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 442 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP2]] 443 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYINIT_DONE]], label [[OMP_ARRAYINIT_BODY]] 444 // IR-PCH: omp.arrayinit.done: 445 // IR-PCH-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4 446 // IR-PCH-NEXT: store i32 99, ptr [[DOTOMP_COMB_UB]], align 4 447 // IR-PCH-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 448 // IR-PCH-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 449 // IR-PCH-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 450 // IR-PCH-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 451 // IR-PCH-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB1:[0-9]+]], i32 [[TMP4]], i32 92, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_COMB_LB]], ptr [[DOTOMP_COMB_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) 452 // IR-PCH-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 453 // IR-PCH-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 99 454 // IR-PCH-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 455 // IR-PCH: cond.true: 456 // IR-PCH-NEXT: br label [[COND_END:%.*]] 457 // IR-PCH: cond.false: 458 // IR-PCH-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 459 // IR-PCH-NEXT: br label [[COND_END]] 460 // IR-PCH: cond.end: 461 // IR-PCH-NEXT: [[COND:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[TMP6]], [[COND_FALSE]] ] 462 // IR-PCH-NEXT: store i32 [[COND]], ptr [[DOTOMP_COMB_UB]], align 4 463 // IR-PCH-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_COMB_LB]], align 4 464 // IR-PCH-NEXT: store i32 [[TMP7]], ptr [[DOTOMP_IV]], align 4 465 // IR-PCH-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] 466 // IR-PCH: omp.inner.for.cond: 467 // IR-PCH-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 468 // IR-PCH-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 469 // IR-PCH-NEXT: [[CMP5:%.*]] = icmp sle i32 [[TMP8]], [[TMP9]] 470 // IR-PCH-NEXT: br i1 [[CMP5]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] 471 // IR-PCH: omp.inner.for.body: 472 // IR-PCH-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_COMB_LB]], align 4 473 // IR-PCH-NEXT: [[TMP11:%.*]] = zext i32 [[TMP10]] to i64 474 // IR-PCH-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTOMP_COMB_UB]], align 4 475 // IR-PCH-NEXT: [[TMP13:%.*]] = zext i32 [[TMP12]] to i64 476 // IR-PCH-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB4]], i32 4, ptr @_Z3foov.omp_outlined.omp_outlined, i64 [[TMP11]], i64 [[TMP13]], ptr [[J3]], ptr [[SUM1]]) 477 // IR-PCH-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] 478 // IR-PCH: omp.inner.for.inc: 479 // IR-PCH-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4 480 // IR-PCH-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTOMP_STRIDE]], align 4 481 // IR-PCH-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP14]], [[TMP15]] 482 // IR-PCH-NEXT: store i32 [[ADD]], ptr [[DOTOMP_IV]], align 4 483 // IR-PCH-NEXT: br label [[OMP_INNER_FOR_COND]] 484 // IR-PCH: omp.inner.for.end: 485 // IR-PCH-NEXT: br label [[OMP_LOOP_EXIT:%.*]] 486 // IR-PCH: omp.loop.exit: 487 // IR-PCH-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 488 // IR-PCH-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 489 // IR-PCH-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) 490 // IR-PCH-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 491 // IR-PCH-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 492 // IR-PCH-NEXT: br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] 493 // IR-PCH: .omp.lastprivate.then: 494 // IR-PCH-NEXT: store i32 10, ptr [[J3]], align 4 495 // IR-PCH-NEXT: [[TMP20:%.*]] = load i32, ptr [[J3]], align 4 496 // IR-PCH-NEXT: store i32 [[TMP20]], ptr [[TMP0]], align 4 497 // IR-PCH-NEXT: br label [[DOTOMP_LASTPRIVATE_DONE]] 498 // IR-PCH: .omp.lastprivate.done: 499 // IR-PCH-NEXT: [[TMP21:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 500 // IR-PCH-NEXT: store ptr [[SUM1]], ptr [[TMP21]], align 8 501 // IR-PCH-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 502 // IR-PCH-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 503 // IR-PCH-NEXT: [[TMP24:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP23]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) 504 // IR-PCH-NEXT: switch i32 [[TMP24]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ 505 // IR-PCH-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] 506 // IR-PCH-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] 507 // IR-PCH-NEXT: ] 508 // IR-PCH: .omp.reduction.case1: 509 // IR-PCH-NEXT: [[TMP25:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 510 // IR-PCH-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP1]], [[TMP25]] 511 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE10:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 512 // IR-PCH: omp.arraycpy.body: 513 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[SUM1]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 514 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST6:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT8:%.*]], [[OMP_ARRAYCPY_BODY]] ] 515 // IR-PCH-NEXT: [[TMP26:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST6]], align 4 516 // IR-PCH-NEXT: [[TMP27:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 517 // IR-PCH-NEXT: [[ADD7:%.*]] = add nsw i32 [[TMP26]], [[TMP27]] 518 // IR-PCH-NEXT: store i32 [[ADD7]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST6]], align 4 519 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT8]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST6]], i32 1 520 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 521 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE9:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT8]], [[TMP25]] 522 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE9]], label [[OMP_ARRAYCPY_DONE10]], label [[OMP_ARRAYCPY_BODY]] 523 // IR-PCH: omp.arraycpy.done10: 524 // IR-PCH-NEXT: call void @__kmpc_end_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP23]], ptr @.gomp_critical_user_.reduction.var) 525 // IR-PCH-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 526 // IR-PCH: .omp.reduction.case2: 527 // IR-PCH-NEXT: [[TMP28:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 528 // IR-PCH-NEXT: [[OMP_ARRAYCPY_ISEMPTY11:%.*]] = icmp eq ptr [[TMP1]], [[TMP28]] 529 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY11]], label [[OMP_ARRAYCPY_DONE18:%.*]], label [[OMP_ARRAYCPY_BODY12:%.*]] 530 // IR-PCH: omp.arraycpy.body12: 531 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST13:%.*]] = phi ptr [ [[SUM1]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT16:%.*]], [[OMP_ARRAYCPY_BODY12]] ] 532 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST14:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT15:%.*]], [[OMP_ARRAYCPY_BODY12]] ] 533 // IR-PCH-NEXT: [[TMP29:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST13]], align 4 534 // IR-PCH-NEXT: [[TMP30:%.*]] = atomicrmw add ptr [[OMP_ARRAYCPY_DESTELEMENTPAST14]], i32 [[TMP29]] monotonic, align 4 535 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT15]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST14]], i32 1 536 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT16]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST13]], i32 1 537 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE17:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT15]], [[TMP28]] 538 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE17]], label [[OMP_ARRAYCPY_DONE18]], label [[OMP_ARRAYCPY_BODY12]] 539 // IR-PCH: omp.arraycpy.done18: 540 // IR-PCH-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 541 // IR-PCH: .omp.reduction.default: 542 // IR-PCH-NEXT: ret void 543 // 544 // 545 // IR-PCH-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined.omp_outlined 546 // IR-PCH-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[J:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[SUM:%.*]]) #[[ATTR1]] { 547 // IR-PCH-NEXT: entry: 548 // IR-PCH-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 549 // IR-PCH-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 550 // IR-PCH-NEXT: [[DOTPREVIOUS_LB__ADDR:%.*]] = alloca i64, align 8 551 // IR-PCH-NEXT: [[DOTPREVIOUS_UB__ADDR:%.*]] = alloca i64, align 8 552 // IR-PCH-NEXT: [[J_ADDR:%.*]] = alloca ptr, align 8 553 // IR-PCH-NEXT: [[SUM_ADDR:%.*]] = alloca ptr, align 8 554 // IR-PCH-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 555 // IR-PCH-NEXT: [[TMP:%.*]] = alloca i32, align 4 556 // IR-PCH-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 557 // IR-PCH-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 558 // IR-PCH-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 559 // IR-PCH-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 560 // IR-PCH-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 561 // IR-PCH-NEXT: [[J3:%.*]] = alloca i32, align 4 562 // IR-PCH-NEXT: [[SUM4:%.*]] = alloca [10 x [10 x i32]], align 16 563 // IR-PCH-NEXT: [[I:%.*]] = alloca i32, align 4 564 // IR-PCH-NEXT: [[J5:%.*]] = alloca i32, align 4 565 // IR-PCH-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8 566 // IR-PCH-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 567 // IR-PCH-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 568 // IR-PCH-NEXT: store i64 [[DOTPREVIOUS_LB_]], ptr [[DOTPREVIOUS_LB__ADDR]], align 8 569 // IR-PCH-NEXT: store i64 [[DOTPREVIOUS_UB_]], ptr [[DOTPREVIOUS_UB__ADDR]], align 8 570 // IR-PCH-NEXT: store ptr [[J]], ptr [[J_ADDR]], align 8 571 // IR-PCH-NEXT: store ptr [[SUM]], ptr [[SUM_ADDR]], align 8 572 // IR-PCH-NEXT: [[TMP0:%.*]] = load ptr, ptr [[J_ADDR]], align 8 573 // IR-PCH-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SUM_ADDR]], align 8 574 // IR-PCH-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 575 // IR-PCH-NEXT: store i32 99, ptr [[DOTOMP_UB]], align 4 576 // IR-PCH-NEXT: [[TMP2:%.*]] = load i64, ptr [[DOTPREVIOUS_LB__ADDR]], align 8 577 // IR-PCH-NEXT: [[CONV:%.*]] = trunc i64 [[TMP2]] to i32 578 // IR-PCH-NEXT: [[TMP3:%.*]] = load i64, ptr [[DOTPREVIOUS_UB__ADDR]], align 8 579 // IR-PCH-NEXT: [[CONV2:%.*]] = trunc i64 [[TMP3]] to i32 580 // IR-PCH-NEXT: store i32 [[CONV]], ptr [[DOTOMP_LB]], align 4 581 // IR-PCH-NEXT: store i32 [[CONV2]], ptr [[DOTOMP_UB]], align 4 582 // IR-PCH-NEXT: store i32 1, ptr [[DOTOMP_STRIDE]], align 4 583 // IR-PCH-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 584 // IR-PCH-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [10 x [10 x i32]], ptr [[SUM4]], i32 0, i32 0, i32 0 585 // IR-PCH-NEXT: [[TMP4:%.*]] = getelementptr i32, ptr [[ARRAY_BEGIN]], i64 100 586 // IR-PCH-NEXT: [[OMP_ARRAYINIT_ISEMPTY:%.*]] = icmp eq ptr [[ARRAY_BEGIN]], [[TMP4]] 587 // IR-PCH-NEXT: br i1 [[OMP_ARRAYINIT_ISEMPTY]], label [[OMP_ARRAYINIT_DONE:%.*]], label [[OMP_ARRAYINIT_BODY:%.*]] 588 // IR-PCH: omp.arrayinit.body: 589 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYINIT_BODY]] ] 590 // IR-PCH-NEXT: store i32 0, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 591 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 592 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP4]] 593 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYINIT_DONE]], label [[OMP_ARRAYINIT_BODY]] 594 // IR-PCH: omp.arrayinit.done: 595 // IR-PCH-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 596 // IR-PCH-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4 597 // IR-PCH-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) 598 // IR-PCH-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 599 // IR-PCH-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP7]], 99 600 // IR-PCH-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 601 // IR-PCH: cond.true: 602 // IR-PCH-NEXT: br label [[COND_END:%.*]] 603 // IR-PCH: cond.false: 604 // IR-PCH-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 605 // IR-PCH-NEXT: br label [[COND_END]] 606 // IR-PCH: cond.end: 607 // IR-PCH-NEXT: [[COND:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[TMP8]], [[COND_FALSE]] ] 608 // IR-PCH-NEXT: store i32 [[COND]], ptr [[DOTOMP_UB]], align 4 609 // IR-PCH-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 610 // IR-PCH-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 611 // IR-PCH-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] 612 // IR-PCH: omp.inner.for.cond: 613 // IR-PCH-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3:![0-9]+]] 614 // IR-PCH-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4, !llvm.access.group [[ACC_GRP3]] 615 // IR-PCH-NEXT: [[CMP6:%.*]] = icmp sle i32 [[TMP10]], [[TMP11]] 616 // IR-PCH-NEXT: br i1 [[CMP6]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_END:%.*]] 617 // IR-PCH: omp.inner.for.body: 618 // IR-PCH-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 619 // IR-PCH-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP12]], 10 620 // IR-PCH-NEXT: [[MUL:%.*]] = mul nsw i32 [[DIV]], 1 621 // IR-PCH-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] 622 // IR-PCH-NEXT: store i32 [[ADD]], ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] 623 // IR-PCH-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 624 // IR-PCH-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 625 // IR-PCH-NEXT: [[DIV7:%.*]] = sdiv i32 [[TMP14]], 10 626 // IR-PCH-NEXT: [[MUL8:%.*]] = mul nsw i32 [[DIV7]], 10 627 // IR-PCH-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP13]], [[MUL8]] 628 // IR-PCH-NEXT: [[MUL9:%.*]] = mul nsw i32 [[SUB]], 1 629 // IR-PCH-NEXT: [[ADD10:%.*]] = add nsw i32 0, [[MUL9]] 630 // IR-PCH-NEXT: store i32 [[ADD10]], ptr [[J3]], align 4, !llvm.access.group [[ACC_GRP3]] 631 // IR-PCH-NEXT: [[TMP15:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] 632 // IR-PCH-NEXT: [[TMP16:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] 633 // IR-PCH-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP16]] to i64 634 // IR-PCH-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x [10 x i32]], ptr [[SUM4]], i64 0, i64 [[IDXPROM]] 635 // IR-PCH-NEXT: [[TMP17:%.*]] = load i32, ptr [[J3]], align 4, !llvm.access.group [[ACC_GRP3]] 636 // IR-PCH-NEXT: [[IDXPROM11:%.*]] = sext i32 [[TMP17]] to i64 637 // IR-PCH-NEXT: [[ARRAYIDX12:%.*]] = getelementptr inbounds [10 x i32], ptr [[ARRAYIDX]], i64 0, i64 [[IDXPROM11]] 638 // IR-PCH-NEXT: [[TMP18:%.*]] = load i32, ptr [[ARRAYIDX12]], align 4, !llvm.access.group [[ACC_GRP3]] 639 // IR-PCH-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP18]], [[TMP15]] 640 // IR-PCH-NEXT: store i32 [[ADD13]], ptr [[ARRAYIDX12]], align 4, !llvm.access.group [[ACC_GRP3]] 641 // IR-PCH-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] 642 // IR-PCH: omp.body.continue: 643 // IR-PCH-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] 644 // IR-PCH: omp.inner.for.inc: 645 // IR-PCH-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 646 // IR-PCH-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP19]], 1 647 // IR-PCH-NEXT: store i32 [[ADD14]], ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] 648 // IR-PCH-NEXT: br label [[OMP_INNER_FOR_COND]], !llvm.loop [[LOOP4:![0-9]+]] 649 // IR-PCH: omp.inner.for.end: 650 // IR-PCH-NEXT: br label [[OMP_LOOP_EXIT:%.*]] 651 // IR-PCH: omp.loop.exit: 652 // IR-PCH-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 653 // IR-PCH-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 654 // IR-PCH-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) 655 // IR-PCH-NEXT: [[TMP22:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 656 // IR-PCH-NEXT: store ptr [[SUM4]], ptr [[TMP22]], align 8 657 // IR-PCH-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 658 // IR-PCH-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 659 // IR-PCH-NEXT: [[TMP25:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) 660 // IR-PCH-NEXT: switch i32 [[TMP25]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ 661 // IR-PCH-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] 662 // IR-PCH-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] 663 // IR-PCH-NEXT: ] 664 // IR-PCH: .omp.reduction.case1: 665 // IR-PCH-NEXT: [[TMP26:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 666 // IR-PCH-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP1]], [[TMP26]] 667 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE19:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 668 // IR-PCH: omp.arraycpy.body: 669 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[SUM4]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 670 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST15:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE1]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT17:%.*]], [[OMP_ARRAYCPY_BODY]] ] 671 // IR-PCH-NEXT: [[TMP27:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST15]], align 4 672 // IR-PCH-NEXT: [[TMP28:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 673 // IR-PCH-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP27]], [[TMP28]] 674 // IR-PCH-NEXT: store i32 [[ADD16]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST15]], align 4 675 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT17]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST15]], i32 1 676 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 677 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE18:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT17]], [[TMP26]] 678 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE18]], label [[OMP_ARRAYCPY_DONE19]], label [[OMP_ARRAYCPY_BODY]] 679 // IR-PCH: omp.arraycpy.done19: 680 // IR-PCH-NEXT: call void @__kmpc_end_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], ptr @.gomp_critical_user_.reduction.var) 681 // IR-PCH-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 682 // IR-PCH: .omp.reduction.case2: 683 // IR-PCH-NEXT: [[TMP29:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 684 // IR-PCH-NEXT: [[OMP_ARRAYCPY_ISEMPTY20:%.*]] = icmp eq ptr [[TMP1]], [[TMP29]] 685 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY20]], label [[OMP_ARRAYCPY_DONE27:%.*]], label [[OMP_ARRAYCPY_BODY21:%.*]] 686 // IR-PCH: omp.arraycpy.body21: 687 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST22:%.*]] = phi ptr [ [[SUM4]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT25:%.*]], [[OMP_ARRAYCPY_BODY21]] ] 688 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST23:%.*]] = phi ptr [ [[TMP1]], [[DOTOMP_REDUCTION_CASE2]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT24:%.*]], [[OMP_ARRAYCPY_BODY21]] ] 689 // IR-PCH-NEXT: [[TMP30:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST22]], align 4 690 // IR-PCH-NEXT: [[TMP31:%.*]] = atomicrmw add ptr [[OMP_ARRAYCPY_DESTELEMENTPAST23]], i32 [[TMP30]] monotonic, align 4 691 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT24]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST23]], i32 1 692 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT25]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST22]], i32 1 693 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE26:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT24]], [[TMP29]] 694 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE26]], label [[OMP_ARRAYCPY_DONE27]], label [[OMP_ARRAYCPY_BODY21]] 695 // IR-PCH: omp.arraycpy.done27: 696 // IR-PCH-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] 697 // IR-PCH: .omp.reduction.default: 698 // IR-PCH-NEXT: [[TMP32:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 699 // IR-PCH-NEXT: [[TMP33:%.*]] = icmp ne i32 [[TMP32]], 0 700 // IR-PCH-NEXT: br i1 [[TMP33]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] 701 // IR-PCH: .omp.lastprivate.then: 702 // IR-PCH-NEXT: store i32 10, ptr [[J3]], align 4 703 // IR-PCH-NEXT: [[TMP34:%.*]] = load i32, ptr [[J3]], align 4 704 // IR-PCH-NEXT: store i32 [[TMP34]], ptr [[TMP0]], align 4 705 // IR-PCH-NEXT: br label [[DOTOMP_LASTPRIVATE_DONE]] 706 // IR-PCH: .omp.lastprivate.done: 707 // IR-PCH-NEXT: ret void 708 // 709 // 710 // IR-PCH-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func 711 // IR-PCH-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { 712 // IR-PCH-NEXT: entry: 713 // IR-PCH-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 714 // IR-PCH-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 715 // IR-PCH-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 716 // IR-PCH-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 717 // IR-PCH-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8 718 // IR-PCH-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 719 // IR-PCH-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0 720 // IR-PCH-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 721 // IR-PCH-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0 722 // IR-PCH-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 723 // IR-PCH-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[TMP7]], i64 100 724 // IR-PCH-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP7]], [[TMP8]] 725 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE2:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 726 // IR-PCH: omp.arraycpy.body: 727 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP5]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 728 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP7]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 729 // IR-PCH-NEXT: [[TMP9:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 730 // IR-PCH-NEXT: [[TMP10:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 731 // IR-PCH-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] 732 // IR-PCH-NEXT: store i32 [[ADD]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 733 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 734 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 735 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP8]] 736 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE2]], label [[OMP_ARRAYCPY_BODY]] 737 // IR-PCH: omp.arraycpy.done2: 738 // IR-PCH-NEXT: ret void 739 // 740 // 741 // IR-PCH-LABEL: define {{[^@]+}}@_Z3foov.omp_outlined.omp.reduction.reduction_func 742 // IR-PCH-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR3]] { 743 // IR-PCH-NEXT: entry: 744 // IR-PCH-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 745 // IR-PCH-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 746 // IR-PCH-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 747 // IR-PCH-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 748 // IR-PCH-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8 749 // IR-PCH-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 750 // IR-PCH-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP3]], i64 0, i64 0 751 // IR-PCH-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 752 // IR-PCH-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[TMP2]], i64 0, i64 0 753 // IR-PCH-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 754 // IR-PCH-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[TMP7]], i64 100 755 // IR-PCH-NEXT: [[OMP_ARRAYCPY_ISEMPTY:%.*]] = icmp eq ptr [[TMP7]], [[TMP8]] 756 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_ISEMPTY]], label [[OMP_ARRAYCPY_DONE2:%.*]], label [[OMP_ARRAYCPY_BODY:%.*]] 757 // IR-PCH: omp.arraycpy.body: 758 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP5]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 759 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP7]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] 760 // IR-PCH-NEXT: [[TMP9:%.*]] = load i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 761 // IR-PCH-NEXT: [[TMP10:%.*]] = load i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], align 4 762 // IR-PCH-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] 763 // IR-PCH-NEXT: store i32 [[ADD]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], align 4 764 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 765 // IR-PCH-NEXT: [[OMP_ARRAYCPY_SRC_ELEMENT]] = getelementptr i32, ptr [[OMP_ARRAYCPY_SRCELEMENTPAST]], i32 1 766 // IR-PCH-NEXT: [[OMP_ARRAYCPY_DONE:%.*]] = icmp eq ptr [[OMP_ARRAYCPY_DEST_ELEMENT]], [[TMP8]] 767 // IR-PCH-NEXT: br i1 [[OMP_ARRAYCPY_DONE]], label [[OMP_ARRAYCPY_DONE2]], label [[OMP_ARRAYCPY_BODY]] 768 // IR-PCH: omp.arraycpy.done2: 769 // IR-PCH-NEXT: ret void 770 // 771