1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6;
7;    void bar(int, float, double);
8;
9;    void foo(int N) {
10;      float p = 3;
11;      double q = 5;
12;      N = 7;
13;
14;    #pragma omp parallel for firstprivate(q)
15;      for (int i = 2; i < N; i++) {
16;        bar(i, p, q);
17;      }
18;    }
19;
20; Verify the constant value of q is propagated into the outlined function.
21;
22target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
23
24%struct.ident_t = type { i32, i32, i32, i32, i8* }
25
26@.str = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
27@0 = private unnamed_addr global %struct.ident_t { i32 0, i32 514, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
28@1 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
29
30;.
31; CHECK: @[[_STR:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [23 x i8] c"
32; CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr global [[STRUCT_IDENT_T:%.*]] { i32 0, i32 514, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
33; CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr global [[STRUCT_IDENT_T:%.*]] { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
34;.
35define dso_local void @foo(i32 %N) {
36; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@foo
37; IS__TUNIT_OPM-SAME: (i32 [[N:%.*]]) {
38; IS__TUNIT_OPM-NEXT:  entry:
39; IS__TUNIT_OPM-NEXT:    [[N_ADDR:%.*]] = alloca i32, align 4
40; IS__TUNIT_OPM-NEXT:    [[P:%.*]] = alloca float, align 4
41; IS__TUNIT_OPM-NEXT:    store i32 [[N]], i32* [[N_ADDR]], align 4
42; IS__TUNIT_OPM-NEXT:    store i32 7, i32* [[N_ADDR]], align 4
43; IS__TUNIT_OPM-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 noundef 3, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* noalias nocapture nofree nonnull readnone align 4 dereferenceable(4) undef, i64 undef)
44; IS__TUNIT_OPM-NEXT:    ret void
45;
46; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@foo
47; IS__TUNIT_NPM-SAME: (i32 [[N:%.*]]) {
48; IS__TUNIT_NPM-NEXT:  entry:
49; IS__TUNIT_NPM-NEXT:    [[N_ADDR:%.*]] = alloca i32, align 4
50; IS__TUNIT_NPM-NEXT:    [[P:%.*]] = alloca float, align 4
51; IS__TUNIT_NPM-NEXT:    store i32 [[N]], i32* [[N_ADDR]], align 4
52; IS__TUNIT_NPM-NEXT:    store i32 7, i32* [[N_ADDR]], align 4
53; IS__TUNIT_NPM-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 noundef 3, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* noalias nocapture nofree nonnull readnone align 4 dereferenceable(4) undef, i64 undef)
54; IS__TUNIT_NPM-NEXT:    ret void
55;
56; IS__CGSCC____-LABEL: define {{[^@]+}}@foo
57; IS__CGSCC____-SAME: (i32 [[N:%.*]]) {
58; IS__CGSCC____-NEXT:  entry:
59; IS__CGSCC____-NEXT:    [[N_ADDR:%.*]] = alloca i32, align 4
60; IS__CGSCC____-NEXT:    [[P:%.*]] = alloca float, align 4
61; IS__CGSCC____-NEXT:    store i32 [[N]], i32* [[N_ADDR]], align 4
62; IS__CGSCC____-NEXT:    store float 3.000000e+00, float* [[P]], align 4
63; IS__CGSCC____-NEXT:    store i32 7, i32* [[N_ADDR]], align 4
64; IS__CGSCC____-NEXT:    call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB1]], i32 noundef 3, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nofree noundef nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]], i64 noundef 4617315517961601024)
65; IS__CGSCC____-NEXT:    ret void
66;
67entry:
68  %N.addr = alloca i32, align 4
69  %p = alloca float, align 4
70  store i32 %N, i32* %N.addr, align 4
71  store float 3.000000e+00, float* %p, align 4
72  store i32 7, i32* %N.addr, align 4
73  call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nonnull %N.addr, float* nonnull %p, i64 4617315517961601024)
74  ret void
75}
76
77define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %N, float* dereferenceable(4) %p, i64 %q) {
78; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@.omp_outlined.
79; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* noalias nocapture nofree nonnull readnone align 4 dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) {
80; IS__TUNIT_OPM-NEXT:  entry:
81; IS__TUNIT_OPM-NEXT:    [[Q_ADDR:%.*]] = alloca i64, align 8
82; IS__TUNIT_OPM-NEXT:    [[DOTOMP_LB:%.*]] = alloca i32, align 4
83; IS__TUNIT_OPM-NEXT:    [[DOTOMP_UB:%.*]] = alloca i32, align 4
84; IS__TUNIT_OPM-NEXT:    [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
85; IS__TUNIT_OPM-NEXT:    [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
86; IS__TUNIT_OPM-NEXT:    store i64 4617315517961601024, i64* [[Q_ADDR]], align 8
87; IS__TUNIT_OPM-NEXT:    [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double*
88; IS__TUNIT_OPM-NEXT:    [[TMP:%.*]] = load i32, i32* [[N]], align 4
89; IS__TUNIT_OPM-NEXT:    [[SUB3:%.*]] = add nsw i32 [[TMP]], -3
90; IS__TUNIT_OPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2
91; IS__TUNIT_OPM-NEXT:    br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]]
92; IS__TUNIT_OPM:       omp.precond.then:
93; IS__TUNIT_OPM-NEXT:    store i32 0, i32* [[DOTOMP_LB]], align 4
94; IS__TUNIT_OPM-NEXT:    store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4
95; IS__TUNIT_OPM-NEXT:    store i32 1, i32* [[DOTOMP_STRIDE]], align 4
96; IS__TUNIT_OPM-NEXT:    store i32 0, i32* [[DOTOMP_IS_LAST]], align 4
97; IS__TUNIT_OPM-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
98; IS__TUNIT_OPM-NEXT:    call void @__kmpc_for_static_init_4(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP5]], i32 noundef 34, i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 noundef 1, i32 noundef 1)
99; IS__TUNIT_OPM-NEXT:    [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
100; IS__TUNIT_OPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]]
101; IS__TUNIT_OPM-NEXT:    br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
102; IS__TUNIT_OPM:       cond.true:
103; IS__TUNIT_OPM-NEXT:    br label [[COND_END:%.*]]
104; IS__TUNIT_OPM:       cond.false:
105; IS__TUNIT_OPM-NEXT:    [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
106; IS__TUNIT_OPM-NEXT:    br label [[COND_END]]
107; IS__TUNIT_OPM:       cond.end:
108; IS__TUNIT_OPM-NEXT:    [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ]
109; IS__TUNIT_OPM-NEXT:    store i32 [[COND]], i32* [[DOTOMP_UB]], align 4
110; IS__TUNIT_OPM-NEXT:    [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4
111; IS__TUNIT_OPM-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
112; IS__TUNIT_OPM:       omp.inner.for.cond:
113; IS__TUNIT_OPM-NEXT:    [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ]
114; IS__TUNIT_OPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
115; IS__TUNIT_OPM-NEXT:    [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]]
116; IS__TUNIT_OPM-NEXT:    br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]]
117; IS__TUNIT_OPM:       omp.inner.for.cond.cleanup:
118; IS__TUNIT_OPM-NEXT:    br label [[OMP_INNER_FOR_END:%.*]]
119; IS__TUNIT_OPM:       omp.inner.for.body:
120; IS__TUNIT_OPM-NEXT:    [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2
121; IS__TUNIT_OPM-NEXT:    [[TMP11:%.*]] = load double, double* [[CONV]], align 8
122; IS__TUNIT_OPM-NEXT:    call void @bar(i32 [[ADD10]], float 3.000000e+00, double [[TMP11]])
123; IS__TUNIT_OPM-NEXT:    br label [[OMP_BODY_CONTINUE:%.*]]
124; IS__TUNIT_OPM:       omp.body.continue:
125; IS__TUNIT_OPM-NEXT:    br label [[OMP_INNER_FOR_INC]]
126; IS__TUNIT_OPM:       omp.inner.for.inc:
127; IS__TUNIT_OPM-NEXT:    [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1
128; IS__TUNIT_OPM-NEXT:    br label [[OMP_INNER_FOR_COND]]
129; IS__TUNIT_OPM:       omp.inner.for.end:
130; IS__TUNIT_OPM-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
131; IS__TUNIT_OPM:       omp.loop.exit:
132; IS__TUNIT_OPM-NEXT:    [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
133; IS__TUNIT_OPM-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP12]])
134; IS__TUNIT_OPM-NEXT:    br label [[OMP_PRECOND_END]]
135; IS__TUNIT_OPM:       omp.precond.end:
136; IS__TUNIT_OPM-NEXT:    ret void
137;
138; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@.omp_outlined.
139; IS__TUNIT_NPM-SAME: (i32* noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* noalias nocapture nofree nonnull readnone align 4 dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) {
140; IS__TUNIT_NPM-NEXT:  entry:
141; IS__TUNIT_NPM-NEXT:    [[Q_ADDR:%.*]] = alloca i64, align 8
142; IS__TUNIT_NPM-NEXT:    [[DOTOMP_LB:%.*]] = alloca i32, align 4
143; IS__TUNIT_NPM-NEXT:    [[DOTOMP_UB:%.*]] = alloca i32, align 4
144; IS__TUNIT_NPM-NEXT:    [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
145; IS__TUNIT_NPM-NEXT:    [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
146; IS__TUNIT_NPM-NEXT:    store i64 4617315517961601024, i64* [[Q_ADDR]], align 8
147; IS__TUNIT_NPM-NEXT:    [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double*
148; IS__TUNIT_NPM-NEXT:    [[TMP:%.*]] = load i32, i32* [[N]], align 4
149; IS__TUNIT_NPM-NEXT:    [[SUB3:%.*]] = add nsw i32 [[TMP]], -3
150; IS__TUNIT_NPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2
151; IS__TUNIT_NPM-NEXT:    br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]]
152; IS__TUNIT_NPM:       omp.precond.then:
153; IS__TUNIT_NPM-NEXT:    store i32 0, i32* [[DOTOMP_LB]], align 4
154; IS__TUNIT_NPM-NEXT:    store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4
155; IS__TUNIT_NPM-NEXT:    store i32 1, i32* [[DOTOMP_STRIDE]], align 4
156; IS__TUNIT_NPM-NEXT:    store i32 0, i32* [[DOTOMP_IS_LAST]], align 4
157; IS__TUNIT_NPM-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
158; IS__TUNIT_NPM-NEXT:    call void @__kmpc_for_static_init_4(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP5]], i32 noundef 34, i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 noundef 1, i32 noundef 1)
159; IS__TUNIT_NPM-NEXT:    [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
160; IS__TUNIT_NPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]]
161; IS__TUNIT_NPM-NEXT:    br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
162; IS__TUNIT_NPM:       cond.true:
163; IS__TUNIT_NPM-NEXT:    br label [[COND_END:%.*]]
164; IS__TUNIT_NPM:       cond.false:
165; IS__TUNIT_NPM-NEXT:    [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
166; IS__TUNIT_NPM-NEXT:    br label [[COND_END]]
167; IS__TUNIT_NPM:       cond.end:
168; IS__TUNIT_NPM-NEXT:    [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ]
169; IS__TUNIT_NPM-NEXT:    store i32 [[COND]], i32* [[DOTOMP_UB]], align 4
170; IS__TUNIT_NPM-NEXT:    [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4
171; IS__TUNIT_NPM-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
172; IS__TUNIT_NPM:       omp.inner.for.cond:
173; IS__TUNIT_NPM-NEXT:    [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ]
174; IS__TUNIT_NPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
175; IS__TUNIT_NPM-NEXT:    [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]]
176; IS__TUNIT_NPM-NEXT:    br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]]
177; IS__TUNIT_NPM:       omp.inner.for.cond.cleanup:
178; IS__TUNIT_NPM-NEXT:    br label [[OMP_INNER_FOR_END:%.*]]
179; IS__TUNIT_NPM:       omp.inner.for.body:
180; IS__TUNIT_NPM-NEXT:    [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2
181; IS__TUNIT_NPM-NEXT:    [[TMP11:%.*]] = load double, double* [[CONV]], align 8
182; IS__TUNIT_NPM-NEXT:    call void @bar(i32 [[ADD10]], float 3.000000e+00, double [[TMP11]])
183; IS__TUNIT_NPM-NEXT:    br label [[OMP_BODY_CONTINUE:%.*]]
184; IS__TUNIT_NPM:       omp.body.continue:
185; IS__TUNIT_NPM-NEXT:    br label [[OMP_INNER_FOR_INC]]
186; IS__TUNIT_NPM:       omp.inner.for.inc:
187; IS__TUNIT_NPM-NEXT:    [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1
188; IS__TUNIT_NPM-NEXT:    br label [[OMP_INNER_FOR_COND]]
189; IS__TUNIT_NPM:       omp.inner.for.end:
190; IS__TUNIT_NPM-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
191; IS__TUNIT_NPM:       omp.loop.exit:
192; IS__TUNIT_NPM-NEXT:    [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
193; IS__TUNIT_NPM-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP12]])
194; IS__TUNIT_NPM-NEXT:    br label [[OMP_PRECOND_END]]
195; IS__TUNIT_NPM:       omp.precond.end:
196; IS__TUNIT_NPM-NEXT:    ret void
197;
198; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@.omp_outlined.
199; IS__CGSCC_OPM-SAME: (i32* noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) {
200; IS__CGSCC_OPM-NEXT:  entry:
201; IS__CGSCC_OPM-NEXT:    [[Q_ADDR:%.*]] = alloca i64, align 8
202; IS__CGSCC_OPM-NEXT:    [[DOTOMP_LB:%.*]] = alloca i32, align 4
203; IS__CGSCC_OPM-NEXT:    [[DOTOMP_UB:%.*]] = alloca i32, align 4
204; IS__CGSCC_OPM-NEXT:    [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
205; IS__CGSCC_OPM-NEXT:    [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
206; IS__CGSCC_OPM-NEXT:    store i64 4617315517961601024, i64* [[Q_ADDR]], align 8
207; IS__CGSCC_OPM-NEXT:    [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double*
208; IS__CGSCC_OPM-NEXT:    [[TMP:%.*]] = load i32, i32* [[N]], align 4
209; IS__CGSCC_OPM-NEXT:    [[SUB3:%.*]] = add nsw i32 [[TMP]], -3
210; IS__CGSCC_OPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2
211; IS__CGSCC_OPM-NEXT:    br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]]
212; IS__CGSCC_OPM:       omp.precond.then:
213; IS__CGSCC_OPM-NEXT:    store i32 0, i32* [[DOTOMP_LB]], align 4
214; IS__CGSCC_OPM-NEXT:    store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4
215; IS__CGSCC_OPM-NEXT:    store i32 1, i32* [[DOTOMP_STRIDE]], align 4
216; IS__CGSCC_OPM-NEXT:    store i32 0, i32* [[DOTOMP_IS_LAST]], align 4
217; IS__CGSCC_OPM-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
218; IS__CGSCC_OPM-NEXT:    call void @__kmpc_for_static_init_4(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP5]], i32 noundef 34, i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 noundef 1, i32 noundef 1)
219; IS__CGSCC_OPM-NEXT:    [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
220; IS__CGSCC_OPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]]
221; IS__CGSCC_OPM-NEXT:    br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
222; IS__CGSCC_OPM:       cond.true:
223; IS__CGSCC_OPM-NEXT:    br label [[COND_END:%.*]]
224; IS__CGSCC_OPM:       cond.false:
225; IS__CGSCC_OPM-NEXT:    [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
226; IS__CGSCC_OPM-NEXT:    br label [[COND_END]]
227; IS__CGSCC_OPM:       cond.end:
228; IS__CGSCC_OPM-NEXT:    [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ]
229; IS__CGSCC_OPM-NEXT:    store i32 [[COND]], i32* [[DOTOMP_UB]], align 4
230; IS__CGSCC_OPM-NEXT:    [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4
231; IS__CGSCC_OPM-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
232; IS__CGSCC_OPM:       omp.inner.for.cond:
233; IS__CGSCC_OPM-NEXT:    [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ]
234; IS__CGSCC_OPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
235; IS__CGSCC_OPM-NEXT:    [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]]
236; IS__CGSCC_OPM-NEXT:    br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]]
237; IS__CGSCC_OPM:       omp.inner.for.cond.cleanup:
238; IS__CGSCC_OPM-NEXT:    br label [[OMP_INNER_FOR_END:%.*]]
239; IS__CGSCC_OPM:       omp.inner.for.body:
240; IS__CGSCC_OPM-NEXT:    [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2
241; IS__CGSCC_OPM-NEXT:    [[TMP10:%.*]] = load float, float* [[P]], align 4
242; IS__CGSCC_OPM-NEXT:    [[TMP11:%.*]] = load double, double* [[CONV]], align 8
243; IS__CGSCC_OPM-NEXT:    call void @bar(i32 [[ADD10]], float [[TMP10]], double [[TMP11]])
244; IS__CGSCC_OPM-NEXT:    br label [[OMP_BODY_CONTINUE:%.*]]
245; IS__CGSCC_OPM:       omp.body.continue:
246; IS__CGSCC_OPM-NEXT:    br label [[OMP_INNER_FOR_INC]]
247; IS__CGSCC_OPM:       omp.inner.for.inc:
248; IS__CGSCC_OPM-NEXT:    [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1
249; IS__CGSCC_OPM-NEXT:    br label [[OMP_INNER_FOR_COND]]
250; IS__CGSCC_OPM:       omp.inner.for.end:
251; IS__CGSCC_OPM-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
252; IS__CGSCC_OPM:       omp.loop.exit:
253; IS__CGSCC_OPM-NEXT:    [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
254; IS__CGSCC_OPM-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP12]])
255; IS__CGSCC_OPM-NEXT:    br label [[OMP_PRECOND_END]]
256; IS__CGSCC_OPM:       omp.precond.end:
257; IS__CGSCC_OPM-NEXT:    ret void
258;
259; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@.omp_outlined.
260; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) {
261; IS__CGSCC_NPM-NEXT:  entry:
262; IS__CGSCC_NPM-NEXT:    [[Q_ADDR:%.*]] = alloca i64, align 8
263; IS__CGSCC_NPM-NEXT:    [[DOTOMP_LB:%.*]] = alloca i32, align 4
264; IS__CGSCC_NPM-NEXT:    [[DOTOMP_UB:%.*]] = alloca i32, align 4
265; IS__CGSCC_NPM-NEXT:    [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
266; IS__CGSCC_NPM-NEXT:    [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
267; IS__CGSCC_NPM-NEXT:    store i64 4617315517961601024, i64* [[Q_ADDR]], align 8
268; IS__CGSCC_NPM-NEXT:    [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double*
269; IS__CGSCC_NPM-NEXT:    [[TMP:%.*]] = load i32, i32* [[N]], align 4
270; IS__CGSCC_NPM-NEXT:    [[SUB3:%.*]] = add nsw i32 [[TMP]], -3
271; IS__CGSCC_NPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2
272; IS__CGSCC_NPM-NEXT:    br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]]
273; IS__CGSCC_NPM:       omp.precond.then:
274; IS__CGSCC_NPM-NEXT:    store i32 0, i32* [[DOTOMP_LB]], align 4
275; IS__CGSCC_NPM-NEXT:    store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4
276; IS__CGSCC_NPM-NEXT:    store i32 1, i32* [[DOTOMP_STRIDE]], align 4
277; IS__CGSCC_NPM-NEXT:    store i32 0, i32* [[DOTOMP_IS_LAST]], align 4
278; IS__CGSCC_NPM-NEXT:    [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
279; IS__CGSCC_NPM-NEXT:    call void @__kmpc_for_static_init_4(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP5]], i32 noundef 34, i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* noundef nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 noundef 1, i32 noundef 1)
280; IS__CGSCC_NPM-NEXT:    [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
281; IS__CGSCC_NPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]]
282; IS__CGSCC_NPM-NEXT:    br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
283; IS__CGSCC_NPM:       cond.true:
284; IS__CGSCC_NPM-NEXT:    br label [[COND_END:%.*]]
285; IS__CGSCC_NPM:       cond.false:
286; IS__CGSCC_NPM-NEXT:    [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
287; IS__CGSCC_NPM-NEXT:    br label [[COND_END]]
288; IS__CGSCC_NPM:       cond.end:
289; IS__CGSCC_NPM-NEXT:    [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ]
290; IS__CGSCC_NPM-NEXT:    store i32 [[COND]], i32* [[DOTOMP_UB]], align 4
291; IS__CGSCC_NPM-NEXT:    [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4
292; IS__CGSCC_NPM-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
293; IS__CGSCC_NPM:       omp.inner.for.cond:
294; IS__CGSCC_NPM-NEXT:    [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ]
295; IS__CGSCC_NPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4
296; IS__CGSCC_NPM-NEXT:    [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]]
297; IS__CGSCC_NPM-NEXT:    br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]]
298; IS__CGSCC_NPM:       omp.inner.for.cond.cleanup:
299; IS__CGSCC_NPM-NEXT:    br label [[OMP_INNER_FOR_END:%.*]]
300; IS__CGSCC_NPM:       omp.inner.for.body:
301; IS__CGSCC_NPM-NEXT:    [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2
302; IS__CGSCC_NPM-NEXT:    [[TMP10:%.*]] = load float, float* [[P]], align 4
303; IS__CGSCC_NPM-NEXT:    [[TMP11:%.*]] = load double, double* [[CONV]], align 8
304; IS__CGSCC_NPM-NEXT:    call void @bar(i32 [[ADD10]], float [[TMP10]], double [[TMP11]])
305; IS__CGSCC_NPM-NEXT:    br label [[OMP_BODY_CONTINUE:%.*]]
306; IS__CGSCC_NPM:       omp.body.continue:
307; IS__CGSCC_NPM-NEXT:    br label [[OMP_INNER_FOR_INC]]
308; IS__CGSCC_NPM:       omp.inner.for.inc:
309; IS__CGSCC_NPM-NEXT:    [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1
310; IS__CGSCC_NPM-NEXT:    br label [[OMP_INNER_FOR_COND]]
311; IS__CGSCC_NPM:       omp.inner.for.end:
312; IS__CGSCC_NPM-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
313; IS__CGSCC_NPM:       omp.loop.exit:
314; IS__CGSCC_NPM-NEXT:    [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4
315; IS__CGSCC_NPM-NEXT:    call void @__kmpc_for_static_fini(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 [[TMP12]])
316; IS__CGSCC_NPM-NEXT:    br label [[OMP_PRECOND_END]]
317; IS__CGSCC_NPM:       omp.precond.end:
318; IS__CGSCC_NPM-NEXT:    ret void
319;
320entry:
321  %q.addr = alloca i64, align 8
322  %.omp.lb = alloca i32, align 4
323  %.omp.ub = alloca i32, align 4
324  %.omp.stride = alloca i32, align 4
325  %.omp.is_last = alloca i32, align 4
326  store i64 %q, i64* %q.addr, align 8
327  %conv = bitcast i64* %q.addr to double*
328  %tmp = load i32, i32* %N, align 4
329  %sub3 = add nsw i32 %tmp, -3
330  %cmp = icmp sgt i32 %tmp, 2
331  br i1 %cmp, label %omp.precond.then, label %omp.precond.end
332
333omp.precond.then:                                 ; preds = %entry
334  store i32 0, i32* %.omp.lb, align 4
335  store i32 %sub3, i32* %.omp.ub, align 4
336  store i32 1, i32* %.omp.stride, align 4
337  store i32 0, i32* %.omp.is_last, align 4
338  %tmp5 = load i32, i32* %.global_tid., align 4
339  call void @__kmpc_for_static_init_4(%struct.ident_t* nonnull @0, i32 %tmp5, i32 34, i32* nonnull %.omp.is_last, i32* nonnull %.omp.lb, i32* nonnull %.omp.ub, i32* nonnull %.omp.stride, i32 1, i32 1)
340  %tmp6 = load i32, i32* %.omp.ub, align 4
341  %cmp6 = icmp sgt i32 %tmp6, %sub3
342  br i1 %cmp6, label %cond.true, label %cond.false
343
344cond.true:                                        ; preds = %omp.precond.then
345  br label %cond.end
346
347cond.false:                                       ; preds = %omp.precond.then
348  %tmp7 = load i32, i32* %.omp.ub, align 4
349  br label %cond.end
350
351cond.end:                                         ; preds = %cond.false, %cond.true
352  %cond = phi i32 [ %sub3, %cond.true ], [ %tmp7, %cond.false ]
353  store i32 %cond, i32* %.omp.ub, align 4
354  %tmp8 = load i32, i32* %.omp.lb, align 4
355  br label %omp.inner.for.cond
356
357omp.inner.for.cond:                               ; preds = %omp.inner.for.inc, %cond.end
358  %.omp.iv.0 = phi i32 [ %tmp8, %cond.end ], [ %add11, %omp.inner.for.inc ]
359  %tmp9 = load i32, i32* %.omp.ub, align 4
360  %cmp8 = icmp sgt i32 %.omp.iv.0, %tmp9
361  br i1 %cmp8, label %omp.inner.for.cond.cleanup, label %omp.inner.for.body
362
363omp.inner.for.cond.cleanup:                       ; preds = %omp.inner.for.cond
364  br label %omp.inner.for.end
365
366omp.inner.for.body:                               ; preds = %omp.inner.for.cond
367  %add10 = add nsw i32 %.omp.iv.0, 2
368  %tmp10 = load float, float* %p, align 4
369  %tmp11 = load double, double* %conv, align 8
370  call void @bar(i32 %add10, float %tmp10, double %tmp11)
371  br label %omp.body.continue
372
373omp.body.continue:                                ; preds = %omp.inner.for.body
374  br label %omp.inner.for.inc
375
376omp.inner.for.inc:                                ; preds = %omp.body.continue
377  %add11 = add nsw i32 %.omp.iv.0, 1
378  br label %omp.inner.for.cond
379
380omp.inner.for.end:                                ; preds = %omp.inner.for.cond.cleanup
381  br label %omp.loop.exit
382
383omp.loop.exit:                                    ; preds = %omp.inner.for.end
384  %tmp12 = load i32, i32* %.global_tid., align 4
385  call void @__kmpc_for_static_fini(%struct.ident_t* nonnull @0, i32 %tmp12)
386  br label %omp.precond.end
387
388omp.precond.end:                                  ; preds = %omp.loop.exit, %entry
389  ret void
390}
391
392declare dso_local void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32)
393
394declare dso_local void @bar(i32, float, double)
395
396declare dso_local void @__kmpc_for_static_fini(%struct.ident_t*, i32)
397
398declare !callback !0 dso_local void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...)
399
400!1 = !{i64 2, i64 -1, i64 -1, i1 true}
401!0 = !{!1}
402;.
403; CHECK: [[META0:![0-9]+]] = !{!1}
404; CHECK: [[META1:![0-9]+]] = !{i64 2, i64 -1, i64 -1, i1 true}
405;.
406