Skip to content

[flang][hlfir] Make alias analysis trace through box designators. #67353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 25, 2023
Merged
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
14 changes: 14 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ def fir_FortranVariableOpInterface : OpInterface<"FortranVariableOpInterface"> {
fir::FortranVariableFlagsEnum::host_assoc);
}

/// Is this variable a Fortran target?
bool isTarget() {
auto attrs = getFortranAttrs();
return attrs && bitEnumContainsAny(*attrs,
fir::FortranVariableFlagsEnum::target);
}

/// Is this variable a Fortran intent(in)?
bool isIntentIn() {
auto attrs = getFortranAttrs();
return attrs && bitEnumContainsAny(*attrs,
fir::FortranVariableFlagsEnum::intent_in);
}

/// Interface verifier imlementation for declare operations.
mlir::LogicalResult verifyDeclareLikeOpImpl(mlir::Value memRef);

Expand Down
26 changes: 25 additions & 1 deletion flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,26 @@ ModRefResult AliasAnalysis::getModRef(Operation *op, Value location) {
return result;
}

AliasAnalysis::Source::Attributes
getAttrsFromVariable(fir::FortranVariableOpInterface var) {
AliasAnalysis::Source::Attributes attrs;
if (var.isTarget())
attrs.set(AliasAnalysis::Attribute::Target);
if (var.isPointer())
attrs.set(AliasAnalysis::Attribute::Pointer);
if (var.isIntentIn())
attrs.set(AliasAnalysis::Attribute::IntentIn);

return attrs;
}

AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
auto *defOp = v.getDefiningOp();
SourceKind type{SourceKind::Unknown};
mlir::Type ty;
bool breakFromLoop{false};
bool approximateSource{false};
bool followBoxAddr{false};
bool followBoxAddr{mlir::isa<fir::BaseBoxType>(v.getType())};
mlir::SymbolRefAttr global;
Source::Attributes attributes;
while (defOp && !breakFromLoop) {
Expand Down Expand Up @@ -334,6 +347,15 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
})
.Case<hlfir::DeclareOp, fir::DeclareOp>([&](auto op) {
auto varIf = llvm::cast<fir::FortranVariableOpInterface>(defOp);
// While going through a declare operation collect
// the variable attributes from it. Right now, some
// of the attributes are duplicated, e.g. a TARGET dummy
// argument has the target attribute both on its declare
// operation and on the entry block argument.
// In case of host associated use, the declare operation
// is the only carrier of the variable attributes,
// so we have to collect them here.
attributes |= getAttrsFromVariable(varIf);
if (varIf.isHostAssoc()) {
// Do not track past such DeclareOp, because it does not
// currently provide any useful information. The host associated
Expand Down Expand Up @@ -364,6 +386,8 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
// because of this limitation, we need to make sure we never return
// MustAlias after going through a designate operation
approximateSource = true;
if (mlir::isa<fir::BaseBoxType>(v.getType()))
followBoxAddr = true;
})
.Default([&](auto op) {
defOp = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Analysis/AliasAnalysis/alias-analysis-6.fir
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))'
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' 2>&1 | FileCheck %s

// CHECK: test_y(1)#0 <-> test_x(1)#0: MayAlias
func.func @_QPtest(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "y"}) {
Expand Down
99 changes: 99 additions & 0 deletions flang/test/Analysis/AliasAnalysis/alias-analysis-7.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' 2>&1 | FileCheck %s

// leslie3d case with two allocatable module variables
// that cannot alias:
// module les3d_data
// implicit real*8 (a-h,o-z)
// integer imax, jmax, kmax
// double precision,allocatable,dimension(:,:,:,:,:) :: q
// double precision,allocatable,dimension(:,:,:,:) :: du
// end module les3d_data
// subroutine update()
// use les3d_data
// implicit real*8(a-h,o-z)
// i2 = imax - 1
// do k = 1, kmax - 1
// do j = 1, jmax - 1
// q(1:i2,j,k,1,m) = (q(1:i2,j,k,1,m) + du(1:i2,j,k,1))
// end do
// end do
// end subroutine update

// CHECK: allocatable_mod1#0 <-> allocatable_mod2#0: NoAlias
func.func @_QPupdate() {
%c1 = arith.constant 1 : index
%c0 = arith.constant 0 : index
%c1_i32 = arith.constant 1 : i32
%0 = fir.address_of(@_QMles3d_dataEdu) : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>
%1:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMles3d_dataEdu"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>)
%2 = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QFupdateEi2"}
%3:2 = hlfir.declare %2 {uniq_name = "_QFupdateEi2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%4 = fir.address_of(@_QMles3d_dataEimax) : !fir.ref<i32>
%5:2 = hlfir.declare %4 {uniq_name = "_QMles3d_dataEimax"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%6 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFupdateEj"}
%7:2 = hlfir.declare %6 {uniq_name = "_QFupdateEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%8 = fir.address_of(@_QMles3d_dataEjmax) : !fir.ref<i32>
%9:2 = hlfir.declare %8 {uniq_name = "_QMles3d_dataEjmax"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%10 = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFupdateEk"}
%11:2 = hlfir.declare %10 {uniq_name = "_QFupdateEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%12 = fir.address_of(@_QMles3d_dataEkmax) : !fir.ref<i32>
%13:2 = hlfir.declare %12 {uniq_name = "_QMles3d_dataEkmax"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%14 = fir.alloca i32 {bindc_name = "m", uniq_name = "_QFupdateEm"}
%15:2 = hlfir.declare %14 {uniq_name = "_QFupdateEm"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%16 = fir.address_of(@_QMles3d_dataEq) : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>
%17:2 = hlfir.declare %16 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMles3d_dataEq"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>)
%18 = fir.load %5#0 : !fir.ref<i32>
%19 = arith.subi %18, %c1_i32 : i32
hlfir.assign %19 to %3#0 : i32, !fir.ref<i32>
%20 = fir.load %13#0 : !fir.ref<i32>
%21 = arith.subi %20, %c1_i32 : i32
%22 = fir.convert %21 : (i32) -> index
%23 = fir.convert %c1 : (index) -> i32
%24:2 = fir.do_loop %arg0 = %c1 to %22 step %c1 iter_args(%arg1 = %23) -> (index, i32) {
fir.store %arg1 to %11#1 : !fir.ref<i32>
%25 = fir.load %9#0 : !fir.ref<i32>
%26 = arith.subi %25, %c1_i32 : i32
%27 = fir.convert %26 : (i32) -> index
%28:2 = fir.do_loop %arg2 = %c1 to %27 step %c1 iter_args(%arg3 = %23) -> (index, i32) {
fir.store %arg3 to %7#1 : !fir.ref<i32>
%32 = fir.load %17#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>
%33 = fir.load %3#0 : !fir.ref<i32>
%34 = fir.convert %33 : (i32) -> index
%35 = arith.cmpi sgt, %34, %c0 : index
%36 = arith.select %35, %34, %c0 : index
%37 = fir.load %7#0 : !fir.ref<i32>
%38 = fir.convert %37 : (i32) -> i64
%39 = fir.load %11#0 : !fir.ref<i32>
%40 = fir.convert %39 : (i32) -> i64
%41 = fir.load %15#0 : !fir.ref<i32>
%42 = fir.convert %41 : (i32) -> i64
%43 = fir.shape %36 : (index) -> !fir.shape<1>
%44 = hlfir.designate %32 (%c1:%34:%c1, %38, %40, %c1, %42) shape %43 {test.ptr = "allocatable_mod1"} : (!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>, index, index, index, i64, i64, index, i64, !fir.shape<1>) -> !fir.box<!fir.array<?xf64>>
%45 = fir.load %1#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>
%46 = hlfir.designate %45 (%c1:%34:%c1, %38, %40, %c1) shape %43 {test.ptr = "allocatable_mod2"} : (!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>, index, index, index, i64, i64, index, !fir.shape<1>) -> !fir.box<!fir.array<?xf64>>
%47 = hlfir.elemental %43 unordered : (!fir.shape<1>) -> !hlfir.expr<?xf64> {
^bb0(%arg4: index):
%51 = hlfir.designate %44 (%arg4) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
%52 = hlfir.designate %46 (%arg4) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
%53 = fir.load %51 : !fir.ref<f64>
%54 = fir.load %52 : !fir.ref<f64>
%55 = arith.addf %53, %54 fastmath<fast> : f64
%56 = hlfir.no_reassoc %55 : f64
hlfir.yield_element %56 : f64
}
hlfir.assign %47 to %44 : !hlfir.expr<?xf64>, !fir.box<!fir.array<?xf64>>
hlfir.destroy %47 : !hlfir.expr<?xf64>
%48 = arith.addi %arg2, %c1 : index
%49 = fir.load %7#1 : !fir.ref<i32>
%50 = arith.addi %49, %23 : i32
fir.result %48, %50 : index, i32
}
fir.store %28#1 to %7#1 : !fir.ref<i32>
%29 = arith.addi %arg0, %c1 : index
%30 = fir.load %11#1 : !fir.ref<i32>
%31 = arith.addi %30, %23 : i32
fir.result %29, %31 : index, i32
}
fir.store %24#1 to %11#1 : !fir.ref<i32>
return
}
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,7 @@ func.func @_QFtest8Pinner(%arg0: !fir.ref<tuple<!fir.box<!fir.array<10xi32>>>> {
// end subroutine inner
// end subroutine test9

// FIXME: 'g' is classified as Indirect access leading to a conservative reply:
// CHECK: test9_g(1)#0 <-> test9_x(1)#0: MayAlias
// CHECK: test9_g(1)#0 <-> test9_x(1)#0: NoAlias
func.func @_QFtest9Pinner(%arg0: !fir.ref<tuple<!fir.box<!fir.array<10xi32>>>> {fir.host_assoc}) attributes {fir.internal_proc} {
%0 = fir.address_of(@_QMglobalsEg) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
%1:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMglobalsEg"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>)
Expand Down
102 changes: 102 additions & 0 deletions flang/test/HLFIR/opt-bufferization-leslie3d.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// RUN: fir-opt --opt-bufferization %s | FileCheck %s

// leslie3d case with two allocatable module variables
// that cannot alias:
// module les3d_data
// implicit real*8 (a-h,o-z)
// integer imax, jmax, kmax
// double precision,allocatable,dimension(:,:,:,:,:) :: q
// double precision,allocatable,dimension(:,:,:,:) :: du
// end module les3d_data
// subroutine update()
// use les3d_data
// implicit real*8(a-h,o-z)
// i2 = imax - 1
// do k = 1, kmax - 1
// do j = 1, jmax - 1
// q(1:i2,j,k,1,m) = (q(1:i2,j,k,1,m) + du(1:i2,j,k,1))
// end do
// end do
// end subroutine update

func.func @_QPupdate() {
%c1 = arith.constant 1 : index
%c0 = arith.constant 0 : index
%c1_i32 = arith.constant 1 : i32
%0 = fir.address_of(@_QMles3d_dataEdu) : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>
%1:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMles3d_dataEdu"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>)
%2 = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QFupdateEi2"}
%3:2 = hlfir.declare %2 {uniq_name = "_QFupdateEi2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%4 = fir.address_of(@_QMles3d_dataEimax) : !fir.ref<i32>
%5:2 = hlfir.declare %4 {uniq_name = "_QMles3d_dataEimax"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%6 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFupdateEj"}
%7:2 = hlfir.declare %6 {uniq_name = "_QFupdateEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%8 = fir.address_of(@_QMles3d_dataEjmax) : !fir.ref<i32>
%9:2 = hlfir.declare %8 {uniq_name = "_QMles3d_dataEjmax"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%10 = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFupdateEk"}
%11:2 = hlfir.declare %10 {uniq_name = "_QFupdateEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%12 = fir.address_of(@_QMles3d_dataEkmax) : !fir.ref<i32>
%13:2 = hlfir.declare %12 {uniq_name = "_QMles3d_dataEkmax"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%14 = fir.alloca i32 {bindc_name = "m", uniq_name = "_QFupdateEm"}
%15:2 = hlfir.declare %14 {uniq_name = "_QFupdateEm"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%16 = fir.address_of(@_QMles3d_dataEq) : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>
%17:2 = hlfir.declare %16 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMles3d_dataEq"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>)
%18 = fir.load %5#0 : !fir.ref<i32>
%19 = arith.subi %18, %c1_i32 : i32
hlfir.assign %19 to %3#0 : i32, !fir.ref<i32>
%20 = fir.load %13#0 : !fir.ref<i32>
%21 = arith.subi %20, %c1_i32 : i32
%22 = fir.convert %21 : (i32) -> index
%23 = fir.convert %c1 : (index) -> i32
%24:2 = fir.do_loop %arg0 = %c1 to %22 step %c1 iter_args(%arg1 = %23) -> (index, i32) {
fir.store %arg1 to %11#1 : !fir.ref<i32>
%25 = fir.load %9#0 : !fir.ref<i32>
%26 = arith.subi %25, %c1_i32 : i32
%27 = fir.convert %26 : (i32) -> index
%28:2 = fir.do_loop %arg2 = %c1 to %27 step %c1 iter_args(%arg3 = %23) -> (index, i32) {
fir.store %arg3 to %7#1 : !fir.ref<i32>
%32 = fir.load %17#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>>
%33 = fir.load %3#0 : !fir.ref<i32>
%34 = fir.convert %33 : (i32) -> index
%35 = arith.cmpi sgt, %34, %c0 : index
%36 = arith.select %35, %34, %c0 : index
%37 = fir.load %7#0 : !fir.ref<i32>
%38 = fir.convert %37 : (i32) -> i64
%39 = fir.load %11#0 : !fir.ref<i32>
%40 = fir.convert %39 : (i32) -> i64
%41 = fir.load %15#0 : !fir.ref<i32>
%42 = fir.convert %41 : (i32) -> i64
%43 = fir.shape %36 : (index) -> !fir.shape<1>
%44 = hlfir.designate %32 (%c1:%34:%c1, %38, %40, %c1, %42) shape %43 : (!fir.box<!fir.heap<!fir.array<?x?x?x?x?xf64>>>, index, index, index, i64, i64, index, i64, !fir.shape<1>) -> !fir.box<!fir.array<?xf64>>
%45 = fir.load %1#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>>
%46 = hlfir.designate %45 (%c1:%34:%c1, %38, %40, %c1) shape %43 : (!fir.box<!fir.heap<!fir.array<?x?x?x?xf64>>>, index, index, index, i64, i64, index, !fir.shape<1>) -> !fir.box<!fir.array<?xf64>>
%47 = hlfir.elemental %43 unordered : (!fir.shape<1>) -> !hlfir.expr<?xf64> {
^bb0(%arg4: index):
%51 = hlfir.designate %44 (%arg4) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
%52 = hlfir.designate %46 (%arg4) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
%53 = fir.load %51 : !fir.ref<f64>
%54 = fir.load %52 : !fir.ref<f64>
%55 = arith.addf %53, %54 fastmath<fast> : f64
%56 = hlfir.no_reassoc %55 : f64
hlfir.yield_element %56 : f64
}
hlfir.assign %47 to %44 : !hlfir.expr<?xf64>, !fir.box<!fir.array<?xf64>>
hlfir.destroy %47 : !hlfir.expr<?xf64>
%48 = arith.addi %arg2, %c1 : index
%49 = fir.load %7#1 : !fir.ref<i32>
%50 = arith.addi %49, %23 : i32
fir.result %48, %50 : index, i32
}
fir.store %28#1 to %7#1 : !fir.ref<i32>
%29 = arith.addi %arg0, %c1 : index
%30 = fir.load %11#1 : !fir.ref<i32>
%31 = arith.addi %30, %23 : i32
fir.result %29, %31 : index, i32
}
fir.store %24#1 to %11#1 : !fir.ref<i32>
return
}
// CHECK-LABEL: func.func @_QPupdate() {
// CHECK-NOT: hlfir.assign {{.*}}!fir.box<!fir.array<?xf64>>
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : f64, !fir.ref<f64>
// CHECK-NOT: hlfir.assign {{.*}}!fir.box<!fir.array<?xf64>>
24 changes: 10 additions & 14 deletions flang/test/HLFIR/opt-variable-assign.fir
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func.func @_QPtest4(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {f
// CHECK-NOT: hlfir.assign


// TODO: LHS is a pointer, but RHS is a subroutine local,
// LHS is a pointer, but RHS is a subroutine local,
// so they cannot alias.
func.func @_QPtest5(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) {
%c0 = arith.constant 0 : index
Expand Down Expand Up @@ -220,13 +220,13 @@ func.func @_QPtest5(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fi
}
// CHECK-LABEL: func.func @_QPtest5(
// CHECK-NOT: hlfir.assign
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : !fir.ref<!fir.array<3x3xf32>>, !fir.box<!fir.array<?x?xf32>>
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : f32, !fir.ref<f32>
// CHECK-NOT: hlfir.assign
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : !fir.ref<!fir.array<3x3xf32>>, !fir.box<!fir.ptr<!fir.array<?x?xf32>>>
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : f32, !fir.ref<f32>
// CHECK-NOT: hlfir.assign


// TODO: RHS is a pointer, but LHS is a subroutine local,
// RHS is a pointer, but LHS is a subroutine local,
// so they cannot alias.
func.func @_QPtest6(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) {
%c1 = arith.constant 1 : index
Expand Down Expand Up @@ -261,20 +261,14 @@ func.func @_QPtest6(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>> {fi
}
// CHECK-LABEL: func.func @_QPtest6(
// CHECK-NOT: hlfir.assign
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : !fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<3x3xf32>>
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : f32, !fir.ref<f32>
// CHECK-NOT: hlfir.assign
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : !fir.box<!fir.ptr<!fir.array<?x?xf32>>>, !fir.ref<!fir.array<3x3xf32>>
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : f32, !fir.ref<f32>
// CHECK-NOT: hlfir.assign


// TODO: LHS and RHS do not alias, and the assignment cannot
// LHS and RHS do not alias, and the assignment cannot
// allocate/reallocate LHS, so we should be able to optimize.
// The box load blocks alias analysis.
// subroutine test7(x)
// real, allocatable :: x(:,:)
// real :: y(3,3)
// x(:,:) = y(:,:)
// end subroutine test7
func.func @_QPtest7(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {fir.bindc_name = "x"}) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
Expand Down Expand Up @@ -305,4 +299,6 @@ func.func @_QPtest7(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> {f
return
}
// CHECK-LABEL: func.func @_QPtest7(
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : !fir.ref<!fir.array<3x3xf32>>, !fir.box<!fir.array<?x?xf32>>
// CHECK-NOT: hlfir.assign
// CHECK: hlfir.assign %{{.*}} to %{{.*}} : f32, !fir.ref<f32>
// CHECK-NOT: hlfir.assign