diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index 0b0f83d024ce3..1dac023727338 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -505,30 +505,17 @@ getAttrsFromVariable(fir::FortranVariableOpInterface var) { } template -static Value getPrivateArg(omp::BlockArgOpenMPOpInterface &argIface, - OMPTypeOp &op, DeclTypeOp &declOp) { - Value privateArg; +static bool isPrivateArg(omp::BlockArgOpenMPOpInterface &argIface, + OMPTypeOp &op, DeclTypeOp &declOp) { if (!op.getPrivateSyms().has_value()) - return privateArg; + return false; for (auto [opSym, blockArg] : llvm::zip_equal(*op.getPrivateSyms(), argIface.getPrivateBlockArgs())) { if (blockArg == declOp.getMemref()) { - omp::PrivateClauseOp privateOp = - SymbolTable::lookupNearestSymbolFrom( - op, cast(opSym)); - privateOp.walk([&](omp::YieldOp yieldOp) { - // TODO Extend alias analysis if omp.yield points to - // block argument value - if (!yieldOp.getResults()[0].getDefiningOp()) - return; - llvm::TypeSwitch(yieldOp.getResults()[0].getDefiningOp()) - .template Case( - [&](auto declOp) { privateArg = declOp.getMemref(); }); - }); - return privateArg; + return true; } } - return privateArg; + return false; } AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, @@ -630,6 +617,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, breakFromLoop = true; }) .Case([&](auto op) { + bool isPrivateItem = false; if (omp::BlockArgOpenMPOpInterface argIface = dyn_cast(op->getParentOp())) { Value ompValArg; @@ -643,19 +631,18 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, omp::MapInfoOp mapInfo = llvm::cast(opArg.getDefiningOp()); ompValArg = mapInfo.getVarPtr(); - break; + return; } } // If given operation does not reflect mapping item, // check private clause - if (!ompValArg) - ompValArg = getPrivateArg(argIface, targetOp, op); + isPrivateItem = isPrivateArg(argIface, targetOp, op); }) .template Case( [&](auto privateOp) { - ompValArg = getPrivateArg(argIface, privateOp, op); + isPrivateItem = isPrivateArg(argIface, privateOp, op); }); if (ompValArg) { v = ompValArg; @@ -705,6 +692,11 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, } else { instantiationPoint = op; } + if (isPrivateItem) { + type = SourceKind::Allocate; + breakFromLoop = true; + return; + } // TODO: Look for the fortran attributes present on the operation // Track further through the operand v = op.getMemref(); diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-allocatable.mlir b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-allocatable.mlir new file mode 100644 index 0000000000000..5116622364fad --- /dev/null +++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-private-allocatable.mlir @@ -0,0 +1,50 @@ +// Use --mlir-disable-threading so that the AA queries are serialized +// as well as its diagnostic output. +// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s + +// Fortran code before simplification: +// SUBROUTINE mysub(ns,ne) +// INTEGER :: n +// REAL(KIND=8), DIMENSION(:), allocatable :: ar1 +// real(kind=8), dimension(20) :: ar2 +// REAL(KIND=8), DIMENSION(20) :: d +// +//!$OMP parallel PRIVATE(ar1) +// d(1:1) = (/(DOT_PRODUCT(ar1(1:n), ar2(1:n)),n=1, 1)/) +//!$OMP END parallel +// END SUBROUTINE + +// CHECK-LABEL: Testing : "testPrivateAllocatable" +// CHECK: ar2#0 <-> ar1#0: NoAlias +// CHECK: ar2#1 <-> ar1#0: NoAlias +// CHECK: ar2#0 <-> ar1#1: NoAlias +// CHECK: ar2#1 <-> ar1#1: NoAlias + +omp.private {type = private} @_QFmysubEar1_private_ref_box_heap_Uxf64 : !fir.ref>>> alloc { +^bb0(%arg0: !fir.ref>>>): + %0 = fir.alloca !fir.box>> {bindc_name = "ar1", pinned, uniq_name = "_QFmysubEar1"} + %5:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFmysubEar1"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + omp.yield(%5#0 : !fir.ref>>>) +} dealloc { +^bb0(%arg0: !fir.ref>>>): + omp.yield +} +func.func @testPrivateAllocatable(%arg0: !fir.ref {fir.bindc_name = "ns"}, %arg1: !fir.ref {fir.bindc_name = "ne"}) { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.alloca !fir.box>> {bindc_name = "ar1", uniq_name = "_QFmysubEar1"} + %2 = fir.zero_bits !fir.heap> + %c0 = arith.constant 0 : index + %3 = fir.shape %c0 : (index) -> !fir.shape<1> + %4 = fir.embox %2(%3) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> + fir.store %4 to %1 : !fir.ref>>> + %5:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFmysubEar1"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + %c20 = arith.constant 20 : index + %6 = fir.alloca !fir.array<20xf64> {bindc_name = "ar2", uniq_name = "_QFmysubEar2"} + %7 = fir.shape %c20 : (index) -> !fir.shape<1> + %8:2 = hlfir.declare %6(%7) {uniq_name = "_QFmysubEar2", test.ptr="ar2" } : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + omp.parallel private(@_QFmysubEar1_private_ref_box_heap_Uxf64 %5#0 -> %arg2 : !fir.ref>>>) { + %20:2 = hlfir.declare %arg2 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFmysubEar1", test.ptr = "ar1"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + omp.terminator + } + return +}