// Check AliasAnalysis for pointer components. // // Throughout this test, The ".fir" suffix on symbols indicates a version of the // MLIR after convert-hlfir-to-fir. A key difference is that component access // is via fir.coordinate_of instead of hlfir.designate. We would like alias // analysis results to be the same in both versions. // RUN: fir-opt %s -split-input-file -o /dev/null --mlir-disable-threading \ // RUN: -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' \ // RUN: 2>&1 | FileCheck -match-full-lines %s // module m // type t // type(t), pointer :: next // integer :: i // end type // contains // subroutine foo(x, y) // type(t) :: x, y // integer :: i1, i2 // i1 = x%next%i // x = y // i2 = x%next%i // end subroutine // end module // CHECK-LABEL: Testing : "_QMmPfoo" // x and y are non pointer, non target argument and therefore do not alias. // CHECK-DAG: x#0 <-> y#0: NoAlias // CHECK-DAG: x.fir#0 <-> y.fir#0: NoAlias // y is not a pointer object and therefore does not alias with the x%next // component. Also assigning x to y would not modify x.next // CHECK-DAG: y#0 <-> xnext1#0: NoAlias // CHECK-DAG: y#0 <-> xnext2#0: NoAlias // CHECK-DAG: y.fir#0 <-> xnext1.fir#0: NoAlias // CHECK-DAG: y.fir#0 <-> xnext2.fir#0: NoAlias // We need to catch the fact that assigning y to x will modify xnext. // The only side-effect between the 2 loads of x.next is the assignment to x, // 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 // 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#0 <-> ynext#0: NoAlias // CHECK-DAG: xnext1.fir#0 <-> ynext.fir#0: NoAlias func.func @_QMmPfoo(%arg0: !fir.ref>>,i:i32}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>,i:i32}>> {fir.bindc_name = "y"}) { %0 = fir.alloca i32 {bindc_name = "i1", uniq_name = "_QMmFfooEi1"} %1:2 = hlfir.declare %0 {uniq_name = "_QMmFfooEi1"} : (!fir.ref) -> (!fir.ref, !fir.ref) %2 = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QMmFfooEi2"} %3:2 = hlfir.declare %2 {uniq_name = "_QMmFfooEi2"} : (!fir.ref) -> (!fir.ref, !fir.ref) %4:2 = hlfir.declare %arg0 {uniq_name = "_QMmFfooEx", test.ptr = "x"} : (!fir.ref>>,i:i32}>>) -> (!fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>>) %5:2 = hlfir.declare %arg1 {uniq_name = "_QMmFfooEy", test.ptr = "y"} : (!fir.ref>>,i:i32}>>) -> (!fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>>) %6 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs, test.ptr = "xnext1"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %7 = fir.load %6 : !fir.ref>>,i:i32}>>>> %8 = fir.box_addr %7 : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> %9 = hlfir.designate %8{"i"} : (!fir.ptr>>,i:i32}>>) -> !fir.ref %10 = fir.load %9 : !fir.ref hlfir.assign %10 to %1#0 : i32, !fir.ref hlfir.assign %5#0 to %4#0 : !fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>> %11 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs, test.ptr = "xnext2"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %12 = fir.load %11 : !fir.ref>>,i:i32}>>>> %13 = fir.box_addr %12 : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> %14 = hlfir.designate %13{"i"} : (!fir.ptr>>,i:i32}>>) -> !fir.ref %15 = fir.load %14 : !fir.ref hlfir.assign %15 to %3#0 : i32, !fir.ref %16 = hlfir.designate %5#0{"next"} {fortran_attrs = #fir.var_attrs, test.ptr = "ynext"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> return } func.func @_QMmPfoo.fir(%arg0: !fir.ref>>,i:i32}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>,i:i32}>> {fir.bindc_name = "y"}) { %0 = fir.alloca !fir.box>>,i:i32}>> %1 = fir.alloca i32 {bindc_name = "i1", uniq_name = "_QMmFfooEi1"} %2 = fir.declare %1 {uniq_name = "_QMmFfooEi1"} : (!fir.ref) -> !fir.ref %3 = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QMmFfooEi2"} %4 = fir.declare %3 {uniq_name = "_QMmFfooEi2"} : (!fir.ref) -> !fir.ref %5 = fir.declare %arg0 {test.ptr = "x.fir", uniq_name = "_QMmFfooEx"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>> %6 = fir.declare %arg1 {test.ptr = "y.fir", uniq_name = "_QMmFfooEy"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>> %8 = fir.coordinate_of %5, next {test.ptr="xnext1.fir"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %9 = fir.load %8 : !fir.ref>>,i:i32}>>>> %10 = fir.box_addr %9 : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> %12 = fir.coordinate_of %10, i : (!fir.ptr>>,i:i32}>>) -> !fir.ref %13 = fir.load %12 : !fir.ref fir.store %13 to %2 : !fir.ref %14 = fir.embox %5 : (!fir.ref>>,i:i32}>>) -> !fir.box>>,i:i32}>> %15 = fir.embox %6 : (!fir.ref>>,i:i32}>>) -> !fir.box>>,i:i32}>> fir.store %14 to %0 : !fir.ref>>,i:i32}>>> %16 = fir.address_of(@_QQclX746D70332E66697200) : !fir.ref> %c9 = arith.constant 9 : index %c14_i32 = arith.constant 14 : i32 %17 = fir.convert %0 : (!fir.ref>>,i:i32}>>>) -> !fir.ref> %18 = fir.convert %15 : (!fir.box>>,i:i32}>>) -> !fir.box %19 = fir.convert %16 : (!fir.ref>) -> !fir.ref fir.call @_FortranAAssign(%17, %18, %19, %c14_i32) : (!fir.ref>, !fir.box, !fir.ref, i32) -> () %22 = fir.coordinate_of %5, next {test.ptr="xnext2.fir"}: (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %23 = fir.load %22 : !fir.ref>>,i:i32}>>>> %24 = fir.box_addr %23 : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> %26 = fir.coordinate_of %24, i : (!fir.ptr>>,i:i32}>>) -> !fir.ref %27 = fir.load %26 : !fir.ref fir.store %27 to %4 : !fir.ref %29 = fir.coordinate_of %6, next {test.ptr="ynext.fir"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> return } // ----- // Same test as above focusing on aliasing between x%next and y%next data // CHECK-LABEL: Testing : "_QMmPfoo2" // CHECK-DAG: xnext#0 <-> ynext#0: MayAlias // CHECK-DAG: xnext.fir#0 <-> ynext.fir#0: MayAlias func.func @_QMmPfoo2(%arg0: !fir.ref>>,i:i32}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>,i:i32}>> {fir.bindc_name = "y"}) { %4:2 = hlfir.declare %arg0 {uniq_name = "_QMmFfooEx"} : (!fir.ref>>,i:i32}>>) -> (!fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>>) %5:2 = hlfir.declare %arg1 {uniq_name = "_QMmFfooEy"} : (!fir.ref>>,i:i32}>>) -> (!fir.ref>>,i:i32}>>, !fir.ref>>,i:i32}>>) %6 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %7 = fir.load %6 : !fir.ref>>,i:i32}>>>> %8 = fir.box_addr %7 {test.ptr = "xnext"} : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> %9 = hlfir.designate %5#0{"next"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %10 = fir.load %9 : !fir.ref>>,i:i32}>>>> %11 = fir.box_addr %10 {test.ptr = "ynext"} : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> return } func.func @_QMmPfoo2.fir(%arg0: !fir.ref>>,i:i32}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>,i:i32}>> {fir.bindc_name = "y"}) { %0 = fir.declare %arg0 {uniq_name = "_QMmFfooEx"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>> %1 = fir.declare %arg1 {uniq_name = "_QMmFfooEy"} : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>> %3 = fir.coordinate_of %0, next : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %4 = fir.load %3 : !fir.ref>>,i:i32}>>>> %5 = fir.box_addr %4 {test.ptr = "xnext.fir"} : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> %7 = fir.coordinate_of %1, next : (!fir.ref>>,i:i32}>>) -> !fir.ref>>,i:i32}>>>> %8 = fir.load %7 : !fir.ref>>,i:i32}>>>> %9 = fir.box_addr %8 {test.ptr = "ynext.fir"} : (!fir.box>>,i:i32}>>>) -> !fir.ptr>>,i:i32}>> return } // ----- // module m // type ta // integer, pointer :: array(:) // end type // contains // subroutine foo3(x, y) // type(t) :: x, y // x%array(1) = y%array(1) // end subroutine // end module // CHECK-LABEL: Testing : "_QMmPfoo3" // CHECK-DAG: yarray#0 <-> xarray#0: MayAlias // CHECK-DAG: yarray.fir#0 <-> xarray.fir#0: MayAlias func.func @_QMmPfoo3(%arg0: !fir.ref>>}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>}>> {fir.bindc_name = "y"}) { %0:2 = hlfir.declare %arg0 {uniq_name = "_QMmFfooEx"} : (!fir.ref>>}>>) -> (!fir.ref>>}>>, !fir.ref>>}>>) %1:2 = hlfir.declare %arg1 {uniq_name = "_QMmFfooEy"} : (!fir.ref>>}>>) -> (!fir.ref>>}>>, !fir.ref>>}>>) %2 = hlfir.designate %1#0{"array"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> %3 = fir.load %2 : !fir.ref>>> %c1 = arith.constant 1 : index %4 = hlfir.designate %3 (%c1) {test.ptr = "yarray"} : (!fir.box>>, index) -> !fir.ref %5 = fir.load %4 : !fir.ref %6 = hlfir.designate %0#0{"array"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> %7 = fir.load %6 : !fir.ref>>> %c1_0 = arith.constant 1 : index %8 = hlfir.designate %7 (%c1_0) {test.ptr = "xarray"} : (!fir.box>>, index) -> !fir.ref hlfir.assign %5 to %8 : i32, !fir.ref return } func.func @_QMmPfoo3.fir(%arg0: !fir.ref>>}>> {fir.bindc_name = "x"}, %arg1: !fir.ref>>}>> {fir.bindc_name = "y"}) { %0 = fir.declare %arg0 {uniq_name = "_QMmFfooEx"} : (!fir.ref>>}>>) -> !fir.ref>>}>> %1 = fir.declare %arg1 {uniq_name = "_QMmFfooEy"} : (!fir.ref>>}>>) -> !fir.ref>>}>> %3 = fir.coordinate_of %1, array : (!fir.ref>>}>>) -> !fir.ref>>> %4 = fir.load %3 : !fir.ref>>> %c1 = arith.constant 1 : index %c0 = arith.constant 0 : index %5:3 = fir.box_dims %4, %c0 : (!fir.box>>, index) -> (index, index, index) %6 = fir.shift %5#0 : (index) -> !fir.shift<1> %7 = fir.array_coor %4(%6) %c1 {test.ptr="yarray.fir"} : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref %8 = fir.load %7 : !fir.ref %10 = fir.coordinate_of %0, array : (!fir.ref>>}>>) -> !fir.ref>>> %11 = fir.load %10 : !fir.ref>>> %c1_0 = arith.constant 1 : index %c0_1 = arith.constant 0 : index %12:3 = fir.box_dims %11, %c0_1 : (!fir.box>>, index) -> (index, index, index) %13 = fir.shift %12#0 : (index) -> !fir.shift<1> %14 = fir.array_coor %11(%13) %c1_0 {test.ptr="xarray.fir"} : (!fir.box>>, !fir.shift<1>, index) -> !fir.ref fir.store %8 to %14 : !fir.ref return } // ----- // The address of a composite aliases the address of any component, including an // allocatable component. Like the address of a pointer, the address of an // allocatable is considered non-data, so AliasAnalysis has special handling to // detect the aliasing. // module m // type t // integer, allocatable :: p // end type // type(t) :: x // contains // subroutine test() // ! access x%p // end subroutine // end module // CHECK-LABEL: Testing : "_QMmPtest" // CHECK-DAG: x#0 <-> x%p#0: MayAlias // CHECK-DAG: x.fir#0 <-> x%p.fir#0: MayAlias func.func @_QMmPtest() { %0 = fir.address_of(@_QMmEx) : !fir.ref>}>> %1:2 = hlfir.declare %0 {test.ptr="x", uniq_name = "_QMmEx"} : (!fir.ref>}>>) -> (!fir.ref>}>>, !fir.ref>}>>) %2 = hlfir.designate %1#0{"p"} {test.ptr="x%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>}>>) -> !fir.ref>> return } func.func @_QMmPtest.fir() { %0 = fir.address_of(@_QMmEx) : !fir.ref>}>> %1 = fir.declare %0 {test.ptr = "x.fir", uniq_name = "_QMmEx"} : (!fir.ref>}>>) -> !fir.ref>}>> %3 = fir.coordinate_of %1, p {test.ptr="x%p.fir"} : (!fir.ref>}>>) -> !fir.ref>> return } // ----- // Nested composites. // module m // type t1 // integer, pointer :: p // end type // type t2 // type(t1) :: x // integer, pointer :: p // integer :: i // end type // contains // subroutine test() // type(t2) :: x // end subroutine // end module // CHECK-LABEL: Testing : "_QMmPtest" // The addresses of a composite and its pointer component alias even if the // 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 // The addresses of different components of the same composite do not alias. // CHECK-DAG: x%x#0 <-> x%i#0: NoAlias // CHECK-DAG: x%p#0 <-> x%i#0: NoAlias // CHECK-DAG: x%x#0 <-> x%p#0: NoAlias // CHECK-DAG: x%x.fir#0 <-> x%i.fir#0: NoAlias // CHECK-DAG: x%p.fir#0 <-> x%i.fir#0: NoAlias // CHECK-DAG: x%x.fir#0 <-> x%p.fir#0: NoAlias func.func @_QMmPtest() { %0 = fir.alloca !fir.type<_QMmTt2{x:!fir.type<_QMmTt1{p:!fir.box>}>,p:!fir.box>,i:i32}> {bindc_name = "x", uniq_name = "_QMmFtestEx"} %1:2 = hlfir.declare %0 {test.ptr="x", uniq_name = "_QMmFtestEx"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> (!fir.ref>}>,p:!fir.box>,i:i32}>>, !fir.ref>}>,p:!fir.box>,i:i32}>>) %2 = hlfir.designate %1#0{"x"} {test.ptr="x%x"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref>}>> %3 = hlfir.designate %1#0{"p"} {test.ptr="x%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref>> %4 = hlfir.designate %1#0{"i"} {test.ptr="x%i"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref %5 = hlfir.designate %2{"p"} {test.ptr="x%x%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>}>>) -> !fir.ref>> return } func.func @_QMmPtest.fir() { %0 = fir.alloca !fir.type<_QMmTt2{x:!fir.type<_QMmTt1{p:!fir.box>}>,p:!fir.box>,i:i32}> {bindc_name = "x", uniq_name = "_QMmFtestEx"} %1 = fir.declare %0 {test.ptr = "x.fir", uniq_name = "_QMmFtestEx"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref>}>,p:!fir.box>,i:i32}>> %3 = fir.coordinate_of %1, x {test.ptr="x%x.fir"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref>}>> %5 = fir.coordinate_of %1, p {test.ptr="x%p.fir"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref>> %7 = fir.coordinate_of %1, i {test.ptr="x%i.fir"} : (!fir.ref>}>,p:!fir.box>,i:i32}>>) -> !fir.ref %9 = fir.coordinate_of %3, p {test.ptr="x%x%p.fir"} : (!fir.ref>}>>) -> !fir.ref>> return } // ----- // Pointer that might dynamically be a component. // The address of a pointer dummy arg (argp) might alias the address of a // pointer component (x%p) and thus the address of the associated composite (x), // but it does not alias the addresses of other components (x%i) of the // composite. Moreover, the address *in* argp does not alias any of those. // Finally, an allocatable dummy arg (arga) should not be mistaken for a pointer // dummy arg and cannot have such aliasing. // module m // type t // integer, pointer :: p // integer i // end type // type(t) :: glob // contains // subroutine test(argp, arga, arg) // integer, pointer :: argp // integer, allocatable :: arga // type(t) :: arg // type(t) :: loc // end subroutine // end module // CHECK-LABEL: Testing : "_QMmPtest" // Check when composite is a dummy arg. // // CHECK-DAG: argp#0 <-> arg#0: MayAlias // CHECK-DAG: argp#0 <-> arg%p#0: MayAlias // CHECK-DAG: argp#0 <-> arg%i#0: NoAlias // CHECK-DAG: argp.fir#0 <-> arg.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> arg%p.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> arg%i.fir#0: NoAlias // // CHECK-DAG: argp.tgt#0 <-> arg#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> arg%p#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> arg%i#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> arg.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> arg%p.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> arg%i.fir#0: NoAlias // // CHECK-DAG: arga#0 <-> arg#0: NoAlias // CHECK-DAG: arga#0 <-> arg%p#0: NoAlias // CHECK-DAG: arga.fir#0 <-> arg.fir#0: NoAlias // CHECK-DAG: arga.fir#0 <-> arg%p.fir#0: NoAlias // Check when composite is a global. // // CHECK-DAG: argp#0 <-> glob#0: MayAlias // CHECK-DAG: argp#0 <-> glob%p#0: MayAlias // CHECK-DAG: argp#0 <-> glob%i#0: NoAlias // CHECK-DAG: argp.fir#0 <-> glob.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> glob%p.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> glob%i.fir#0: NoAlias // // CHECK-DAG: argp.tgt#0 <-> glob#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> glob%p#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> glob%i#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> glob.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> glob%p.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> glob%i.fir#0: NoAlias // // CHECK-DAG: arga#0 <-> glob#0: NoAlias // CHECK-DAG: arga#0 <-> glob%p#0: NoAlias // CHECK-DAG: arga.fir#0 <-> glob.fir#0: NoAlias // CHECK-DAG: arga.fir#0 <-> glob%p.fir#0: NoAlias // Check when composite is a local and thus cannot alias a dummy arg. // // CHECK-DAG: argp#0 <-> loc#0: NoAlias // CHECK-DAG: argp#0 <-> loc%p#0: NoAlias // CHECK-DAG: argp#0 <-> loc%i#0: NoAlias // CHECK-DAG: argp.fir#0 <-> loc.fir#0: NoAlias // CHECK-DAG: argp.fir#0 <-> loc%p.fir#0: NoAlias // CHECK-DAG: argp.fir#0 <-> loc%i.fir#0: NoAlias // // CHECK-DAG: argp.tgt#0 <-> loc#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> loc%p#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> loc%i#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> loc.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> loc%p.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> loc%i.fir#0: NoAlias // // CHECK-DAG: arga#0 <-> loc#0: NoAlias // CHECK-DAG: arga#0 <-> loc%p#0: NoAlias // CHECK-DAG: arga.fir#0 <-> loc.fir#0: NoAlias // CHECK-DAG: arga.fir#0 <-> loc%p.fir#0: NoAlias fir.global @_QMmEglob : !fir.type<_QMmTt{p:!fir.box>,i:i32}> func.func @_QMmPtest(%arg0: !fir.ref>> {fir.bindc_name = "argp"}, %arg1: !fir.ref>> {fir.bindc_name = "arga"}, %arg2: !fir.ref>,i:i32}>> {fir.bindc_name = "arg"}) { %0 = fir.dummy_scope : !fir.dscope %1:2 = hlfir.declare %arg0 dummy_scope %0 {test.ptr="argp", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEargp"} : (!fir.ref>>, !fir.dscope) -> (!fir.ref>>, !fir.ref>>) %2 = fir.load %1#0 : !fir.ref>> %3 = fir.box_addr %2 {test.ptr="argp.tgt"} : (!fir.box>) -> !fir.ptr %4:2 = hlfir.declare %arg1 dummy_scope %0 {test.ptr="arga", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarga"} : (!fir.ref>>, !fir.dscope) -> (!fir.ref>>, !fir.ref>>) %5:2 = hlfir.declare %arg2 dummy_scope %0 {test.ptr="arg", uniq_name = "_QMmFtestEarg"} : (!fir.ref>,i:i32}>>, !fir.dscope) -> (!fir.ref>,i:i32}>>, !fir.ref>,i:i32}>>) %6 = hlfir.designate %5#0{"p"} {test.ptr="arg%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %7 = hlfir.designate %5#0{"i"} {test.ptr="arg%i"} : (!fir.ref>,i:i32}>>) -> !fir.ref %8 = fir.address_of(@_QMmEglob) : !fir.ref>,i:i32}>> %9:2 = hlfir.declare %8 {test.ptr="glob", uniq_name = "_QMmEglob"} : (!fir.ref>,i:i32}>>) -> (!fir.ref>,i:i32}>>, !fir.ref>,i:i32}>>) %10 = hlfir.designate %9#0{"p"} {test.ptr="glob%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %11 = hlfir.designate %9#0{"i"} {test.ptr="glob%i"} : (!fir.ref>,i:i32}>>) -> !fir.ref %12 = fir.alloca !fir.type<_QMmTt{p:!fir.box>,i:i32}> {bindc_name = "loc", uniq_name = "_QMmFtestEloc"} %13:2 = hlfir.declare %12 {test.ptr="loc", uniq_name = "_QMmFtestEloc"} : (!fir.ref>,i:i32}>>) -> (!fir.ref>,i:i32}>>, !fir.ref>,i:i32}>>) %14 = hlfir.designate %13#0{"p"} {test.ptr="loc%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %15 = hlfir.designate %13#0{"i"} {test.ptr="loc%i"} : (!fir.ref>,i:i32}>>) -> !fir.ref return } func.func @_QMmPtest.fir(%arg0: !fir.ref>> {fir.bindc_name = "argp"}, %arg1: !fir.ref>> {fir.bindc_name = "arga"}, %arg2: !fir.ref>,i:i32}>> {fir.bindc_name = "arg"}) { %0 = fir.dummy_scope : !fir.dscope %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, test.ptr = "argp.fir", uniq_name = "_QMmFtestEargp"} : (!fir.ref>>, !fir.dscope) -> !fir.ref>> %2 = fir.load %1 : !fir.ref>> %3 = fir.box_addr %2 {test.ptr = "argp.tgt.fir"} : (!fir.box>) -> !fir.ptr %4 = fir.declare %arg1 dummy_scope %0 {fortran_attrs = #fir.var_attrs, test.ptr = "arga.fir", uniq_name = "_QMmFtestEarga"} : (!fir.ref>>, !fir.dscope) -> !fir.ref>> %5 = fir.declare %arg2 dummy_scope %0 {test.ptr = "arg.fir", uniq_name = "_QMmFtestEarg"} : (!fir.ref>,i:i32}>>, !fir.dscope) -> !fir.ref>,i:i32}>> %7 = fir.coordinate_of %5, p {test.ptr="arg%p.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %9 = fir.coordinate_of %5, i {test.ptr="arg%i.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref %10 = fir.address_of(@_QMmEglob) : !fir.ref>,i:i32}>> %11 = fir.declare %10 {test.ptr = "glob.fir", uniq_name = "_QMmEglob"} : (!fir.ref>,i:i32}>>) -> !fir.ref>,i:i32}>> %13 = fir.coordinate_of %11, p {test.ptr="glob%p.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %15 = fir.coordinate_of %11, i {test.ptr="glob%i.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref %16 = fir.alloca !fir.type<_QMmTt{p:!fir.box>,i:i32}> {bindc_name = "loc", uniq_name = "_QMmFtestEloc"} %17 = fir.declare %16 {test.ptr = "loc.fir", uniq_name = "_QMmFtestEloc"} : (!fir.ref>,i:i32}>>) -> !fir.ref>,i:i32}>> %19 = fir.coordinate_of %17, p {test.ptr="loc%p.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %21 = fir.coordinate_of %17, i {test.ptr="loc%i.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref return } // ----- // Same as previous case but argp and arga are HostAssoc. // module m // type t // integer, pointer :: p // integer i // end type // type(t) :: glob // contains // subroutine parent(argp, arga) // integer, pointer :: argp // integer, allocatable :: arga // type(t) :: arg // call test(arg) // contains // subroutine test(arg) // type(t) :: arg // type(t) :: loc // end subroutine // end subroutine // end module // CHECK-LABEL: Testing : "_QMmFparentPtest" // Check when composite is a dummy arg. // // CHECK-DAG: argp#0 <-> arg#0: MayAlias // CHECK-DAG: argp#0 <-> arg%p#0: MayAlias // CHECK-DAG: argp#0 <-> arg%i#0: NoAlias // CHECK-DAG: argp.fir#0 <-> arg.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> arg%p.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> arg%i.fir#0: NoAlias // // TODO: Shouldn't these all be NoAlias? // However, argp.tgt is currently handled as Indirect, and we only // can disambiguate descriptor and data addresses. // CHECK-DAG: argp.tgt#0 <-> arg#0: MayAlias // CHECK-DAG: argp.tgt#0 <-> arg%p#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> arg%i#0: MayAlias // CHECK-DAG: argp.tgt.fir#0 <-> arg.fir#0: MayAlias // CHECK-DAG: argp.tgt.fir#0 <-> arg%p.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> arg%i.fir#0: MayAlias // // CHECK-DAG: arga#0 <-> arg#0: NoAlias // CHECK-DAG: arga#0 <-> arg%p#0: NoAlias // CHECK-DAG: arga.fir#0 <-> arg.fir#0: NoAlias // CHECK-DAG: arga.fir#0 <-> arg%p.fir#0: NoAlias // Check when composite is a global. // // CHECK-DAG: argp#0 <-> glob#0: MayAlias // CHECK-DAG: argp#0 <-> glob%p#0: MayAlias // CHECK-DAG: argp#0 <-> glob%i#0: NoAlias // CHECK-DAG: argp.fir#0 <-> glob.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> glob%p.fir#0: MayAlias // CHECK-DAG: argp.fir#0 <-> glob%i.fir#0: NoAlias // // TODO: Shouldn't these all be NoAlias? // However, argp.tgt is currently handled as Indirect, and we only // can disambiguate descriptor and data addresses. // CHECK-DAG: argp.tgt#0 <-> glob#0: MayAlias // CHECK-DAG: argp.tgt#0 <-> glob%p#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> glob%i#0: MayAlias // CHECK-DAG: argp.tgt.fir#0 <-> glob.fir#0: MayAlias // CHECK-DAG: argp.tgt.fir#0 <-> glob%p.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> glob%i.fir#0: MayAlias // // CHECK-DAG: arga#0 <-> glob#0: NoAlias // CHECK-DAG: arga#0 <-> glob%p#0: NoAlias // CHECK-DAG: arga.fir#0 <-> glob.fir#0: NoAlias // CHECK-DAG: arga.fir#0 <-> glob%p.fir#0: NoAlias // Check when composite is a local and thus cannot alias a dummy arg. // // CHECK-DAG: argp#0 <-> loc#0: NoAlias // CHECK-DAG: argp#0 <-> loc%p#0: NoAlias // CHECK-DAG: argp#0 <-> loc%i#0: NoAlias // CHECK-DAG: argp.fir#0 <-> loc.fir#0: NoAlias // CHECK-DAG: argp.fir#0 <-> loc%p.fir#0: NoAlias // CHECK-DAG: argp.fir#0 <-> loc%i.fir#0: NoAlias // // TODO: Shouldn't these all be NoAlias? // However, argp.tgt is currently handled as Indirect, and we only // can disambiguate descriptor and data addresses. // CHECK-DAG: argp.tgt#0 <-> loc#0: MayAlias // CHECK-DAG: argp.tgt#0 <-> loc%p#0: NoAlias // CHECK-DAG: argp.tgt#0 <-> loc%i#0: MayAlias // CHECK-DAG: argp.tgt.fir#0 <-> loc.fir#0: MayAlias // CHECK-DAG: argp.tgt.fir#0 <-> loc%p.fir#0: NoAlias // CHECK-DAG: argp.tgt.fir#0 <-> loc%i.fir#0: MayAlias // // CHECK-DAG: arga#0 <-> loc#0: NoAlias // CHECK-DAG: arga#0 <-> loc%p#0: NoAlias // CHECK-DAG: arga.fir#0 <-> loc.fir#0: NoAlias // CHECK-DAG: arga.fir#0 <-> loc%p.fir#0: NoAlias fir.global @_QMmEglob : !fir.type<_QMmTt{p:!fir.box>,i:i32}> func.func private @_QMmFparentPtest(%arg0: !fir.ref>,i:i32}>> {fir.bindc_name = "arg"}, %arg1: !fir.ref>>, !fir.ref>>>> {fir.host_assoc}) attributes {fir.host_symbol = @_QMmPparent, llvm.linkage = #llvm.linkage} { %0 = fir.dummy_scope : !fir.dscope %c0_i32 = arith.constant 0 : i32 %1 = fir.coordinate_of %arg1, %c0_i32 : (!fir.ref>>, !fir.ref>>>>, i32) -> !fir.llvm_ptr>>> %2 = fir.load %1 : !fir.llvm_ptr>>> %3:2 = hlfir.declare %2 {test.ptr="argp", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFparentEargp"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) %4 = fir.load %3#0 : !fir.ref>> %5 = fir.box_addr %4 {test.ptr="argp.tgt"} : (!fir.box>) -> !fir.ptr %c1_i32 = arith.constant 1 : i32 %10 = fir.coordinate_of %arg1, %c1_i32 : (!fir.ref>>, !fir.ref>>>>, i32) -> !fir.llvm_ptr>>> %11 = fir.load %10 : !fir.llvm_ptr>>> %12:2 = hlfir.declare %11 {test.ptr="arga", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFparentEarga"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) %20 = fir.address_of(@_QMmEglob) : !fir.ref>,i:i32}>> %21:2 = hlfir.declare %20 {test.ptr="glob", uniq_name = "_QMmEglob"} : (!fir.ref>,i:i32}>>) -> (!fir.ref>,i:i32}>>, !fir.ref>,i:i32}>>) %22 = hlfir.designate %21#0{"p"} {test.ptr="glob%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %23 = hlfir.designate %21#0{"i"} {test.ptr="glob%i"} : (!fir.ref>,i:i32}>>) -> !fir.ref %30:2 = hlfir.declare %arg0 dummy_scope %0 {test.ptr="arg", uniq_name = "_QMmFparentFtestEarg"} : (!fir.ref>,i:i32}>>, !fir.dscope) -> (!fir.ref>,i:i32}>>, !fir.ref>,i:i32}>>) %31 = hlfir.designate %30#0{"p"} {test.ptr="arg%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %32 = hlfir.designate %30#0{"i"} {test.ptr="arg%i"} : (!fir.ref>,i:i32}>>) -> !fir.ref %40 = fir.alloca !fir.type<_QMmTt{p:!fir.box>,i:i32}> {bindc_name = "loc", uniq_name = "_QMmFparentFtestEloc"} %41:2 = hlfir.declare %40 {test.ptr="loc", uniq_name = "_QMmFparentFtestEloc"} : (!fir.ref>,i:i32}>>) -> (!fir.ref>,i:i32}>>, !fir.ref>,i:i32}>>) %42 = hlfir.designate %41#0{"p"} {test.ptr="loc%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %43 = hlfir.designate %41#0{"i"} {test.ptr="loc%i"} : (!fir.ref>,i:i32}>>) -> !fir.ref return } func.func private @_QMmFparentPtest.fir(%arg0: !fir.ref>,i:i32}>> {fir.bindc_name = "arg"}, %arg1: !fir.ref>>, !fir.ref>>>> {fir.host_assoc}) attributes {fir.host_symbol = @_QMmPparent, llvm.linkage = #llvm.linkage} { %0 = fir.dummy_scope : !fir.dscope %c0_i32 = arith.constant 0 : i32 %1 = fir.coordinate_of %arg1, %c0_i32 : (!fir.ref>>, !fir.ref>>>>, i32) -> !fir.llvm_ptr>>> %2 = fir.load %1 : !fir.llvm_ptr>>> %3 = fir.declare %2 {fortran_attrs = #fir.var_attrs, test.ptr = "argp.fir", uniq_name = "_QMmFparentEargp"} : (!fir.ref>>) -> !fir.ref>> %4 = fir.load %3 : !fir.ref>> %5 = fir.box_addr %4 {test.ptr = "argp.tgt.fir"} : (!fir.box>) -> !fir.ptr %c1_i32 = arith.constant 1 : i32 %6 = fir.coordinate_of %arg1, %c1_i32 : (!fir.ref>>, !fir.ref>>>>, i32) -> !fir.llvm_ptr>>> %7 = fir.load %6 : !fir.llvm_ptr>>> %8 = fir.declare %7 {fortran_attrs = #fir.var_attrs, test.ptr = "arga.fir", uniq_name = "_QMmFparentEarga"} : (!fir.ref>>) -> !fir.ref>> %9 = fir.address_of(@_QMmEglob) : !fir.ref>,i:i32}>> %10 = fir.declare %9 {test.ptr = "glob.fir", uniq_name = "_QMmEglob"} : (!fir.ref>,i:i32}>>) -> !fir.ref>,i:i32}>> %12 = fir.coordinate_of %10, p {test.ptr="glob%p.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %14 = fir.coordinate_of %10, i {test.ptr="glob%i.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref %15 = fir.declare %arg0 dummy_scope %0 {test.ptr = "arg.fir", uniq_name = "_QMmFparentFtestEarg"} : (!fir.ref>,i:i32}>>, !fir.dscope) -> !fir.ref>,i:i32}>> %17 = fir.coordinate_of %15, p {test.ptr="arg%p.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %19 = fir.coordinate_of %15, i {test.ptr="arg%i.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref %20 = fir.alloca !fir.type<_QMmTt{p:!fir.box>,i:i32}> {bindc_name = "loc", uniq_name = "_QMmFparentFtestEloc"} %21 = fir.declare %20 {test.ptr = "loc.fir", uniq_name = "_QMmFparentFtestEloc"} : (!fir.ref>,i:i32}>>) -> !fir.ref>,i:i32}>> %23 = fir.coordinate_of %21, p {test.ptr="loc%p.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref>> %25 = fir.coordinate_of %21, i {test.ptr="loc%i.fir"} : (!fir.ref>,i:i32}>>) -> !fir.ref return } // ----- // Dummy arg with target attribute and pointer component. // The address of a dummy arg (arg0) may alias the address of a global (glob0) // or another dummy arg (arg1) when both have target attributes. If either is a // composite, the addresses of components (whether data like r, or non-data like // p and a) may also alias the composite or the same component. However, target // attributes do not permit two globals (glob0 and glob1) to alias. // module m // type t // real, pointer :: p // real, allocatable :: a // real :: r // end type // type(t), target :: glob0 // type(t), target :: glob1 // contains // subroutine test(arg0, arg1) // type(t), target :: arg0 // type(t), target :: arg1 // end subroutine // end module // Check composite vs. composite. // // CHECK-DAG: arg0#0 <-> arg1#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> arg1.fir#0: MayAlias // // CHECK-DAG: arg0#0 <-> glob0#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> glob0.fir#0: MayAlias // // CHECK-DAG: glob0#0 <-> glob1#0: NoAlias // CHECK-DAG: glob0.fir#0 <-> glob1.fir#0: NoAlias // Check component vs. composite. // // CHECK-DAG: arg0%p#0 <-> arg1#0: MayAlias // CHECK-DAG: arg0%a#0 <-> arg1#0: MayAlias // CHECK-DAG: arg0%r#0 <-> arg1#0: MayAlias // CHECK-DAG: arg0%p.fir#0 <-> arg1.fir#0: MayAlias // CHECK-DAG: arg0%a.fir#0 <-> arg1.fir#0: MayAlias // CHECK-DAG: arg0%r.fir#0 <-> arg1.fir#0: MayAlias // // CHECK-DAG: arg0%p#0 <-> glob0#0: MayAlias // CHECK-DAG: arg0%a#0 <-> glob0#0: MayAlias // CHECK-DAG: arg0%r#0 <-> glob0#0: MayAlias // CHECK-DAG: arg0%p.fir#0 <-> glob0.fir#0: MayAlias // CHECK-DAG: arg0%a.fir#0 <-> glob0.fir#0: MayAlias // CHECK-DAG: arg0%r.fir#0 <-> glob0.fir#0: MayAlias // // CHECK-DAG: glob0%p#0 <-> glob1#0: NoAlias // CHECK-DAG: glob0%a#0 <-> glob1#0: NoAlias // CHECK-DAG: glob0%r#0 <-> glob1#0: NoAlias // CHECK-DAG: glob0%p.fir#0 <-> glob1.fir#0: NoAlias // CHECK-DAG: glob0%a.fir#0 <-> glob1.fir#0: NoAlias // CHECK-DAG: glob0%r.fir#0 <-> glob1.fir#0: NoAlias // Check composite vs. component. // // CHECK-DAG: arg0#0 <-> arg1%p#0: MayAlias // CHECK-DAG: arg0#0 <-> arg1%a#0: MayAlias // CHECK-DAG: arg0#0 <-> arg1%r#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> arg1%p.fir#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> arg1%a.fir#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> arg1%r.fir#0: MayAlias // // CHECK-DAG: arg0#0 <-> glob0%p#0: MayAlias // CHECK-DAG: arg0#0 <-> glob0%a#0: MayAlias // CHECK-DAG: arg0#0 <-> glob0%r#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> glob0%p.fir#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> glob0%a.fir#0: MayAlias // CHECK-DAG: arg0.fir#0 <-> glob0%r.fir#0: MayAlias // // CHECK-DAG: glob0#0 <-> glob1%p#0: NoAlias // CHECK-DAG: glob0#0 <-> glob1%a#0: NoAlias // CHECK-DAG: glob0#0 <-> glob1%r#0: NoAlias // CHECK-DAG: glob0.fir#0 <-> glob1%p.fir#0: NoAlias // CHECK-DAG: glob0.fir#0 <-> glob1%a.fir#0: NoAlias // CHECK-DAG: glob0.fir#0 <-> glob1%r.fir#0: NoAlias // Check component vs. component. // // CHECK-DAG: arg0%p#0 <-> arg1%p#0: MayAlias // CHECK-DAG: arg0%a#0 <-> arg1%a#0: MayAlias // CHECK-DAG: arg0%r#0 <-> arg1%r#0: MayAlias // CHECK-DAG: arg0%p.fir#0 <-> arg1%p.fir#0: MayAlias // CHECK-DAG: arg0%a.fir#0 <-> arg1%a.fir#0: MayAlias // CHECK-DAG: arg0%r.fir#0 <-> arg1%r.fir#0: MayAlias // // CHECK-DAG: arg0%p.fir#0 <-> glob0%p.fir#0: MayAlias // CHECK-DAG: arg0%a.fir#0 <-> glob0%a.fir#0: MayAlias // CHECK-DAG: arg0%r.fir#0 <-> glob0%r.fir#0: MayAlias // // CHECK-DAG: glob0%p.fir#0 <-> glob1%p.fir#0: NoAlias // CHECK-DAG: glob0%a.fir#0 <-> glob1%a.fir#0: NoAlias // CHECK-DAG: glob0%r.fir#0 <-> glob1%r.fir#0: NoAlias func.func @_QMmPtest(%arg0: !fir.ref>,a:!fir.box>,r:f32}>> {fir.bindc_name = "arg0", fir.target}, %arg1: !fir.ref>,a:!fir.box>,r:f32}>> {fir.bindc_name = "arg1", fir.target}) { %0 = fir.dummy_scope : !fir.dscope %10:2 = hlfir.declare %arg0 dummy_scope %0 {test.ptr="arg0", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarg0"} : (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.dscope) -> (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.ref>,a:!fir.box>,r:f32}>>) %11 = hlfir.designate %10#0{"p"} {test.ptr="arg0%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %12 = hlfir.designate %10#0{"a"} {test.ptr="arg0%a", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %13 = hlfir.designate %10#0{"r"} {test.ptr="arg0%r"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref %20:2 = hlfir.declare %arg1 dummy_scope %0 {test.ptr="arg1", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarg1"} : (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.dscope) -> (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.ref>,a:!fir.box>,r:f32}>>) %21 = hlfir.designate %20#0{"p"} {test.ptr="arg1%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %22 = hlfir.designate %20#0{"a"} {test.ptr="arg1%a", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %23 = hlfir.designate %20#0{"r"} {test.ptr="arg1%r"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref %30 = fir.address_of(@_QMmEglob0) : !fir.ref>,a:!fir.box>,r:f32}>> %31:2 = hlfir.declare %30 {test.ptr="glob0", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmEglob0"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.ref>,a:!fir.box>,r:f32}>>) %32 = hlfir.designate %31#0{"p"} {test.ptr="glob0%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %33 = hlfir.designate %31#0{"a"} {test.ptr="glob0%a", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %34 = hlfir.designate %31#0{"r"} {test.ptr="glob0%r"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref %40 = fir.address_of(@_QMmEglob1) : !fir.ref>,a:!fir.box>,r:f32}>> %41:2 = hlfir.declare %40 {test.ptr="glob1", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmEglob1"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.ref>,a:!fir.box>,r:f32}>>) %42 = hlfir.designate %41#0{"p"} {test.ptr="glob1%p", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %43 = hlfir.designate %41#0{"a"} {test.ptr="glob1%a", fortran_attrs = #fir.var_attrs} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %44 = hlfir.designate %41#0{"r"} {test.ptr="glob1%r"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref return } func.func @_QMmPtest.fir(%arg0: !fir.ref>,a:!fir.box>,r:f32}>> {fir.bindc_name = "arg0", fir.target}, %arg1: !fir.ref>,a:!fir.box>,r:f32}>> {fir.bindc_name = "arg1", fir.target}) { %0 = fir.dummy_scope : !fir.dscope %1 = fir.declare %arg0 dummy_scope %0 {test.ptr="arg0.fir", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarg0"} : (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.dscope) -> !fir.ref>,a:!fir.box>,r:f32}>> %3 = fir.coordinate_of %1, p {test.ptr="arg0%p.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %5 = fir.coordinate_of %1, a {test.ptr="arg0%a.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %7 = fir.coordinate_of %1, r {test.ptr="arg0%r.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref %8 = fir.declare %arg1 dummy_scope %0 {test.ptr="arg1.fir", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarg1"} : (!fir.ref>,a:!fir.box>,r:f32}>>, !fir.dscope) -> !fir.ref>,a:!fir.box>,r:f32}>> %10 = fir.coordinate_of %8, p {test.ptr="arg1%p.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %12 = fir.coordinate_of %8, a {test.ptr="arg1%a.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %14 = fir.coordinate_of %8, r {test.ptr="arg1%r.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref %15 = fir.address_of(@_QMmEglob0) : !fir.ref>,a:!fir.box>,r:f32}>> %16 = fir.declare %15 {test.ptr="glob0.fir", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmEglob0"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>,a:!fir.box>,r:f32}>> %18 = fir.coordinate_of %16, p {test.ptr="glob0%p.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %20 = fir.coordinate_of %16, a {test.ptr="glob0%a.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %22 = fir.coordinate_of %16, r {test.ptr="glob0%r.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref %23 = fir.address_of(@_QMmEglob1) : !fir.ref>,a:!fir.box>,r:f32}>> %24 = fir.declare %23 {test.ptr="glob1.fir", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmEglob1"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>,a:!fir.box>,r:f32}>> %26 = fir.coordinate_of %24, p {test.ptr="glob1%p.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %28 = fir.coordinate_of %24, a {test.ptr="glob1%a.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref>> %30 = fir.coordinate_of %24, r {test.ptr="glob1%r.fir"} : (!fir.ref>,a:!fir.box>,r:f32}>>) -> !fir.ref return } // ----- // Allocatable dummy arg with target attribute. // This case is like the previous one except that the non-data is the address // of the dummy arg itself rather than of a pointer component of the dummy arg. // The goal is to check that logic introduced into AliasAnalysis to handle the // pointer component case doesn't break this related one. // module m // real, allocatable, target :: glob0 // real, allocatable, target :: glob1 // contains // subroutine test(arg0, arg1) // real, allocatable, target :: arg0 // real, allocatable, target :: arg1 // end subroutine // end module // CHECK-DAG: arg0#0 <-> arg1#0: MayAlias // CHECK-DAG: arg0#0 <-> glob0#0: MayAlias // CHECK-DAG: glob0#0 <-> glob1#0: NoAlias func.func @_QMmPtest(%arg0: !fir.ref>> {fir.bindc_name = "arg0", fir.target}, %arg1: !fir.ref>> {fir.bindc_name = "arg1", fir.target}) { %0 = fir.dummy_scope : !fir.dscope %10:2 = hlfir.declare %arg0 dummy_scope %0 {test.ptr="arg0", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarg0"} : (!fir.ref>>, !fir.dscope) -> (!fir.ref>>, !fir.ref>>) %11:2 = hlfir.declare %arg1 dummy_scope %0 {test.ptr="arg1", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmFtestEarg1"} : (!fir.ref>>, !fir.dscope) -> (!fir.ref>>, !fir.ref>>) %20 = fir.address_of(@_QMmEglob0) : !fir.ref>> %21:2 = hlfir.declare %20 {test.ptr="glob0", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmEglob0"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) %22 = fir.address_of(@_QMmEglob1) : !fir.ref>> %23:2 = hlfir.declare %22 {test.ptr="glob1", fortran_attrs = #fir.var_attrs, uniq_name = "_QMmEglob1"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) return }