Skip to content

Commit 19c498f

Browse files
committed
[RFC][mlir] ViewLikeOpInterface method for detecting partial views.
I am trying to simplify the implementation of Flang's AliasAnalysis by using ViewLikeOpInterface for some FIR dialect operations. Currently, Flang's AliasAnalysis implementation explicitly recognizes specific set of operations, which is inconvenient. ViewLikeOpInterface may also be used in other parts of Flang. In this patch, I only add ViewLikeOpInterface support to few FIR operations to demonstrate the intent. Flang's alias analysis LIT tests are failing with this change, and I would like to get some advices on how to proceed. As soon as I add, ViewLikeOpInterface interface support for FIR operations, the LocalAliasAnalysis kicks in, and starts reporting `MustAlias` for some cases where Flang currently reports MayAlias. I believe both analyses are incorrect here: they should actually report `PartialAlias` for those cases. This is what the new method `isSameStart` should be used for. I would like to fix both LocalAliasAnalysis and Flang's alias analysis to return `PartialAlias` in those cases, but I am not sure if querying `isSameStart` is enough - see the TBD comment in ViewLikeInterface.td. If my understanding of `PartialAlias` is correct, then we can have a partial alias even when the starting addresses of the source and the resulting view are the same - though, I might be wrong.
1 parent 024dd56 commit 19c498f

File tree

5 files changed

+58
-30
lines changed

5 files changed

+58
-30
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
2121
#include "mlir/Interfaces/LoopLikeInterface.h"
2222
#include "mlir/Interfaces/SideEffectInterfaces.h"
23+
#include "mlir/Interfaces/ViewLikeInterface.h"
2324

2425
namespace fir {
2526

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
include "mlir/Dialect/Arith/IR/ArithBase.td"
1818
include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td"
1919
include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
20+
include "mlir/Interfaces/ViewLikeInterface.td"
2021
include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.td"
2122
include "flang/Optimizer/Dialect/FIRDialect.td"
2223
include "flang/Optimizer/Dialect/FIRTypes.td"
@@ -1730,8 +1731,9 @@ def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store",
17301731
// Record and array type operations
17311732
//===----------------------------------------------------------------------===//
17321733

1733-
def fir_ArrayCoorOp : fir_Op<"array_coor",
1734-
[NoMemoryEffect, AttrSizedOperandSegments]> {
1734+
def fir_ArrayCoorOp
1735+
: fir_Op<"array_coor", [NoMemoryEffect, AttrSizedOperandSegments,
1736+
ViewLikeOpInterface]> {
17351737

17361738
let summary = "Find the coordinate of an element of an array";
17371739

@@ -1774,9 +1776,13 @@ def fir_ArrayCoorOp : fir_Op<"array_coor",
17741776

17751777
let hasVerifier = 1;
17761778
let hasCanonicalizer = 1;
1779+
let extraClassDeclaration = [{
1780+
mlir::Value getViewSource() { return getMemref(); }
1781+
}];
17771782
}
17781783

1779-
def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> {
1784+
def fir_CoordinateOp
1785+
: fir_Op<"coordinate_of", [NoMemoryEffect, ViewLikeOpInterface]> {
17801786

17811787
let summary = "Finds the coordinate (location) of a value in memory";
17821788

@@ -1828,6 +1834,7 @@ def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> {
18281834
let extraClassDeclaration = [{
18291835
constexpr static int32_t kDynamicIndex = std::numeric_limits<int32_t>::min();
18301836
CoordinateIndicesAdaptor getIndices();
1837+
mlir::Value getViewSource() { return getRef(); }
18311838
}];
18321839
}
18331840

@@ -2792,7 +2799,8 @@ def fir_VolatileCastOp : fir_SimpleOneResultOp<"volatile_cast", [Pure]> {
27922799
let hasFolder = 1;
27932800
}
27942801

2795-
def fir_ConvertOp : fir_SimpleOneResultOp<"convert", [NoMemoryEffect]> {
2802+
def fir_ConvertOp
2803+
: fir_SimpleOneResultOp<"convert", [NoMemoryEffect, ViewLikeOpInterface]> {
27962804
let summary = "encapsulates all Fortran entity type conversions";
27972805

27982806
let description = [{
@@ -2830,6 +2838,8 @@ def fir_ConvertOp : fir_SimpleOneResultOp<"convert", [NoMemoryEffect]> {
28302838
static bool isPointerCompatible(mlir::Type ty);
28312839
static bool canBeConverted(mlir::Type inType, mlir::Type outType);
28322840
static bool areVectorsCompatible(mlir::Type inTy, mlir::Type outTy);
2841+
mlir::Value getViewSource() { return getValue(); }
2842+
bool isSameStart() { return true; }
28332843
}];
28342844
let hasCanonicalizer = 1;
28352845
}

flang/lib/Optimizer/Analysis/AliasAnalysis.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -559,10 +559,19 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
559559
type = SourceKind::Allocate;
560560
breakFromLoop = true;
561561
})
562-
.Case<fir::ConvertOp>([&](auto op) {
563-
// Skip ConvertOp's and track further through the operand.
564-
v = op->getOperand(0);
562+
.Case<mlir::ViewLikeOpInterface>([&](auto op) {
563+
if (isPointerReference(ty))
564+
attributes.set(Attribute::Pointer);
565+
v = op.getViewSource();
565566
defOp = v.getDefiningOp();
567+
// If the source is a box, and the result is not a box,
568+
// then this is one of the box "unpacking" operations,
569+
// so we should set followingData.
570+
if (mlir::isa<fir::BaseBoxType>(v.getType()) &&
571+
!mlir::isa<fir::BaseBoxType>(ty))
572+
followingData = true;
573+
if (!op.isSameStart())
574+
approximateSource = true;
566575
})
567576
.Case<fir::PackArrayOp>([&](auto op) {
568577
// The packed array is not distinguishable from the original
@@ -578,15 +587,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
578587
if (mlir::isa<fir::BaseBoxType>(v.getType()))
579588
followBoxData = true;
580589
})
581-
.Case<fir::ArrayCoorOp, fir::CoordinateOp>([&](auto op) {
582-
if (isPointerReference(ty))
583-
attributes.set(Attribute::Pointer);
584-
v = op->getOperand(0);
585-
defOp = v.getDefiningOp();
586-
if (mlir::isa<fir::BaseBoxType>(v.getType()))
587-
followBoxData = true;
588-
approximateSource = true;
589-
})
590590
.Case<fir::EmboxOp, fir::ReboxOp>([&](auto op) {
591591
if (followBoxData) {
592592
v = op->getOperand(0);

mlir/include/mlir/Interfaces/ViewLikeInterface.td

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,34 @@ def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> {
2323
}];
2424
let cppNamespace = "::mlir";
2525

26-
let methods = [
27-
InterfaceMethod<
28-
"Returns the source buffer from which the view is created.",
29-
"::mlir::Value", "getViewSource">,
30-
InterfaceMethod<
31-
/*desc=*/[{ Returns the buffer which the view created. }],
32-
/*retTy=*/"::mlir::Value",
33-
/*methodName=*/"getViewDest",
34-
/*args=*/(ins),
35-
/*methodBody=*/"",
36-
/*defaultImplementation=*/[{
26+
let methods =
27+
[InterfaceMethod<
28+
"Returns the source buffer from which the view is created.",
29+
"::mlir::Value", "getViewSource">,
30+
InterfaceMethod<
31+
/*desc=*/[{ Returns the buffer which the view created. }],
32+
/*retTy=*/"::mlir::Value",
33+
/*methodName=*/"getViewDest",
34+
/*args=*/(ins),
35+
/*methodBody=*/"",
36+
/*defaultImplementation=*/[{
3737
return $_op->getResult(0);
38-
}]
39-
>
40-
];
38+
}]>,
39+
InterfaceMethod<
40+
// TBD: should it be generalized into isPartialView that will
41+
// return true in any of these cases?
42+
// 1. Resulting view is a slice view of the source.
43+
// 2. Resulting view's start does not match the source's start.
44+
// 3. Resulting view's end does not match the source's end.
45+
/*desc=*/
46+
[{ Returns true iff the source buffer and the resulting view start at the same "address". }],
47+
/*retTy=*/"bool",
48+
/*methodName=*/"isSameStart",
49+
/*args=*/(ins),
50+
/*methodBody=*/"",
51+
/*defaultImplementation=*/[{
52+
return false;
53+
}]>];
4154
}
4255

4356
def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface"> {

mlir/lib/Analysis/AliasAnalysis/LocalAliasAnalysis.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ static void collectUnderlyingAddressValues(OpResult result, unsigned maxDepth,
129129
// If this is a view, unwrap to the source.
130130
if (ViewLikeOpInterface view = dyn_cast<ViewLikeOpInterface>(op)) {
131131
if (result == view.getViewDest()) {
132+
// TODO: if view.isSameStart() returns false here,
133+
// we have to make sure that further analysis may return
134+
// PartialAlias for all underlying addresses we are going
135+
// to collect from this point up the def-use.
132136
return collectUnderlyingAddressValues(view.getViewSource(), maxDepth,
133137
visited, output);
134138
}

0 commit comments

Comments
 (0)