Files
clang-p2996/llvm/test/Transforms/OpenMP/parallel_deletion.ll
Johannes Doerfert 02a4fcec6b [Attributor] Port AANonNull to the isImpliedByIR interface
AANonNull is now the first AA that is always queried via the new APIs
and not created manually. Others will follow shortly to avoid trivial
AAs whenever possible.

This commit introduced some helper logic that will make it simpler to
port the next one. It also untangles AADereferenceable and AANonNull
such that the former does not keep a handle on the latter. Finally,
we stop deducing `nonnull` for `undef`, which was incorrect.
2023-07-09 16:04:19 -07:00

720 lines
41 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
; RUN: opt -S -passes='attributor,cgscc(openmp-opt-cgscc)' < %s | FileCheck %s
;
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
%struct.ident_t = type { i32, i32, i32, i32, ptr }
@.str = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
@0 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, ptr @.str }, align 8
@1 = private unnamed_addr global %struct.ident_t { i32 0, i32 322, i32 0, i32 0, ptr @.str }, align 8
@.gomp_critical_user_.reduction.var = common global [8 x i32] zeroinitializer
@2 = private unnamed_addr global %struct.ident_t { i32 0, i32 18, i32 0, i32 0, ptr @.str }, align 8
; void delete_parallel_0(void) {
; #pragma omp parallel
; { unknown_willreturn(); }
; #pragma omp parallel
; { readonly_willreturn(); }
; #pragma omp parallel
; { readnone_willreturn(); }
; #pragma omp parallel
; {}
; }
;
; We delete all but the first of the parallel regions in this test.
define void @delete_parallel_0() {
; CHECK-LABEL: define {{[^@]+}}@delete_parallel_0() {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0:[0-9]+]], i32 noundef 0, ptr noundef nonnull @.omp_outlined.willreturn)
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@delete_parallel_0() {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0:[0-9]+]], i32 noundef 0, ptr noundef @.omp_outlined.willreturn)
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@delete_parallel_0() {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0:[0-9]+]], i32 noundef 0, ptr noundef @.omp_outlined.willreturn)
; CHECK2-NEXT: ret void
entry:
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn.0)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn.1)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.willreturn.2)
ret void
}
define internal void @.omp_outlined.willreturn(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @unknown() #[[ATTR14:[0-9]+]]
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void @unknown() #[[ATTR0]]
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void @unknown() #[[ATTR0]]
; CHECK2-NEXT: ret void
entry:
call void @unknown() willreturn
ret void
}
define internal void @.omp_outlined.willreturn.0(ptr noalias %.global_tid., ptr noalias %.bound_tid.) willreturn {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @readonly() #[[ATTR4:[0-9]+]]
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void @readonly() #[[ATTR4:[0-9]+]]
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void @readonly() #[[ATTR4:[0-9]+]]
; CHECK2-NEXT: ret void
entry:
call void @readonly()
ret void
}
define internal void @.omp_outlined.willreturn.1(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @readnone() #[[ATTR14]]
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void @readnone() #[[ATTR0]]
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void @readnone() #[[ATTR0]]
; CHECK2-NEXT: ret void
entry:
call void @readnone() willreturn
ret void
}
define internal void @.omp_outlined.willreturn.2(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: ret void
entry:
ret void
}
; void delete_parallel_1(void) {
; #pragma omp parallel
; { unknown(); }
; #pragma omp parallel
; { readonly(); }
; #pragma omp parallel
; { readnone(); }
; #pragma omp parallel
; {}
; }
;
; We delete only the last parallel regions in this test because the others might not return.
define void @delete_parallel_1() {
; CHECK-LABEL: define {{[^@]+}}@delete_parallel_1() {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef nonnull @.omp_outlined.)
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef nonnull @.omp_outlined..0)
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef nonnull @.omp_outlined..1)
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@delete_parallel_1() {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined.)
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..0)
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..1)
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@delete_parallel_1() {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined.)
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..0)
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 0, ptr noundef @.omp_outlined..1)
; CHECK2-NEXT: ret void
entry:
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined.)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined..0)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined..1)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 0, ptr @.omp_outlined..2)
ret void
}
define internal void @.omp_outlined.(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @unknown()
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined.
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void @unknown()
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined.
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void @unknown()
; CHECK2-NEXT: ret void
entry:
call void @unknown()
ret void
}
define internal void @.omp_outlined..0(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..0
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @readonly() #[[ATTR4]]
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..0
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void @readonly() #[[ATTR4]]
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..0
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void @readonly() #[[ATTR4]]
; CHECK2-NEXT: ret void
entry:
call void @readonly()
ret void
}
define internal void @.omp_outlined..1(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..1
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @readnone()
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..1
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: call void @readnone()
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..1
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: call void @readnone()
; CHECK2-NEXT: ret void
entry:
call void @readnone()
ret void
}
define internal void @.omp_outlined..2(ptr noalias %.global_tid., ptr noalias %.bound_tid.) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..2
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..2
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..2
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #[[ATTR3]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: ret void
entry:
ret void
}
; void delete_parallel_2(void) {
; int a = 0;
; #pragma omp parallel
; {
; if (omp_get_thread_num() == 0)
; ++a;
; }
; #pragma omp parallel
; {
; #pragma omp master
; ++a;
; }
; #pragma omp parallel
; {
; #pragma omp single
; ++a;
; }
; #pragma omp parallel reduction(+: a)
; {
; ++a;
; }
; }
;
; FIXME: We do not realize that `a` is dead and all accesses to it can be removed
; making the parallel regions readonly and deletable.
define void @delete_parallel_2() {
; CHECK-LABEL: define {{[^@]+}}@delete_parallel_2() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR15:[0-9]+]]
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..3, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..5, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef nonnull @.omp_outlined..6, ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A]])
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@delete_parallel_2() {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: [[A:%.*]] = alloca i32, align 4
; CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR0]]
; CHECK1-NEXT: store i32 0, ptr [[A]], align 4
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..3, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..5, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..6, ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A]])
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@delete_parallel_2() {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: [[A:%.*]] = alloca i32, align 4
; CHECK2-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR0]]
; CHECK2-NEXT: store i32 0, ptr [[A]], align 4
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..3, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..5, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr noundef nonnull align 8 dereferenceable(24) @[[GLOB0]], i32 noundef 1, ptr noundef @.omp_outlined..6, ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A]])
; CHECK2-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A]])
; CHECK2-NEXT: ret void
entry:
%a = alloca i32, align 4
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a)
store i32 0, ptr %a, align 4
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..3, ptr nonnull %a)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..4, ptr nonnull %a)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..5, ptr nonnull %a)
call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr nonnull @0, i32 1, ptr @.omp_outlined..6, ptr nonnull %a)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %a)
ret void
}
define internal void @.omp_outlined..3(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..3
; CHECK-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = call i32 @omp_get_thread_num() #[[ATTR16:[0-9]+]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1
; CHECK-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..3
; CHECK1-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: [[CALL:%.*]] = call i32 @omp_get_thread_num() #[[ATTR14:[0-9]+]]
; CHECK1-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
; CHECK1-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK1: if.then:
; CHECK1-NEXT: [[TMP:%.*]] = load i32, ptr [[A]], align 4
; CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1
; CHECK1-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK1-NEXT: br label [[IF_END]]
; CHECK1: if.end:
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..3
; CHECK2-SAME: (ptr noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: [[CALL:%.*]] = call i32 @omp_get_thread_num() #[[ATTR14:[0-9]+]]
; CHECK2-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
; CHECK2-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK2: if.then:
; CHECK2-NEXT: [[TMP:%.*]] = load i32, ptr [[A]], align 4
; CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1
; CHECK2-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK2-NEXT: br label [[IF_END]]
; CHECK2: if.end:
; CHECK2-NEXT: ret void
entry:
%call = call i32 @omp_get_thread_num()
%cmp = icmp eq i32 %call, 0
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
%tmp = load i32, ptr %a, align 4
%inc = add nsw i32 %tmp, 1
store i32 %inc, ptr %a, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
ret void
}
define internal void @.omp_outlined..4(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..4
; CHECK-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
; CHECK: omp_if.then:
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1
; CHECK-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK-NEXT: call void @__kmpc_end_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK-NEXT: br label [[OMP_IF_END]]
; CHECK: omp_if.end:
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..4
; CHECK1-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK1-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK1-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK1-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
; CHECK1: omp_if.then:
; CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[A]], align 4
; CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1
; CHECK1-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK1-NEXT: call void @__kmpc_end_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK1-NEXT: br label [[OMP_IF_END]]
; CHECK1: omp_if.end:
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..4
; CHECK2-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK2-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK2-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK2-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
; CHECK2: omp_if.then:
; CHECK2-NEXT: [[TMP3:%.*]] = load i32, ptr [[A]], align 4
; CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1
; CHECK2-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK2-NEXT: call void @__kmpc_end_master(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK2-NEXT: br label [[OMP_IF_END]]
; CHECK2: omp_if.end:
; CHECK2-NEXT: ret void
entry:
%tmp = load i32, ptr %.global_tid., align 4
%tmp1 = call i32 @__kmpc_master(ptr nonnull @0, i32 %tmp)
%tmp2 = icmp eq i32 %tmp1, 0
br i1 %tmp2, label %omp_if.end, label %omp_if.then
omp_if.then: ; preds = %entry
%tmp3 = load i32, ptr %a, align 4
%inc = add nsw i32 %tmp3, 1
store i32 %inc, ptr %a, align 4
call void @__kmpc_end_master(ptr nonnull @0, i32 %tmp)
br label %omp_if.end
omp_if.end: ; preds = %entry, %omp_if.then
ret void
}
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
declare i32 @omp_get_thread_num() inaccessiblememonly nofree nosync nounwind readonly
declare i32 @__kmpc_master(ptr, i32)
declare void @__kmpc_end_master(ptr, i32)
define internal void @.omp_outlined..5(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..5
; CHECK-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr noundef nonnull @[[GLOB0]]) #[[ATTR16]]
; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
; CHECK: omp_if.then:
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1
; CHECK-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK-NEXT: call void @__kmpc_end_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK-NEXT: br label [[OMP_IF_END]]
; CHECK: omp_if.end:
; CHECK-NEXT: call void @__kmpc_barrier(ptr noundef nonnull @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]])
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..5
; CHECK1-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr noundef nonnull @[[GLOB0]]) #[[ATTR14]]
; CHECK1-NEXT: [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK1-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK1-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK1-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
; CHECK1: omp_if.then:
; CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[A]], align 4
; CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1
; CHECK1-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK1-NEXT: call void @__kmpc_end_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK1-NEXT: br label [[OMP_IF_END]]
; CHECK1: omp_if.end:
; CHECK1-NEXT: call void @__kmpc_barrier(ptr noundef nonnull @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]])
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..5
; CHECK2-SAME: (ptr noalias nocapture nofree readonly [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr noundef nonnull @[[GLOB0]]) #[[ATTR14]]
; CHECK2-NEXT: [[TMP:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK2-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK2-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK2-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]]
; CHECK2: omp_if.then:
; CHECK2-NEXT: [[TMP3:%.*]] = load i32, ptr [[A]], align 4
; CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1
; CHECK2-NEXT: store i32 [[INC]], ptr [[A]], align 4
; CHECK2-NEXT: call void @__kmpc_end_single(ptr noundef nonnull @[[GLOB0]], i32 [[TMP]])
; CHECK2-NEXT: br label [[OMP_IF_END]]
; CHECK2: omp_if.end:
; CHECK2-NEXT: call void @__kmpc_barrier(ptr noundef nonnull @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]])
; CHECK2-NEXT: ret void
entry:
%omp_global_thread_num = call i32 @__kmpc_global_thread_num(ptr nonnull @0)
%tmp = load i32, ptr %.global_tid., align 4
%tmp1 = call i32 @__kmpc_single(ptr nonnull @0, i32 %tmp)
%tmp2 = icmp eq i32 %tmp1, 0
br i1 %tmp2, label %omp_if.end, label %omp_if.then
omp_if.then: ; preds = %entry
%tmp3 = load i32, ptr %a, align 4
%inc = add nsw i32 %tmp3, 1
store i32 %inc, ptr %a, align 4
call void @__kmpc_end_single(ptr nonnull @0, i32 %tmp)
br label %omp_if.end
omp_if.end: ; preds = %entry, %omp_if.then
call void @__kmpc_barrier(ptr nonnull @1, i32 %omp_global_thread_num) #6
ret void
}
define internal void @.omp_outlined..6(ptr noalias %.global_tid., ptr noalias %.bound_tid., ptr dereferenceable(4) %a) {
; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..6
; CHECK-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A1:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 [[A1]]) #[[ATTR17:[0-9]+]]
; CHECK-NEXT: store i32 1, ptr [[A1]], align 4
; CHECK-NEXT: store ptr [[A1]], ptr [[DOTOMP_REDUCTION_RED_LIST]], align 8
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(ptr noundef nonnull @[[GLOB2:[0-9]+]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, ptr noundef nonnull align 8 [[DOTOMP_REDUCTION_RED_LIST]], ptr noundef nonnull @.omp.reduction.reduction_func, ptr noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK-NEXT: switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
; CHECK-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
; CHECK-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
; CHECK-NEXT: ]
; CHECK: .omp.reduction.case1:
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4
; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[A1]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK-NEXT: store i32 [[ADD]], ptr [[A]], align 4
; CHECK-NEXT: call void @__kmpc_end_reduce_nowait(ptr noundef nonnull @[[GLOB2]], i32 [[TMP2]], ptr noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK: .omp.reduction.case2:
; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[A1]], align 4
; CHECK-NEXT: [[TMP8:%.*]] = atomicrmw add ptr [[A]], i32 [[TMP7]] monotonic, align 4
; CHECK-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK: .omp.reduction.default:
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A1]])
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp_outlined..6
; CHECK1-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: [[A1:%.*]] = alloca i32, align 4
; CHECK1-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
; CHECK1-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 [[A1]]) #[[ATTR0]]
; CHECK1-NEXT: store i32 1, ptr [[A1]], align 4
; CHECK1-NEXT: store ptr [[A1]], ptr [[DOTOMP_REDUCTION_RED_LIST]], align 8
; CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK1-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(ptr noundef nonnull @[[GLOB2:[0-9]+]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, ptr noundef nonnull align 8 [[DOTOMP_REDUCTION_RED_LIST]], ptr noundef nonnull @.omp.reduction.reduction_func, ptr noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK1-NEXT: switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
; CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
; CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
; CHECK1-NEXT: ]
; CHECK1: .omp.reduction.case1:
; CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4
; CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[A1]], align 4
; CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK1-NEXT: store i32 [[ADD]], ptr [[A]], align 4
; CHECK1-NEXT: call void @__kmpc_end_reduce_nowait(ptr noundef nonnull @[[GLOB2]], i32 [[TMP2]], ptr noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK1-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK1: .omp.reduction.case2:
; CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[A1]], align 4
; CHECK1-NEXT: [[TMP8:%.*]] = atomicrmw add ptr [[A]], i32 [[TMP7]] monotonic, align 4
; CHECK1-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK1: .omp.reduction.default:
; CHECK1-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A1]])
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp_outlined..6
; CHECK2-SAME: (ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], ptr noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], ptr nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: [[A1:%.*]] = alloca i32, align 4
; CHECK2-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x ptr], align 8
; CHECK2-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noundef nonnull align 4 [[A1]]) #[[ATTR0]]
; CHECK2-NEXT: store i32 1, ptr [[A1]], align 4
; CHECK2-NEXT: store ptr [[A1]], ptr [[DOTOMP_REDUCTION_RED_LIST]], align 8
; CHECK2-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTGLOBAL_TID_]], align 4
; CHECK2-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(ptr noundef nonnull @[[GLOB2:[0-9]+]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, ptr noundef nonnull align 8 [[DOTOMP_REDUCTION_RED_LIST]], ptr noundef nonnull @.omp.reduction.reduction_func, ptr noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK2-NEXT: switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
; CHECK2-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
; CHECK2-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
; CHECK2-NEXT: ]
; CHECK2: .omp.reduction.case1:
; CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4
; CHECK2-NEXT: [[TMP6:%.*]] = load i32, ptr [[A1]], align 4
; CHECK2-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK2-NEXT: store i32 [[ADD]], ptr [[A]], align 4
; CHECK2-NEXT: call void @__kmpc_end_reduce_nowait(ptr noundef nonnull @[[GLOB2]], i32 [[TMP2]], ptr noundef nonnull @.gomp_critical_user_.reduction.var)
; CHECK2-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK2: .omp.reduction.case2:
; CHECK2-NEXT: [[TMP7:%.*]] = load i32, ptr [[A1]], align 4
; CHECK2-NEXT: [[TMP8:%.*]] = atomicrmw add ptr [[A]], i32 [[TMP7]] monotonic, align 4
; CHECK2-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]]
; CHECK2: .omp.reduction.default:
; CHECK2-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noundef nonnull [[A1]])
; CHECK2-NEXT: ret void
entry:
%a1 = alloca i32, align 4
%.omp.reduction.red_list = alloca [1 x ptr], align 8
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a1)
store i32 1, ptr %a1, align 4
store ptr %a1, ptr %.omp.reduction.red_list, align 8
%tmp2 = load i32, ptr %.global_tid., align 4
%tmp4 = call i32 @__kmpc_reduce_nowait(ptr nonnull @2, i32 %tmp2, i32 1, i64 8, ptr nonnull %.omp.reduction.red_list, ptr nonnull @.omp.reduction.reduction_func, ptr nonnull @.gomp_critical_user_.reduction.var)
switch i32 %tmp4, label %.omp.reduction.default [
i32 1, label %.omp.reduction.case1
i32 2, label %.omp.reduction.case2
]
.omp.reduction.case1: ; preds = %entry
%tmp5 = load i32, ptr %a, align 4
%tmp6 = load i32, ptr %a1, align 4
%add = add nsw i32 %tmp5, %tmp6
store i32 %add, ptr %a, align 4
call void @__kmpc_end_reduce_nowait(ptr nonnull @2, i32 %tmp2, ptr nonnull @.gomp_critical_user_.reduction.var)
br label %.omp.reduction.default
.omp.reduction.case2: ; preds = %entry
%tmp7 = load i32, ptr %a1, align 4
%tmp8 = atomicrmw add ptr %a, i32 %tmp7 monotonic
br label %.omp.reduction.default
.omp.reduction.default: ; preds = %.omp.reduction.case2, %.omp.reduction.case1, %entry
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %a1)
ret void
}
define internal void @.omp.reduction.reduction_func(ptr %arg, ptr %arg1) {
; CHECK-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func
; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARG1]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[ARG]], align 8
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP2]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK-NEXT: store i32 [[ADD]], ptr [[TMP4]], align 4
; CHECK-NEXT: ret void
;
; CHECK1-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func
; CHECK1-SAME: (ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
; CHECK1-NEXT: entry:
; CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARG1]], align 8
; CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[ARG]], align 8
; CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
; CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP2]], align 4
; CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK1-NEXT: store i32 [[ADD]], ptr [[TMP4]], align 4
; CHECK1-NEXT: ret void
; CHECK2-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func
; CHECK2-SAME: (ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], ptr nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #[[ATTR10:[0-9]+]] {
; CHECK2-NEXT: entry:
; CHECK2-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARG1]], align 8
; CHECK2-NEXT: [[TMP4:%.*]] = load ptr, ptr [[ARG]], align 8
; CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
; CHECK2-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP2]], align 4
; CHECK2-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]]
; CHECK2-NEXT: store i32 [[ADD]], ptr [[TMP4]], align 4
; CHECK2-NEXT: ret void
entry:
%tmp2 = load ptr, ptr %arg1, align 8
%tmp4 = load ptr, ptr %arg, align 8
%tmp5 = load i32, ptr %tmp4, align 4
%tmp6 = load i32, ptr %tmp2, align 4
%add = add nsw i32 %tmp5, %tmp6
store i32 %add, ptr %tmp4, align 4
ret void
}
declare i32 @__kmpc_single(ptr, i32)
declare void @__kmpc_end_single(ptr, i32)
declare void @__kmpc_barrier(ptr, i32)
declare i32 @__kmpc_global_thread_num(ptr) nofree nosync nounwind readonly
declare i32 @__kmpc_reduce_nowait(ptr, i32, i32, i64, ptr, ptr, ptr)
declare void @__kmpc_end_reduce_nowait(ptr, i32, ptr)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
declare !callback !2 void @__kmpc_fork_call(ptr, i32, ptr, ...)
declare void @unknown()
declare void @readonly() readonly
declare void @readnone() readnone
!llvm.module.flags = !{!8}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang"}
!2 = !{!3}
!3 = !{i64 2, i64 -1, i64 -1, i1 true}
!4 = !{!5, !5, i64 0}
!5 = !{!"int", !6, i64 0}
!6 = !{!"omnipotent char", !7, i64 0}
!7 = !{!"Simple C/C++ TBAA"}
!8 = !{i32 7, !"openmp", i32 50}