blob: e115072f4cf387d54c96e0cbae84a3062e0c5d17 [file] [edit]
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux-gnu \
// RUN: -fopenmp-targets=amdgpu9.00-amd-amdhsa -emit-llvm-bc %s -o %t-host.bc
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple amdgpu9.00-amd-amdhsa \
// RUN: -fopenmp-targets=amdgpu9.00-amd-amdhsa -fopenmp-is-target-device \
// RUN: -fopenmp-target-atomic-reduction -fopenmp-host-ir-file-path %t-host.bc \
// RUN: -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=ATOMIC %s < %t.ll
// RUN: FileCheck --check-prefix=BUFFER %s < %t.ll
// RUN: FileCheck %s < %t.ll
// expected-no-diagnostics
// ATOMIC-DAG: call i32 @__kmpc_is_team_main_thread(
// ATOMIC-DAG: atomicrmw add ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw add ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw and ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw or ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw xor ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw min ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw max ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw umin ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw umax ptr {{.*}} syncscope("agent") monotonic
// ATOMIC-DAG: atomicrmw fadd ptr {{.*}} syncscope("agent") monotonic
void atomicable_matrix(int n) {
int si = 0, su = 0, an = ~0, orv = 0, xr = 0, smn = 0x7fffffff,
smx = -0x7fffffff - 1;
unsigned umn = ~0u, umx = 0u;
float f = 0.0f;
#pragma omp target teams distribute parallel for reduction(+ : si) \
reduction(- : su) reduction(& : an) reduction(| : orv) reduction(^ : xr) \
reduction(min : smn) reduction(max : smx) reduction(min : umn) \
reduction(max : umx) reduction(+ : f)
for (int i = 0; i < n; ++i) {
si += i;
su -= i;
an &= i;
orv |= i;
xr ^= i;
smn = i < smn ? i : smn;
smx = i > smx ? i : smx;
umn = (unsigned)i < umn ? (unsigned)i : umn;
umx = (unsigned)i > umx ? (unsigned)i : umx;
f += i;
}
}
// A fp multiply and a fp max reduction have no direct atomicrmw, so each falls
// back to the buffer path even with -fopenmp-target-atomic-reduction. Together with
// the mixed construct below there are exactly three buffered writebacks.
//
// BUFFER-COUNT-3: call i32 @__kmpc_gpu_xteam_reduce_nowait(
// BUFFER-NOT: call i32 @__kmpc_gpu_xteam_reduce_nowait(
double nonatomicable_mul(int n) {
double p = 1.0;
#pragma omp target teams distribute parallel for reduction(* : p)
for (int i = 0; i < n; ++i)
p *= 1.0;
return p;
}
double nonatomicable_fpmax(int n) {
double mx = 0.0;
#pragma omp target teams distribute parallel for reduction(max : mx)
for (int i = 0; i < n; ++i)
mx = (double)i > mx ? (double)i : mx;
return mx;
}
// A single non-atomicable reduction (fp multiply) poisons the whole set: the
// atomic path requires *all* reductions to have an atomicrmw, so even the int
// sum here is combined through the buffer, not atomically. Hence no team-main
// guard and no `atomicrmw add` for `s` from this construct (asserted by the
// module-wide counts above).
//
// CHECK-COUNT-1: call i32 @__kmpc_is_team_main_thread(
// CHECK-NOT: call i32 @__kmpc_is_team_main_thread(
// CHECK-NOT: atomicrmw fmul
// CHECK-NOT: atomicrmw fmax
double mixed(int n) {
int s = 0;
double p = 1.0;
#pragma omp target teams distribute parallel for reduction(+ : s) \
reduction(* : p)
for (int i = 0; i < n; ++i) {
s += i;
p *= 1.0;
}
return s + p;
}