[flang][acc] Add AA implementation for acc operations#189772
Conversation
This PR extends flang's alias analysis so it can reason about values that originate from OpenACC data and privatization operations, including values passed through block arguments.
|
@llvm/pr-subscribers-mlir-openacc @llvm/pr-subscribers-flang-fir-hlfir Author: Razvan Lupusoru (razvanlupusoru) ChangesThis PR extends flang's alias analysis so it can reason about values that originate from OpenACC data and privatization operations, including values passed through block arguments. Patch is 35.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/189772.diff 8 Files Affected:
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
index a8b9bcf5cfd4b..840622b7dd0f9 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
@@ -13,14 +13,30 @@
#ifndef FORTRAN_OPTIMIZER_OPENACC_SUPPORT_FIROPENACCUTILS_H
#define FORTRAN_OPTIMIZER_OPENACC_SUPPORT_FIROPENACCUTILS_H
+#include "flang/Optimizer/Analysis/AliasAnalysis.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/Operation.h"
#include "mlir/IR/Value.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include <string>
namespace fir {
namespace acc {
+/// Memory source for `mappedValue` when it is produced by OpenACC mapping op
+/// `accOp` . Private-like ops return `SourceKind::Allocate`; other data clauses
+/// trace the host variable via `traceValue`.
+///
+/// `accumulatedAttrs` collects Fortran variable attributes from the path from
+/// the queried value to `accOp` (e.g. [hl]fir.declare); they are merged into
+/// the returned source so TARGET/POINTER/INTENT_IN are not dropped.
+fir::AliasAnalysis::Source getSourceFromACCValue(
+ mlir::Value mappedValue, mlir::Operation *accOp,
+ llvm::function_ref<fir::AliasAnalysis::Source(mlir::Value)> traceValue,
+ bool originIsData,
+ fir::AliasAnalysis::Source::Attributes accumulatedAttrs = {});
+
/// Attempts to extract the variable name from a value by walking through
/// FIR operations and looking for variable names.
/// \param v The value to extract the variable name from
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 550e8a3a281d6..77d334657ad9b 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -13,8 +13,11 @@
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "mlir/Analysis/AliasAnalysis.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenACC/OpenACCUtils.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/Dialect/OpenMP/OpenMPInterfaces.h"
#include "mlir/IR/BuiltinOps.h"
@@ -24,6 +27,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include <optional>
using namespace mlir;
@@ -680,6 +684,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
auto opResult = mlir::cast<OpResult>(v);
assert(opResult.getOwner() == defOp && "v must be a result of defOp");
ty = opResult.getType();
+ std::optional<AliasAnalysis::Source> accSourceReturn;
llvm::TypeSwitch<Operation *>(defOp)
.Case([&](hlfir::AsExprOp op) {
// TODO: we should probably always report hlfir.as_expr
@@ -937,10 +942,21 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
!mlir::isa<fir::BaseBoxType>(ty))
followBoxData = true;
})
+ .Case<ACC_DATA_ENTRY_AND_INIT_OPS>([&](auto op) {
+ accSourceReturn = fir::acc::getSourceFromACCValue(
+ v, op.getOperation(),
+ [&](mlir::Value x) {
+ return getSource(x, getLastInstantiationPoint);
+ },
+ followingData, attributes);
+ breakFromLoop = true;
+ })
.Default([&](auto op) {
defOp = nullptr;
breakFromLoop = true;
});
+ if (accSourceReturn)
+ return *accSourceReturn;
}
if (!defOp && type == SourceKind::Unknown) {
// Check if the memory source is coming through a dummy argument.
@@ -956,6 +972,14 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
// hlfir.eval_in_mem block operands is allocated by the operation.
type = SourceKind::Allocate;
ty = v.getType();
+ } else if (mlir::Operation *accOp =
+ mlir::acc::getACCDataClauseOpForBlockArg(v)) {
+ return fir::acc::getSourceFromACCValue(
+ v, accOp,
+ [&](mlir::Value x) {
+ return getSource(x, getLastInstantiationPoint);
+ },
+ followingData, attributes);
}
}
diff --git a/flang/lib/Optimizer/Analysis/CMakeLists.txt b/flang/lib/Optimizer/Analysis/CMakeLists.txt
index 398a6d3b88427..c017708e35ddf 100644
--- a/flang/lib/Optimizer/Analysis/CMakeLists.txt
+++ b/flang/lib/Optimizer/Analysis/CMakeLists.txt
@@ -6,22 +6,26 @@ add_flang_library(FIRAnalysis
DEPENDS
CUFDialect
FIRDialect
+ FIROpenACCSupport
FIRSupport
HLFIRDialect
LINK_LIBS
CUFDialect
FIRDialect
+ FIROpenACCSupport
FIRSupport
HLFIRDialect
MLIR_DEPS
MLIRIR
+ MLIROpenACCDialect
MLIROpenMPDialect
MLIR_LIBS
MLIRFuncDialect
MLIRLLVMDialect
MLIRMathTransforms
+ MLIROpenACCDialect
MLIROpenMPDialect
)
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
index 519978dba1afd..39ccd3aad1598 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h"
+#include "flang/Optimizer/Analysis/AliasAnalysis.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/Complex.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
@@ -29,6 +30,7 @@
#include "mlir/Interfaces/ViewLikeInterface.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/raw_ostream.h"
+#include <mlir/Support/LLVM.h>
using namespace mlir;
@@ -616,6 +618,42 @@ mlir::SymbolRefAttr fir::acc::createOrGetReductionRecipe(
return mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName());
}
+static bool isACCPrivateLikeOp(mlir::Operation *op) {
+ if (!op)
+ return false;
+ return mlir::isa<mlir::acc::ReductionInitOp, mlir::acc::PrivateOp,
+ mlir::acc::FirstprivateOp,
+ mlir::acc::FirstprivateMapInitialOp>(op);
+}
+
+fir::AliasAnalysis::Source fir::acc::getSourceFromACCValue(
+ mlir::Value mappedValue, mlir::Operation *accOp,
+ llvm::function_ref<fir::AliasAnalysis::Source(mlir::Value)> traceValue,
+ bool originIsData,
+ fir::AliasAnalysis::Source::Attributes accumulatedAttrs) {
+ assert(accOp && "OpenACC mapping op required");
+ if (isACCPrivateLikeOp(accOp))
+ return {{mappedValue, nullptr, originIsData},
+ fir::AliasAnalysis::SourceKind::Allocate,
+ mappedValue.getType(),
+ accumulatedAttrs,
+ false,
+ false};
+
+ // Not private-like: classify using the corresponding host variable's source.
+ //
+ // Caveat: with discrete device memory, host and device copies do not alias
+ // even when this path makes them look related. Alias analysis here is usually
+ // about two values *inside* a compute region, not host-vs-device pointer
+ // queries, so using the host source remains a reasonable tradeoff for
+ // disambiguating in-region uses. Finer modeling would require extending
+ // AliasAnalysis::Source (with address space) and teaching AA to use it.
+ fir::AliasAnalysis::Source traced =
+ traceValue(mlir::acc::getVar(accOp));
+ traced.attributes |= accumulatedAttrs;
+ return traced;
+}
+
mlir::Value fir::acc::getOriginalDef(mlir::Value value, bool stripDeclare) {
mlir::Value currentValue = value;
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-acc.mlir b/flang/test/Analysis/AliasAnalysis/alias-analysis-acc.mlir
new file mode 100644
index 0000000000000..9fb5ee221691d
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-acc.mlir
@@ -0,0 +1,546 @@
+// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
+
+// -----
+
+// Two acc.copyin results from distinct host allocas do not alias.
+// CHECK-LABEL: Testing : "testBothOutsideCopyinDistinctHosts"
+// CHECK-DAG: cin_a#0 <-> cin_b#0: NoAlias
+
+func.func @testBothOutsideCopyinDistinctHosts() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ca = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a", test.ptr = "cin_a"}
+ %cb = acc.copyin varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b", test.ptr = "cin_b"}
+ return
+}
+
+// -----
+
+// Two acc.copyin results from dummy arguments that are Fortran TARGET variables:
+// they may alias.
+// CHECK-LABEL: Testing : "testBothOutsideCopyinTargetDummyArgsMayAlias"
+// CHECK-DAG: arg_cp_a#0 <-> arg_cp_b#0: MayAlias
+
+func.func @testBothOutsideCopyinTargetDummyArgsMayAlias(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<f32> {fir.bindc_name = "y"}) {
+ %ds = fir.dummy_scope : !fir.dscope
+ %dx = fir.declare %arg0 dummy_scope %ds arg 1 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEex"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %dy = fir.declare %arg1 dummy_scope %ds arg 2 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEey"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %cx = acc.copyin varPtr(%dx : !fir.ref<f32>) -> !fir.ref<f32> {name = "x", test.ptr = "arg_cp_a"}
+ %cy = acc.copyin varPtr(%dy : !fir.ref<f32>) -> !fir.ref<f32> {name = "y", test.ptr = "arg_cp_b"}
+ return
+}
+
+// -----
+
+// Two acc.copyin results mapping the same host ref must alias.
+// CHECK-LABEL: Testing : "testBothOutsideCopyinSameHostMustAlias"
+// CHECK-DAG: out_must_a#0 <-> out_must_b#0: MustAlias
+
+func.func @testBothOutsideCopyinSameHostMustAlias() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ca1 = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a", test.ptr = "out_must_a"}
+ %ca2 = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a", test.ptr = "out_must_b"}
+ return
+}
+
+// -----
+
+// CHECK-LABEL: Testing : "testBothOutsideCreateDistinctHosts"
+// CHECK-DAG: crt_a#0 <-> crt_b#0: NoAlias
+
+func.func @testBothOutsideCreateDistinctHosts() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ta = acc.create varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a", test.ptr = "crt_a"}
+ %tb = acc.create varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b", test.ptr = "crt_b"}
+ return
+}
+
+// -----
+
+// Same distinct-host copyins as above, but threaded through acc.compute_region
+// block arguments.
+// CHECK-LABEL: Testing : "testComputeRegionCopyinDistinctHostsInsideConvert"
+// CHECK-DAG: cr_dist_a#0 <-> cr_dist_b#0: NoAlias
+
+func.func @testComputeRegionCopyinDistinctHostsInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ca = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ %cb = acc.copyin varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"}
+ acc.compute_region ins(%arg0 = %ca, %arg1 = %cb) : (!fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %arg0 {test.ptr = "cr_dist_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %arg1 {test.ptr = "cr_dist_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.yield
+ } {origin = "acc.kernels"}
+ return
+}
+
+// -----
+
+// CHECK-LABEL: Testing : "testComputeRegionCreateDistinctHostsInsideConvert"
+// CHECK-DAG: cr_crt_a#0 <-> cr_crt_b#0: NoAlias
+
+func.func @testComputeRegionCreateDistinctHostsInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ta = acc.create varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ %tb = acc.create varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"}
+ acc.compute_region ins(%arg0 = %ta, %arg1 = %tb) : (!fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %arg0 {test.ptr = "cr_crt_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %arg1 {test.ptr = "cr_crt_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.yield
+ } {origin = "acc.kernels"}
+ return
+}
+
+// -----
+
+// Same TARGET dummy copyins as testBothOutsideCopyinTargetDummyArgsMayAlias,
+// through acc.compute_region block args.
+// CHECK-LABEL: Testing : "testComputeRegionCopyinTargetDummiesMayAliasInsideConvert"
+// CHECK-DAG: cr_tgt_a#0 <-> cr_tgt_b#0: MayAlias
+
+func.func @testComputeRegionCopyinTargetDummiesMayAliasInsideConvert(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<f32> {fir.bindc_name = "y"}) {
+ %ds = fir.dummy_scope : !fir.dscope
+ %dx = fir.declare %arg0 dummy_scope %ds arg 1 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEex"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %dy = fir.declare %arg1 dummy_scope %ds arg 2 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEey"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %cx = acc.copyin varPtr(%dx : !fir.ref<f32>) -> !fir.ref<f32> {name = "x"}
+ %cy = acc.copyin varPtr(%dy : !fir.ref<f32>) -> !fir.ref<f32> {name = "y"}
+ acc.compute_region ins(%cr0 = %cx, %cr1 = %cy) : (!fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %cr0 {test.ptr = "cr_tgt_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %cr1 {test.ptr = "cr_tgt_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.yield
+ } {origin = "acc.parallel"}
+ return
+}
+
+// -----
+
+// Single host copyin wired twice through arguments; both block args alias the
+// same mapped host variable.
+// CHECK-LABEL: Testing : "testComputeRegionCopyinSameHostMustAliasInsideConvert"
+// CHECK-DAG: cr_must_a#0 <-> cr_must_b#0: MustAlias
+
+func.func @testComputeRegionCopyinSameHostMustAliasInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ca = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ acc.compute_region ins(%arg0 = %ca, %arg1 = %ca) : (!fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %arg0 {test.ptr = "cr_must_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %arg1 {test.ptr = "cr_must_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.yield
+ } {origin = "acc.kernels"}
+ return
+}
+
+// -----
+
+// Distinct-host copyins passed as acc.kernels dataOperands.
+// CHECK-LABEL: Testing : "testKernelsCopyinDistinctHostsInsideConvert"
+// CHECK-DAG: kern_dist_a#0 <-> kern_dist_b#0: NoAlias
+
+func.func @testKernelsCopyinDistinctHostsInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ca = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ %cb = acc.copyin varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"}
+ acc.kernels dataOperands(%ca, %cb : !fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %ca {test.ptr = "kern_dist_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %cb {test.ptr = "kern_dist_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.terminator
+ }
+ return
+}
+
+// -----
+
+// CHECK-LABEL: Testing : "testKernelsCreateDistinctHostsInsideConvert"
+// CHECK-DAG: kern_crt_a#0 <-> kern_crt_b#0: NoAlias
+
+func.func @testKernelsCreateDistinctHostsInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ta = acc.create varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ %tb = acc.create varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"}
+ acc.kernels dataOperands(%ta, %tb : !fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %ta {test.ptr = "kern_crt_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %tb {test.ptr = "kern_crt_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.terminator
+ }
+ return
+}
+
+// -----
+
+// TARGET dummy copyins as acc.kernels dataOperands.
+// CHECK-LABEL: Testing : "testKernelsCopyinTargetDummiesMayAliasInsideConvert"
+// CHECK-DAG: kern_tgt_a#0 <-> kern_tgt_b#0: MayAlias
+
+func.func @testKernelsCopyinTargetDummiesMayAliasInsideConvert(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<f32> {fir.bindc_name = "y"}) {
+ %ds = fir.dummy_scope : !fir.dscope
+ %dx = fir.declare %arg0 dummy_scope %ds arg 1 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEex"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %dy = fir.declare %arg1 dummy_scope %ds arg 2 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEey"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %cx = acc.copyin varPtr(%dx : !fir.ref<f32>) -> !fir.ref<f32> {name = "x"}
+ %cy = acc.copyin varPtr(%dy : !fir.ref<f32>) -> !fir.ref<f32> {name = "y"}
+ acc.kernels dataOperands(%cx, %cy : !fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %cx {test.ptr = "kern_tgt_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %cy {test.ptr = "kern_tgt_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.terminator
+ }
+ return
+}
+
+// -----
+
+// Same copyin value listed twice in dataOperands; both converts must alias.
+// CHECK-LABEL: Testing : "testKernelsCopyinSameHostMustAliasInsideConvert"
+// CHECK-DAG: kern_must_a#0 <-> kern_must_b#0: MustAlias
+
+func.func @testKernelsCopyinSameHostMustAliasInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %ca = acc.copyin varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ acc.kernels dataOperands(%ca : !fir.ref<f32>) {
+ %va = fir.convert %ca {test.ptr = "kern_must_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %ca {test.ptr = "kern_must_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.terminator
+ }
+ return
+}
+
+// -----
+
+// acc.compute_region: both queried values are inside the region; test.ptr is on
+// fir.convert of each captured private (traces block operands without tagging
+// the region op).
+// CHECK-LABEL: Testing : "testComputeRegionPrivateInsideConvert"
+// CHECK-DAG: cr_priv_a#0 <-> cr_priv_b#0: NoAlias
+
+func.func @testComputeRegionPrivateInsideConvert() {
+ %a = fir.alloca f32 {uniq_name = "_QFEa"}
+ %b = fir.alloca f32 {uniq_name = "_QFEb"}
+ %da = fir.declare %a {uniq_name = "_QFEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %db = fir.declare %b {uniq_name = "_QFEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %pa = acc.private varPtr(%da : !fir.ref<f32>) -> !fir.ref<f32> {name = "a"}
+ %pb = acc.private varPtr(%db : !fir.ref<f32>) -> !fir.ref<f32> {name = "b"}
+ acc.compute_region ins(%arg0 = %pa, %arg1 = %pb) : (!fir.ref<f32>, !fir.ref<f32>) {
+ %va = fir.convert %arg0 {test.ptr = "cr_priv_a"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %vb = fir.convert %arg1 {test.ptr = "cr_priv_b"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ acc.yield
+ } {origin = "acc.parallel"}
+ return
+}
+
+// -----
+
+// Same host ref as both acc.copyin and acc.private operands (two copyins would
+// must-alias); private-like mapping is a distinct allocation vs copyin.
+// CHECK-LABEL: Testing : "testComputeRegionCopyinVsPrivateSameHostNoAlias"
+// CHECK-DAG: cr_mix_cp#0 <-> cr_mix_pr#0: NoAlias
+
+func....
[truncated]
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/169/builds/21491 Here is the relevant piece of the build log for the reference |
This PR extends flang's alias analysis so it can reason about values that originate from OpenACC data and privatization operations, including values passed through block arguments.
This PR extends flang's alias analysis so it can reason about values that originate from OpenACC data and privatization operations, including values passed through block arguments.
This PR extends flang's alias analysis so it can reason about values that originate from OpenACC data and privatization operations, including values passed through block arguments.