Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Dialect/FIROps.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Interfaces/ViewLikeInterface.h"

namespace fir {

Expand Down
19 changes: 15 additions & 4 deletions flang/include/flang/Optimizer/Dialect/FIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
include "mlir/Dialect/Arith/IR/ArithBase.td"
include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td"
include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
include "mlir/Interfaces/ViewLikeInterface.td"
include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.td"
include "flang/Optimizer/Dialect/FIRDialect.td"
include "flang/Optimizer/Dialect/FIRTypes.td"
Expand Down Expand Up @@ -1730,8 +1731,9 @@ def fir_ArrayMergeStoreOp : fir_Op<"array_merge_store",
// Record and array type operations
//===----------------------------------------------------------------------===//

def fir_ArrayCoorOp : fir_Op<"array_coor",
[NoMemoryEffect, AttrSizedOperandSegments]> {
def fir_ArrayCoorOp
: fir_Op<"array_coor", [NoMemoryEffect, AttrSizedOperandSegments,
ViewLikeOpInterface]> {

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

Expand Down Expand Up @@ -1774,9 +1776,13 @@ def fir_ArrayCoorOp : fir_Op<"array_coor",

let hasVerifier = 1;
let hasCanonicalizer = 1;
let extraClassDeclaration = [{
mlir::Value getViewSource() { return getMemref(); }
}];
}

def fir_CoordinateOp : fir_Op<"coordinate_of", [NoMemoryEffect]> {
def fir_CoordinateOp
: fir_Op<"coordinate_of", [NoMemoryEffect, ViewLikeOpInterface]> {

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

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

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

def fir_ConvertOp : fir_SimpleOneResultOp<"convert", [NoMemoryEffect]> {
def fir_ConvertOp
: fir_SimpleOneResultOp<"convert", [NoMemoryEffect, ViewLikeOpInterface]> {
let summary = "encapsulates all Fortran entity type conversions";

let description = [{
Expand Down Expand Up @@ -2830,6 +2838,9 @@ def fir_ConvertOp : fir_SimpleOneResultOp<"convert", [NoMemoryEffect]> {
static bool isPointerCompatible(mlir::Type ty);
static bool canBeConverted(mlir::Type inType, mlir::Type outType);
static bool areVectorsCompatible(mlir::Type inTy, mlir::Type outTy);
mlir::Value getViewSource() { return getValue(); }
bool isSameStart() { return true; }
bool isCompleteView() { return true; }
}];
let hasCanonicalizer = 1;
}
Expand Down
28 changes: 16 additions & 12 deletions flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ AliasResult AliasAnalysis::alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs,
if (lhsSrc.origin == rhsSrc.origin) {
LLVM_DEBUG(llvm::dbgs()
<< " aliasing because same source kind and origin\n");
// TODO: we should return PartialAlias here. Need to decide
// if returning PartialAlias for fir.pack_array is okay;
// if not, then we need to handle it specially to still return
// MayAlias.
if (approximateSource)
return AliasResult::MayAlias;
return AliasResult::MustAlias;
Expand Down Expand Up @@ -559,10 +563,19 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
type = SourceKind::Allocate;
breakFromLoop = true;
})
.Case<fir::ConvertOp>([&](auto op) {
// Skip ConvertOp's and track further through the operand.
v = op->getOperand(0);
.Case<mlir::ViewLikeOpInterface>([&](auto op) {
if (isPointerReference(ty))
attributes.set(Attribute::Pointer);
v = op.getViewSource();
defOp = v.getDefiningOp();
// If the source is a box, and the result is not a box,
// then this is one of the box "unpacking" operations,
// so we should set followingData.
if (mlir::isa<fir::BaseBoxType>(v.getType()) &&
!mlir::isa<fir::BaseBoxType>(ty))
followBoxData = true;
if (!op.isSameStart())
approximateSource = true;
})
.Case<fir::PackArrayOp>([&](auto op) {
// The packed array is not distinguishable from the original
Expand All @@ -578,15 +591,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
if (mlir::isa<fir::BaseBoxType>(v.getType()))
followBoxData = true;
})
.Case<fir::ArrayCoorOp, fir::CoordinateOp>([&](auto op) {
if (isPointerReference(ty))
attributes.set(Attribute::Pointer);
v = op->getOperand(0);
defOp = v.getDefiningOp();
if (mlir::isa<fir::BaseBoxType>(v.getType()))
followBoxData = true;
approximateSource = true;
})
.Case<fir::EmboxOp, fir::ReboxOp>([&](auto op) {
if (followBoxData) {
v = op->getOperand(0);
Expand Down
12 changes: 6 additions & 6 deletions flang/test/Analysis/AliasAnalysis/load-ptr-designate.fir
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@
// CHECK-DAG: obj#0 <-> obj%alloc#0: MayAlias
// CHECK-DAG: obj#0 <-> obj%p0.tgt#0: MayAlias
// CHECK-DAG: obj#0 <-> obj%alloc.tgt#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.fir#0: PartialAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.fir#0: PartialAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.tgt.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.tgt.fir#0: MayAlias

Expand Down Expand Up @@ -252,8 +252,8 @@ func.func @_QPtest.fir() {
// CHECK-DAG: obj#0 <-> obj%alloc#0: MayAlias
// CHECK-DAG: obj#0 <-> obj%p0.tgt#0: MayAlias
// CHECK-DAG: obj#0 <-> obj%alloc.tgt#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.fir#0: PartialAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.fir#0: PartialAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.tgt.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.tgt.fir#0: MayAlias

Expand Down Expand Up @@ -412,8 +412,8 @@ func.func @_QPtest.fir(%arg0: !fir.ref<!fir.type<_QMmTty{p0:!fir.box<!fir.ptr<f3
// CHECK-DAG: obj#0 <-> obj%alloc#0: MayAlias
// CHECK-DAG: obj#0 <-> obj%p0.tgt#0: MayAlias
// CHECK-DAG: obj#0 <-> obj%alloc.tgt#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.fir#0: PartialAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.fir#0: PartialAlias
// CHECK-DAG: obj.fir#0 <-> obj%p0.tgt.fir#0: MayAlias
// CHECK-DAG: obj.fir#0 <-> obj%alloc.tgt.fir#0: MayAlias

Expand Down
21 changes: 12 additions & 9 deletions flang/test/Analysis/AliasAnalysis/ptr-component.fir
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@
// therefore x needs to alias with x.next to prevent the loads from being merged.
// CHECK-DAG: x#0 <-> xnext1#0: MayAlias
// CHECK-DAG: x#0 <-> xnext2#0: MayAlias
// CHECK-DAG: x.fir#0 <-> xnext1.fir#0: MayAlias
// CHECK-DAG: x.fir#0 <-> xnext2.fir#0: MayAlias
// CHECK-DAG: x.fir#0 <-> xnext1.fir#0: PartialAlias
// CHECK-DAG: x.fir#0 <-> xnext2.fir#0: PartialAlias

// TODO: xnext1#0 <-> xnext2#0 are the same and therefore MustAlias but
// we are currently not comparing operands involved in offset computations
// CHECK-DAG: xnext1#0 <-> xnext2#0: MayAlias
// CHECK-DAG: xnext1.fir#0 <-> xnext2.fir#0: MayAlias
// CHECK-DAG: xnext1.fir#0 <-> xnext2.fir#0: PartialAlias

// CHECK-DAG: xnext1#0 <-> ynext#0: NoAlias
// CHECK-DAG: xnext1.fir#0 <-> ynext.fir#0: NoAlias
Expand Down Expand Up @@ -217,7 +217,7 @@ func.func @_QMmPfoo3.fir(%arg0: !fir.ref<!fir.type<_QMmTta{array:!fir.box<!fir.p

// CHECK-LABEL: Testing : "_QMmPtest"
// CHECK-DAG: x#0 <-> x%p#0: MayAlias
// CHECK-DAG: x.fir#0 <-> x%p.fir#0: MayAlias
// CHECK-DAG: x.fir#0 <-> x%p.fir#0: PartialAlias

func.func @_QMmPtest() {
%0 = fir.address_of(@_QMmEx) : !fir.ref<!fir.type<_QMmTt{p:!fir.box<!fir.heap<i32>>}>>
Expand Down Expand Up @@ -258,8 +258,8 @@ func.func @_QMmPtest.fir() {
// composite is nested within another composite.
// CHECK-DAG: x#0 <-> x%p#0: MayAlias
// CHECK-DAG: x%x#0 <-> x%x%p#0: MayAlias
// CHECK-DAG: x.fir#0 <-> x%p.fir#0: MayAlias
// CHECK-DAG: x%x.fir#0 <-> x%x%p.fir#0: MayAlias
// CHECK-DAG: x.fir#0 <-> x%p.fir#0: PartialAlias
// CHECK-DAG: x%x.fir#0 <-> x%x%p.fir#0: PartialAlias

// The addresses of different components of the same composite do not alias.
//
Expand All @@ -274,9 +274,12 @@ func.func @_QMmPtest.fir() {
// CHECK-DAG: x%x#0 <-> x%i#0: MayAlias
// CHECK-DAG: x%p#0 <-> x%i#0: NoAlias
// CHECK-DAG: x%x#0 <-> x%p#0: MayAlias
// CHECK-DAG: x%x.fir#0 <-> x%i.fir#0: MayAlias
// CHECK-DAG: x%p.fir#0 <-> x%i.fir#0: NoAlias
// CHECK-DAG: x%x.fir#0 <-> x%p.fir#0: MayAlias
// CHECK-DAG: x%x.fir#0 <-> x%i.fir#0: PartialAlias

// NOTE: FIR AliasAnalysis can prove NoAlias, but LocalAliasAnalysis
// conservatively assumes PartialAlias.
// CHECK-DAG: x%p.fir#0 <-> x%i.fir#0: PartialAlias
// CHECK-DAG: x%x.fir#0 <-> x%p.fir#0: PartialAlias

func.func @_QMmPtest() {
%0 = fir.alloca !fir.type<_QMmTt2{x:!fir.type<_QMmTt1{p:!fir.box<!fir.ptr<i32>>}>,p:!fir.box<!fir.ptr<i32>>,i:i32}> {bindc_name = "x", uniq_name = "_QMmFtestEx"}
Expand Down
7 changes: 5 additions & 2 deletions mlir/include/mlir/Analysis/AliasAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ class AliasResult {
/// The two locations may or may not alias. This is the least precise
/// result.
MayAlias,
/// The two locations alias, but only due to a partial overlap.
/// The two locations overlap in some way, regardless of whether
/// they start at the same address or not.
PartialAlias,
/// The two locations precisely alias each other.
/// The two locations precisely alias each other, meaning that
/// they always start at exactly the same location.
/// This result does not imply that the pointers compare equal.
MustAlias,
};

Expand Down
10 changes: 9 additions & 1 deletion mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2288,7 +2288,7 @@ def SubViewOp : MemRef_OpWithOffsetSizesAndStrides<"subview", [
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs)>
];

let extraClassDeclaration = extraBaseClassDeclaration # [{
let extraClassDeclaration = extraBaseClassDeclaration#[{
/// Returns the type of the base memref operand.
MemRefType getSourceType() {
return ::llvm::cast<MemRefType>(getSource().getType());
Expand Down Expand Up @@ -2350,6 +2350,10 @@ def SubViewOp : MemRef_OpWithOffsetSizesAndStrides<"subview", [
/// If the shape of `value` cannot be rank-reduced to `desiredShape`, fail.
static FailureOr<Value> rankReduceIfNeeded(
OpBuilder &b, Location loc, Value value, ArrayRef<int64_t> desiredShape);

/// Return true iff the input and the resulting views start
/// at the same address.
bool isSameStart();
}];

let hasCanonicalizer = 1;
Expand Down Expand Up @@ -2459,6 +2463,10 @@ def MemRef_ViewOp : MemRef_Op<"view", [
operand_range getDynamicSizes() {
return {getSizes().begin(), getSizes().end()};
}

/// Return true iff the input and the resulting views start
/// at the same address.
bool isSameStart();
}];

let assemblyFormat = [{
Expand Down
52 changes: 38 additions & 14 deletions mlir/include/mlir/Interfaces/ViewLikeInterface.td
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,45 @@ def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> {
}];
let cppNamespace = "::mlir";

let methods = [
InterfaceMethod<
"Returns the source buffer from which the view is created.",
"::mlir::Value", "getViewSource">,
InterfaceMethod<
/*desc=*/[{ Returns the buffer which the view created. }],
/*retTy=*/"::mlir::Value",
/*methodName=*/"getViewDest",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
let methods =
[InterfaceMethod<
"Returns the source buffer from which the view is created.",
"::mlir::Value", "getViewSource">,
InterfaceMethod<
/*desc=*/[{ Returns the buffer which the view created. }],
/*retTy=*/"::mlir::Value",
/*methodName=*/"getViewDest",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op->getResult(0);
}]
>
];
}]>,
InterfaceMethod<
/*desc=*/
[{ Returns true iff the source buffer and the resulting view start at the same "address". }],
/*retTy=*/"bool",
/*methodName=*/"isSameStart",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return false;
}]>,
InterfaceMethod<
/*desc=*/
[{ Returns true iff the resulting view is a complete view of the source buffer, i.e. isSameStart() is true and the result has the same total size and is not a subview of the input. }],
/*retTy=*/"bool",
/*methodName=*/"isCompleteView",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return false;
}]>];

let verify = [{
auto concreteOp = ::mlir::cast<ConcreteOp>($_op);
// isCompleteView() == true implies isSameStart() == true.
return !concreteOp.isCompleteView() || concreteOp.isSameStart() ? ::mlir::success() : ::mlir::failure();
}];
}

def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface"> {
Expand Down
Loading