Skip to content

Commit 73ad416

Browse files
[OpenMP][Flang] Enable alias analysis inside omp target region (#111670)
At present, alias analysis does not work for operations inside OMP target regions because the FIR declare operations within OMP target do not offer sufficient information for alias analysis. Consequently, it is necessary to examine the FIR code outside the OMP target region.
1 parent 80c15c4 commit 73ad416

File tree

4 files changed

+193
-0
lines changed

4 files changed

+193
-0
lines changed

flang/lib/Optimizer/Analysis/AliasAnalysis.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
1414
#include "flang/Optimizer/HLFIR/HLFIROps.h"
1515
#include "mlir/Analysis/AliasAnalysis.h"
16+
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
17+
#include "mlir/Dialect/OpenMP/OpenMPInterfaces.h"
1618
#include "mlir/IR/BuiltinOps.h"
1719
#include "mlir/IR/Value.h"
1820
#include "mlir/Interfaces/SideEffectInterfaces.h"
@@ -296,6 +298,17 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
296298
defOp = v.getDefiningOp();
297299
return;
298300
}
301+
// If load is inside target and it points to mapped item,
302+
// continue tracking.
303+
Operation *loadMemrefOp = op.getMemref().getDefiningOp();
304+
bool isDeclareOp = llvm::isa<fir::DeclareOp>(loadMemrefOp) ||
305+
llvm::isa<hlfir::DeclareOp>(loadMemrefOp);
306+
if (isDeclareOp &&
307+
llvm::isa<omp::TargetOp>(loadMemrefOp->getParentOp())) {
308+
v = op.getMemref();
309+
defOp = v.getDefiningOp();
310+
return;
311+
}
299312
// No further tracking for addresses loaded from memory for now.
300313
type = SourceKind::Indirect;
301314
breakFromLoop = true;
@@ -319,6 +332,22 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
319332
breakFromLoop = true;
320333
})
321334
.Case<hlfir::DeclareOp, fir::DeclareOp>([&](auto op) {
335+
// If declare operation is inside omp target region,
336+
// continue alias analysis outside the target region
337+
if (auto targetOp =
338+
llvm::dyn_cast<omp::TargetOp>(op->getParentOp())) {
339+
auto argIface = cast<omp::BlockArgOpenMPOpInterface>(*targetOp);
340+
for (auto [opArg, blockArg] : llvm::zip_equal(
341+
targetOp.getMapVars(), argIface.getMapBlockArgs())) {
342+
if (blockArg == op.getMemref()) {
343+
omp::MapInfoOp mapInfo =
344+
llvm::cast<omp::MapInfoOp>(opArg.getDefiningOp());
345+
v = mapInfo.getVarPtr();
346+
defOp = v.getDefiningOp();
347+
return;
348+
}
349+
}
350+
}
322351
auto varIf = llvm::cast<fir::FortranVariableOpInterface>(defOp);
323352
// While going through a declare operation collect
324353
// the variable attributes from it. Right now, some

flang/lib/Optimizer/Analysis/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_flang_library(FIRAnalysis
66
FIRDialect
77
HLFIRDialect
88
MLIRIR
9+
MLIROpenMPDialect
910

1011
LINK_LIBS
1112
FIRBuilder
@@ -14,5 +15,6 @@ add_flang_library(FIRAnalysis
1415
MLIRFuncDialect
1516
MLIRLLVMDialect
1617
MLIRMathTransforms
18+
MLIROpenMPDialect
1719
FIRSupport
1820
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Use --mlir-disable-threading so that the AA queries are serialized
2+
// as well as its diagnostic output.
3+
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
4+
5+
// Fortran source code:
6+
//
7+
// program TestAllocatableArray
8+
// real(kind=8), allocatable :: A(:)
9+
// real(kind=8), allocatable :: B(:)
10+
// !$omp target
11+
// A(0) = B(0)
12+
// !$omp end target
13+
// end TestAllocatableArray
14+
15+
// CHECK-LABEL: Testing : "_QPTestAllocatableArray"
16+
// CHECK-DAG: targetArrayB#0 <-> targetArrayA#0: NoAlias
17+
func.func @_QPTestAllocatableArray() {
18+
%0 = fir.address_of(@_QFEa) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
19+
%1:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "ArrayA" } : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>)
20+
%2 = fir.address_of(@_QFEb) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
21+
%3:2 = hlfir.declare %2 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "ArrayB" } : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>)
22+
%4 = fir.load %1#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
23+
%c1 = arith.constant 1 : index
24+
%c0 = arith.constant 0 : index
25+
%5 = fir.load %1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
26+
%c0_0 = arith.constant 0 : index
27+
%6:3 = fir.box_dims %5, %c0_0 : (!fir.box<!fir.heap<!fir.array<?xf64>>>, index) -> (index, index, index)
28+
%7:3 = fir.box_dims %4, %c0 : (!fir.box<!fir.heap<!fir.array<?xf64>>>, index) -> (index, index, index)
29+
%c0_1 = arith.constant 0 : index
30+
%8 = arith.subi %7#1, %c1 : index
31+
%9 = omp.map.bounds lower_bound(%c0_1 : index) upper_bound(%8 : index) extent(%7#1 : index) stride(%7#2 : index) start_idx(%6#0 : index) {stride_in_bytes = true}
32+
%10 = fir.box_offset %1#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>
33+
%11 = omp.map.info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.array<?xf64>) var_ptr_ptr(%10 : !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%9) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>> {name = ""}
34+
%12 = omp.map.info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.box<!fir.heap<!fir.array<?xf64>>>) map_clauses(implicit, tofrom) capture(ByRef) members(%11 : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>> {name = "a"}
35+
%13 = fir.load %3#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
36+
%c1_2 = arith.constant 1 : index
37+
%c0_3 = arith.constant 0 : index
38+
%14 = fir.load %3#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
39+
%c0_4 = arith.constant 0 : index
40+
%15:3 = fir.box_dims %14, %c0_4 : (!fir.box<!fir.heap<!fir.array<?xf64>>>, index) -> (index, index, index)
41+
%16:3 = fir.box_dims %13, %c0_3 : (!fir.box<!fir.heap<!fir.array<?xf64>>>, index) -> (index, index, index)
42+
%c0_5 = arith.constant 0 : index
43+
%17 = arith.subi %16#1, %c1_2 : index
44+
%18 = omp.map.bounds lower_bound(%c0_5 : index) upper_bound(%17 : index) extent(%16#1 : index) stride(%16#2 : index) start_idx(%15#0 : index) {stride_in_bytes = true}
45+
%19 = fir.box_offset %3#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>
46+
%20 = omp.map.info var_ptr(%3#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.array<?xf64>) var_ptr_ptr(%19 : !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%18) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>> {name = ""}
47+
%21 = omp.map.info var_ptr(%3#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.box<!fir.heap<!fir.array<?xf64>>>) map_clauses(implicit, tofrom) capture(ByRef) members(%20 : [0] : !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>> {name = "b"}
48+
omp.target map_entries(%11 -> %arg0, %12 -> %arg1, %20 -> %arg2, %21 -> %arg3 : !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xf64>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) {
49+
%22:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>)
50+
%23:2 = hlfir.declare %arg3 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFEb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>)
51+
%24 = fir.load %23#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
52+
%c0_6 = arith.constant 0 : index
53+
%25 = hlfir.designate %24 (%c0_6) {test.ptr = "targetArrayB"} : (!fir.box<!fir.heap<!fir.array<?xf64>>>, index) -> !fir.ref<f64>
54+
%26 = fir.load %25 : !fir.ref<f64>
55+
%27 = fir.load %22#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>
56+
%c0_7 = arith.constant 0 : index
57+
%28 = hlfir.designate %27 (%c0_7) {test.ptr = "targetArrayA"} : (!fir.box<!fir.heap<!fir.array<?xf64>>>, index) -> !fir.ref<f64>
58+
hlfir.assign %26 to %28 : f64, !fir.ref<f64>
59+
omp.terminator
60+
}
61+
return
62+
}
63+
fir.global internal @_QFEa : !fir.box<!fir.heap<!fir.array<?xf64>>> {
64+
}
65+
fir.global internal @_QFEb : !fir.box<!fir.heap<!fir.array<?xf64>>> {
66+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Use --mlir-disable-threading so that the AA queries are serialized
2+
// as well as its diagnostic output.
3+
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
4+
5+
// Fortran source code:
6+
//
7+
// subroutine TestTargetData(p, a, b)
8+
// real :: p(10), a(10), b(10)
9+
// !$omp target data map(from: p)
10+
// !$omp target map(to: a )
11+
// p(1) = a(1)
12+
// !$omp end target
13+
// !$omp target map(to: b )
14+
// p(1) = b(1)
15+
// !$omp end target
16+
// !$omp end target data
17+
// end subroutine
18+
19+
// CHECK-LABEL: Testing : "_QPTestTargetData"
20+
21+
// CHECK-DAG: targetArrayA#0 <-> targetArrayP#0: NoAlias
22+
// CHECK-DAG: targetArrayA#0 <-> targetArrayB#0: NoAlias
23+
// CHECK-DAG: targetArrayP#0 <-> targetArrayB#0: NoAlias
24+
25+
func.func @_QPTestTargetData(%arg0: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "p"}, %arg1: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "a"}, %arg2: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "b"}) {
26+
%0 = fir.dummy_scope : !fir.dscope
27+
%c10 = arith.constant 10 : index
28+
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
29+
%2:2 = hlfir.declare %arg1(%1) dummy_scope %0 {uniq_name = "_QFtest_target_dataEa"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
30+
%c10_0 = arith.constant 10 : index
31+
%3 = fir.shape %c10_0 : (index) -> !fir.shape<1>
32+
%4:2 = hlfir.declare %arg2(%3) dummy_scope %0 {uniq_name = "_QFtest_target_dataEb"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
33+
%c10_1 = arith.constant 10 : index
34+
%5 = fir.shape %c10_1 : (index) -> !fir.shape<1>
35+
%6:2 = hlfir.declare %arg0(%5) dummy_scope %0 {uniq_name = "_QFtest_target_dataEp"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
36+
%c1 = arith.constant 1 : index
37+
%c0 = arith.constant 0 : index
38+
%7 = arith.subi %c10_1, %c1 : index
39+
%8 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%7 : index) extent(%c10_1 : index) stride(%c1 : index) start_idx(%c1 : index)
40+
%9 = omp.map.info var_ptr(%6#1 : !fir.ref<!fir.array<10xf32>>, !fir.array<10xf32>) map_clauses(from) capture(ByRef) bounds(%8) -> !fir.ref<!fir.array<10xf32>> {name = "p"}
41+
omp.target_data map_entries(%9 : !fir.ref<!fir.array<10xf32>>) {
42+
%c1_2 = arith.constant 1 : index
43+
%c0_3 = arith.constant 0 : index
44+
%10 = arith.subi %c10, %c1_2 : index
45+
%11 = omp.map.bounds lower_bound(%c0_3 : index) upper_bound(%10 : index) extent(%c10 : index) stride(%c1_2 : index) start_idx(%c1_2 : index)
46+
%12 = omp.map.info var_ptr(%2#1 : !fir.ref<!fir.array<10xf32>>, !fir.array<10xf32>) map_clauses(to) capture(ByRef) bounds(%11) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
47+
%c1_4 = arith.constant 1 : index
48+
%c0_5 = arith.constant 0 : index
49+
%13 = arith.subi %c10_1, %c1_4 : index
50+
%14 = omp.map.bounds lower_bound(%c0_5 : index) upper_bound(%13 : index) extent(%c10_1 : index) stride(%c1_4 : index) start_idx(%c1_4 : index)
51+
%15 = omp.map.info var_ptr(%6#1 : !fir.ref<!fir.array<10xf32>>, !fir.array<10xf32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%14) -> !fir.ref<!fir.array<10xf32>> {name = "p"}
52+
omp.target map_entries(%12 -> %arg3, %15 -> %arg4 : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
53+
%c10_10 = arith.constant 10 : index
54+
%22 = fir.shape %c10_10 : (index) -> !fir.shape<1>
55+
%23:2 = hlfir.declare %arg3(%22) {uniq_name = "_QFtest_target_dataEa"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
56+
%c10_11 = arith.constant 10 : index
57+
%24 = fir.shape %c10_11 : (index) -> !fir.shape<1>
58+
%25:2 = hlfir.declare %arg4(%24) {uniq_name = "_QFtest_target_dataEp"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
59+
%c1_12 = arith.constant 1 : index
60+
%26 = hlfir.designate %23#0 (%c1_12) {test.ptr = "targetArrayA"} : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
61+
%27 = fir.load %26 : !fir.ref<f32>
62+
%c1_13 = arith.constant 1 : index
63+
%28 = hlfir.designate %25#0 (%c1_13) {test.ptr = "targetArrayP"} : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
64+
hlfir.assign %27 to %28 : f32, !fir.ref<f32>
65+
omp.terminator
66+
}
67+
%c1_6 = arith.constant 1 : index
68+
%c0_7 = arith.constant 0 : index
69+
%16 = arith.subi %c10_0, %c1_6 : index
70+
%17 = omp.map.bounds lower_bound(%c0_7 : index) upper_bound(%16 : index) extent(%c10_0 : index) stride(%c1_6 : index) start_idx(%c1_6 : index)
71+
%18 = omp.map.info var_ptr(%4#1 : !fir.ref<!fir.array<10xf32>>, !fir.array<10xf32>) map_clauses(to) capture(ByRef) bounds(%17) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
72+
%c1_8 = arith.constant 1 : index
73+
%c0_9 = arith.constant 0 : index
74+
%19 = arith.subi %c10_1, %c1_8 : index
75+
%20 = omp.map.bounds lower_bound(%c0_9 : index) upper_bound(%19 : index) extent(%c10_1 : index) stride(%c1_8 : index) start_idx(%c1_8 : index)
76+
%21 = omp.map.info var_ptr(%6#1 : !fir.ref<!fir.array<10xf32>>, !fir.array<10xf32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%20) -> !fir.ref<!fir.array<10xf32>> {name = "p"}
77+
omp.target map_entries(%18 -> %arg3, %21 -> %arg4 : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) {
78+
%c10_10 = arith.constant 10 : index
79+
%22 = fir.shape %c10_10 : (index) -> !fir.shape<1>
80+
%23:2 = hlfir.declare %arg3(%22) {uniq_name = "_QFtest_target_dataEb"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
81+
%c10_11 = arith.constant 10 : index
82+
%24 = fir.shape %c10_11 : (index) -> !fir.shape<1>
83+
%25:2 = hlfir.declare %arg4(%24) {uniq_name = "_QFtest_target_dataEp"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
84+
%c1_12 = arith.constant 1 : index
85+
%26 = hlfir.designate %23#0 (%c1_12) {test.ptr = "targetArrayB"} : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
86+
%27 = fir.load %26 : !fir.ref<f32>
87+
%c1_13 = arith.constant 1 : index
88+
%28 = hlfir.designate %25#0 (%c1_13) {test.ptr = "targetArrayP"} : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
89+
hlfir.assign %27 to %28 : f32, !fir.ref<f32>
90+
omp.terminator
91+
}
92+
omp.terminator
93+
}
94+
return
95+
}
96+

0 commit comments

Comments
 (0)