-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[flang] Follow memory source through more operations #66713
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
@llvm/pr-subscribers-flang-fir-hlfir ChangesAdd support for fir.box_addr, fir.array_corr, fir.coordinate, fir.embox, fir.rebox and fir.load.
Patch is 44.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66713.diff 5 Files Affected:
diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index ddde328f5cb5a4d..e96942abc22f3ee 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -20,7 +20,7 @@ namespace fir {
//===----------------------------------------------------------------------===//
// AliasAnalysis
//===----------------------------------------------------------------------===//
-class AliasAnalysis {
+struct AliasAnalysis {
// Structures to describe the memory source of a value.
/// Kind of the memory source referenced by a value.
@@ -81,7 +81,6 @@ class AliasAnalysis {
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const AliasAnalysis::Source &op);
-public:
/// Given two values, return their aliasing behavior.
mlir::AliasResult alias(mlir::Value lhs, mlir::Value rhs);
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 767ef2e8fa7dc08..6f8b8b441c5dfe5 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -36,6 +36,21 @@ static bool isDummyArgument(mlir::Value v) {
return blockArg.getOwner()->isEntryBlock();
}
+/// Temporary function to skip through all the no op operations
+/// TODO: Generalize support of fir.load
+static mlir::Value getOriginalDef(mlir::Value v) {
+ mlir::Operation *defOp;
+ bool breakFromLoop = false;
+ while (!breakFromLoop && (defOp = v.getDefiningOp())) {
+ llvm::TypeSwitch<Operation *>(defOp)
+ .Case<fir::ConvertOp>([&](fir::ConvertOp op) { v = op.getValue(); })
+ .Case<fir::DeclareOp, hlfir::DeclareOp>(
+ [&](auto op) { v = op.getMemref(); })
+ .Default([&](auto op) { breakFromLoop = true; });
+ }
+ return v;
+}
+
namespace fir {
void AliasAnalysis::Source::print(llvm::raw_ostream &os) const {
@@ -80,12 +95,27 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
llvm::dbgs() << " rhsSrc: " << rhsSrc << "\n";
llvm::dbgs() << "\n";);
+ // SourceKind::Unknown is set for the addresses wrapped in a global boxes.
+ // ie: fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
+ // Though nothing is known about them, they would only alias with targets or
+ // pointers
+ bool unknownSourceToNonTargetOrPointer = false;
+ if (lhsSrc.u != rhsSrc.u) {
+ if ((lhsSrc.kind == SourceKind::Unknown && !rhsSrc.isTargetOrPointer()) ||
+ (rhsSrc.kind == SourceKind::Unknown && !lhsSrc.isTargetOrPointer())) {
+ unknownSourceToNonTargetOrPointer = true;
+ }
+ }
+
// Indirect case currently not handled. Conservatively assume
// it aliases with everything
if (lhsSrc.kind == SourceKind::Indirect ||
lhsSrc.kind == SourceKind::Unknown ||
- rhsSrc.kind == SourceKind::Indirect || rhsSrc.kind == SourceKind::Unknown)
- return AliasResult::MayAlias;
+ rhsSrc.kind == SourceKind::Indirect ||
+ rhsSrc.kind == SourceKind::Unknown) {
+ if (!unknownSourceToNonTargetOrPointer)
+ return AliasResult::MayAlias;
+ }
if (lhsSrc.kind == rhsSrc.kind) {
if (lhsSrc.u == rhsSrc.u) {
@@ -103,9 +133,6 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
lhsSrc.kind == SourceKind::Global)
return AliasResult::NoAlias;
- assert(lhsSrc.kind == SourceKind::Argument &&
- "unexpected memory source kind");
-
// Dummy TARGET/POINTER arguments may alias.
if (lhsSrc.isTargetOrPointer() && rhsSrc.isTargetOrPointer())
return AliasResult::MayAlias;
@@ -122,7 +149,7 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
return AliasResult::NoAlias;
}
- assert(lhsSrc.kind != rhsSrc.kind && "memory source kinds must be the same");
+ assert(lhsSrc.kind != rhsSrc.kind && "memory source kinds must be different");
Source *src1, *src2;
if (lhsSrc.kind < rhsSrc.kind) {
@@ -133,18 +160,6 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
src2 = &lhsSrc;
}
- assert(src2->kind <= SourceKind::HostAssoc &&
- "unexpected memory source kind");
- if (src1->kind == SourceKind::Allocate)
- return AliasResult::NoAlias;
-
- assert(((src1->kind == SourceKind::Global &&
- (src2->kind == SourceKind::Argument ||
- src2->kind == SourceKind::HostAssoc)) ||
- (src1->kind == SourceKind::Argument &&
- src2->kind == SourceKind::HostAssoc)) &&
- "unexpected memory source kinds");
-
if (src1->kind == SourceKind::Argument &&
src2->kind == SourceKind::HostAssoc) {
// Treat the host entity as TARGET for the purpose of disambiguating
@@ -229,6 +244,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
mlir::Type ty;
bool breakFromLoop{false};
bool approximateSource{false};
+ bool followBoxAddr{false};
mlir::SymbolRefAttr global;
Source::Attributes attributes;
while (defOp && !breakFromLoop) {
@@ -244,22 +260,74 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
v = op->getOperand(0);
defOp = v.getDefiningOp();
})
+ .Case<fir::BoxAddrOp>([&](auto op) {
+ v = op->getOperand(0);
+ defOp = v.getDefiningOp();
+ if (mlir::isa<fir::BaseBoxType>(v.getType()))
+ followBoxAddr = true;
+ })
+ .Case<fir::ArrayCoorOp, fir::CoordinateOp>([&](auto op) {
+ v = op->getOperand(0);
+ defOp = v.getDefiningOp();
+ if (mlir::isa<fir::BaseBoxType>(v.getType()))
+ followBoxAddr = true;
+ approximateSource = true;
+ })
+ .Case<fir::EmboxOp, fir::ReboxOp>([&](auto op) {
+ if (followBoxAddr) {
+ v = op->getOperand(0);
+ defOp = v.getDefiningOp();
+ } else
+ breakFromLoop = true;
+ })
.Case<fir::LoadOp>([&](auto op) {
- // No further tracking for addresses loaded from memory (e.g. a box)
- // right now.
+ if (followBoxAddr && mlir::isa<fir::BaseBoxType>(op.getType())) {
+ // For now, support the load of an argument or fir.address_of
+ // TODO: generalize to all operations (in particular fir.alloca and
+ // fir.allocmem)
+ auto def = getOriginalDef(op.getMemref());
+ if (isDummyArgument(def) ||
+ def.template getDefiningOp<fir::AddrOfOp>()) {
+ v = def;
+ defOp = v.getDefiningOp();
+ return;
+ }
+ }
+ // No further tracking for addresses loaded from memory for now.
type = SourceKind::Indirect;
breakFromLoop = true;
})
.Case<fir::AddrOfOp>([&](auto op) {
// Address of a global scope object.
- type = SourceKind::Global;
ty = v.getType();
+
+ // When the global is a
+ // fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
+ // or
+ // fir.global @_QMpointersEp : !fir.box<!fir.heap<f32>>
+ //
+ // and when following through the wrapped address, capture
+ // the fact that there is nothing known about it. Therefore setting
+ // the source to unknown.
+ //
+ // When not following the wrapped address, then consider the address
+ // of the box, which has nothing to do with the wrapped address and
+ // lies in the global memory space.
+ if (followBoxAddr &&
+ mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(ty)))
+ type = SourceKind::Unknown;
+ else
+ type = SourceKind::Global;
+
if (fir::valueHasFirAttribute(v,
fir::GlobalOp::getTargetAttrNameStr()))
attributes.set(Attribute::Target);
+ // TODO: Take followBoxAddr into account when setting the pointer
+ // attribute
if (Source::isPointerReference(ty))
attributes.set(Attribute::Pointer);
+
global = llvm::cast<fir::AddrOfOp>(op).getSymbol();
breakFromLoop = true;
})
@@ -278,7 +346,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
breakFromLoop = true;
return;
}
-
+ // TODO: Look for the fortran attributes present on the operation
// Track further through the operand
v = op.getMemref();
defOp = v.getDefiningOp();
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
index ca720cf0ec813a5..31459ef21d947c3 100644
--- a/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
@@ -11,8 +11,11 @@
// p1.addr and p2.addr could both be wrapped inside boxes
// CHECK-DAG: p1.addr#0 <-> boxp1.addr#0: MayAlias
// CHECK-DAG: p2.addr#0 <-> boxp1.addr#0: MayAlias
-// CHECK-DAG: p1.addr#0 <-> arg2.addr#0: MayAlias
-// CHECK-DAG: p2.addr#0 <-> arg2.addr#0: MayAlias
+
+// TODO: To really see aliasing, we should be looking at a load of p1.addr
+// p1.addr is just a local address holding the address to the data
+// CHECK-DAG: p1.addr#0 <-> arg2.addr#0: NoAlias
+// CHECK-DAG: p2.addr#0 <-> arg2.addr#0: NoAlias
// p1.addr and p2.addr are the result of an allocation
// They cannot physically alias with an argument
@@ -41,7 +44,7 @@
// pointer arguments
// CHECK-DAG: arg2.addr#0 <-> func.region0#0: MayAlias
// CHECK-DAG: arg2.addr#0 <-> func.region0#1: MayAlias
-// CHECK-DAG: arg2.addr#0 <-> func.region0#2: MayAlias
+// CHECK-DAG: arg2.addr#0 <-> func.region0#2: MustAlias
// CHECK-DAG: boxp1.addr#0 <-> arg2.addr#0: MayAlias
func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<f32> {fir.bindc_name = "v2", fir.target}, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
@@ -99,7 +102,7 @@ func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %a
// CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias
// CHECK-DAG: func.region0#0 <-> func.region0#2: MayAlias
-func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>>, %arg2: !fir.ref<!fir.ptr<f32>> ) attributes {test.ptr = "func"} {
+func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>>, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
return
}
@@ -131,9 +134,14 @@ func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %
// CHECK-DAG: p#0 <-> func.region0#0: MayAlias
// CHECK-DAG: p#0 <-> func.region0#1: NoAlias
-// FIXME: p and p1 are pointers, they cannot alias with a wrapped address.
-// Only the addresses they wrap could alias with the address wrapped by the box
-// CHECK-DAG: p#0 <-> box.addr#0: MayAlias
+// p could be pointing to var2
+// var2, being a target, could also be passed as argument arg0
+
+// This was the wrong question to ask. We are asking if the address of box _QMpointersEp can
+// alias with the wrapped scalar _QFEvar2. We meant box_addr of _QMpointersEp
+// CHECK-DAG: p#0 <-> box.addr#0: NoAlias
+
+// TODO: Still need to handle more gracefully the difference between !fir.ref<!fir.box<>> and !fir.box<>
// CHECK-DAG: box.addr#0 <-> func.region0#0: MayAlias
// var2, although it is a target, cannot alias with p
@@ -141,14 +149,14 @@ func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %
// CHECK-DAG: var2#0 <-> p#0: NoAlias
// It can alias with p1, if p1 is a pointer component
// CHECK-DAG: var2#0 <-> func.region0#0: MayAlias
-// It can alias with a box.addr
-// CHECK-DAG: var2#0 <-> box.addr#0: MayAlias
+// It is the same as box.addr
+// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias
// A global may not alias with a dummy
// CHECK-DAG: var2#0 <-> func.region0#1: NoAlias
-// FIXME: a pointer may only alias with a target but arg1 is a regular dummy
-// CHECK-DAG: box.addr#0 <-> func.region0#1: MayAlias
+// A pointer may only alias with a target but arg1 is a regular dummy
+// CHECK-DAG: box.addr#0 <-> func.region0#1: NoAlias
// Dummy argument do not alias
// CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-5.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-5.fir
new file mode 100644
index 000000000000000..062413858691204
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-5.fir
@@ -0,0 +1,671 @@
+// 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
+
+// CHECK-LABEL: Testing : "_QPtest1"
+// CHECK: arraya(ii)#0 <-> arrayc(ii)#0: NoAlias
+
+// Generated from
+// subroutine test1(arrayA, arrayB, arrayC, N)
+// integer, dimension(:) :: arrayA, arrayB, arrayC
+// integer N
+// do ii = 1, N
+// arrayC(ii) = arrayB(ii) + arrayA(ii)
+// end do
+// end subroutine
+
+func.func @_QPtest1(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arraya"}, %arg1: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arrayb"}, %arg2: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arrayc"}, %arg3: !fir.ref<i32> {fir.bindc_name = "n"}) {
+ %c1 = arith.constant 1 : index
+ %c1_i64 = arith.constant 1 : i64
+ %0 = fir.alloca i32 {bindc_name = "ii", uniq_name = "_QFtest1Eii"}
+ %1 = fir.load %arg3 : !fir.ref<i32>
+ %2 = fir.convert %1 : (i32) -> index
+ %3 = fir.convert %c1 : (index) -> i32
+ %4:2 = fir.do_loop %arg4 = %c1 to %2 step %c1 iter_args(%arg5 = %3) -> (index, i32) {
+ fir.store %arg5 to %0 : !fir.ref<i32>
+ %5 = fir.load %0 : !fir.ref<i32>
+ %6 = fir.convert %5 : (i32) -> i64
+ %7 = arith.subi %6, %c1_i64 : i64
+ %8 = fir.coordinate_of %arg1, %7 : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ %9 = fir.load %8 : !fir.ref<i32>
+ %10 = fir.coordinate_of %arg0, %7 {test.ptr = "arraya(ii)"} : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ %11 = fir.load %10 : !fir.ref<i32>
+ %12 = arith.addi %9, %11 : i32
+ %13 = fir.coordinate_of %arg2, %7 {test.ptr = "arrayc(ii)"} : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ fir.store %12 to %13 : !fir.ref<i32>
+ %14 = arith.addi %arg4, %c1 : index
+ %15 = fir.load %0 : !fir.ref<i32>
+ %16 = arith.addi %15, %3 : i32
+ fir.result %14, %16 : index, i32
+ }
+ fir.store %4#1 to %0 : !fir.ref<i32>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: Testing : "_QPtest3"
+// CHECK: arraya(ii)#0 <-> arrayc(ii)#0: MayAlias
+
+// subroutine test3(arrayA, arrayB, arrayC, N)
+// integer, dimension(:), target :: arrayA
+// integer, dimension(:) :: arrayB
+// integer, dimension(:), pointer :: arrayC
+// do ii = 1, N
+// arrayC(ii) = arrayB(ii) + arrayA(ii)
+// end do
+// end subroutine
+
+func.func @_QPtest3(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arraya", fir.target}, %arg1: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arrayb"}, %arg2: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "arrayc"}, %arg3: !fir.ref<i32> {fir.bindc_name = "n"}) {
+ %c1 = arith.constant 1 : index
+ %c0 = arith.constant 0 : index
+ %c1_i64 = arith.constant 1 : i64
+ %0 = fir.alloca i32 {bindc_name = "ii", uniq_name = "_QFtest3Eii"}
+ %1 = fir.load %arg3 : !fir.ref<i32>
+ %2 = fir.convert %1 : (i32) -> index
+ %3 = fir.convert %c1 : (index) -> i32
+ %4:2 = fir.do_loop %arg4 = %c1 to %2 step %c1 iter_args(%arg5 = %3) -> (index, i32) {
+ fir.store %arg5 to %0 : !fir.ref<i32>
+ %5 = fir.load %0 : !fir.ref<i32>
+ %6 = fir.convert %5 : (i32) -> i64
+ %7 = arith.subi %6, %c1_i64 : i64
+ %8 = fir.coordinate_of %arg1, %7 : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ %9 = fir.load %8 : !fir.ref<i32>
+ %10 = fir.coordinate_of %arg0, %7 {test.ptr = "arraya(ii)"} : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ %11 = fir.load %10 : !fir.ref<i32>
+ %12 = arith.addi %9, %11 : i32
+ %13 = fir.load %arg2 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+ %14:3 = fir.box_dims %13, %c0 : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)
+ %15 = fir.convert %14#0 : (index) -> i64
+ %16 = arith.subi %6, %15 : i64
+ %17 = fir.coordinate_of %13, %16 {test.ptr = "arrayc(ii)"} : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, i64) -> !fir.ref<i32>
+ fir.store %12 to %17 : !fir.ref<i32>
+ %18 = arith.addi %arg4, %c1 : index
+ %19 = fir.load %0 : !fir.ref<i32>
+ %20 = arith.addi %19, %3 : i32
+ fir.result %18, %20 : index, i32
+ }
+ fir.store %4#1 to %0 : !fir.ref<i32>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: Testing : "_QMtest4Ptest"
+// CHECK: arraya(ii)#0 <-> arrayc(ii)#0: NoAlias
+
+// module test4
+// integer, dimension(:), allocatable :: arrayA
+// integer, dimension(:), allocatable :: arrayB
+// integer, dimension(:), allocatable :: arrayC
+// integer :: N
+// contains
+// subroutine test
+// do ii = 1, N
+// arrayC(ii) = arrayB(ii) + arrayA(ii)
+// end do
+// end subroutine
+// endmodule
+
+fir.global @_QMtest4Earraya : !fir.box<!fir.heap<!fir.array<?xi32>>>
+fir.global @_QMtest4Earrayb : !fir.box<!fir.heap<!fir.array<?xi32>>>
+fir.global @_QMtest4Earrayc : !fir.box<!fir.heap<!fir.array<?xi32>>>
+fir.global @_QMtest4En : i32
+
+func.func @_QMtest4Ptest() {
+ %c1 = arith.constant 1 : index
+ %c0 = arith.constant 0 : index
+ %0 = fir.address_of(@_QMtest4Earraya) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %1 = fir.address_of(@_QMtest4Earrayb) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %2 = fir.address_of(@_QMtest4Earrayc) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %3 = fir.address_of(@_QMtest4En) : !fir.ref<i32>
+ %4 = fir.alloca i32 {bindc_name = "ii", uniq_name = "_QMtest4FtestEii"}
+ %5 = fir.load %3 : !fir.ref<i32>
+ %6 = fir.convert %5 : (i32) -> index
+ %7 = fir.convert %c1 : (index) -> i32
+ %8:2 = fir.do_loop %arg0 = %c1 to %6 step %c1 iter_args(%arg1 = %7) -> (index, i32) {
+ fir.store %arg1 to %4 : !fir.ref<i32>
+ %9 = fir.load %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %10:3 = fir.box_dims %9, %c0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
+ %11 = fir.box_addr %9 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+ %12 = fir.load %4 : !fir.ref<i32>
+ %13 = fir.convert %12 : (i32) -> i64
+ %14 = fir.convert %10#0 : (index) -> i64
+ %15 = arith.subi %13, %14 : i64
+ %16 = fir.coordinate_of %11, %15 : (!fir.heap<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ %17 = fir.load %16 : !fir.ref<i32>
+ %18 = fir.load %0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %19:3 = fir.box_dims %18, %c0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
+ %20 = fir.box_addr %18 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+ %21 = fir.convert %19#0 : (index) -> i64
+ %22 = arith.subi %13, %21 : i64
+ %23 = fir.coordinate_of %20, %22 {test.ptr = "arraya(ii)"} : (!fir.heap<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ %24 = fir.load %23 : !fir.ref<i32>
+ %25 = arith.addi %17, %24 : i32
+ %26 = fir.load %2 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %27:3 = fir.box_dims %26, %c0 : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
+ %28 = fir.box_addr %26 : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+ %29 = fir.convert %27#0 : (index) -> i64
+ %30 = arith.subi %13, %29 : i64
+ %31 = fir.coordinate_of %28, %30 {test.ptr = "arrayc(ii)"} : (!fir.heap<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ fir.store %25 to %31 : !fir.ref<i32>
+ %32 = arith.addi %arg0, %c1 : index
+ %33 = fir.load %4 : !fir.ref<i32>
+ %34 = arith.addi %33, %7 : i32
+ fir.result %32, %34 : index, i32
+ }
+ fir.store %8#1 to %4 : !fir.ref<i32>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: Testing : "_QMtest5Ptest"
+// CHECK: arraya(ii)#0 <-> arrayc(ii)...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! Thanks! Just one comment.
@@ -80,12 +95,27 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) { | |||
llvm::dbgs() << " rhsSrc: " << rhsSrc << "\n"; | |||
llvm::dbgs() << "\n";); | |||
|
|||
// SourceKind::Unknown is set for the addresses wrapped in a global boxes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there not other situations where we get SourceKind::Unknown
? For example, when encountering an unsupported operation.
I think it would be better to keep SourceKind::Unknown
as a state for "we don't know what's going on, conservatively assume it aliases with everything", then set these global pointers to a new state representing a "known unknown" - we don't know much about them but in a controlled way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that there is a bit of overlap between these unknowns and the general unknowns. If things are truly unknown, how can we know that they are not target or pointer? I had started up with the introduction of a new SourceKind but early feedback deemed it too complex. However from this baseline, I believe it would be reasonable to reintroduce it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! Looks great!
Add support for fir.box_addr, fir.array_corr, fir.coordinate, fir.embox, fir.rebox and fir.load.
followBoxAddr
determine whether the analysis should apply to the address of the box or the address wrapped by the box.