1// Use --mlir-disable-threading so that the AA queries are serialized 2// as well as its diagnostic output. 3// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s 4 5// CHECK-LABEL: Testing : "_QFPtest" 6 7// p1.addr and p2.addr result from 2 different allocas 8// They cannot physically alias 9// CHECK-DAG: p1.addr#0 <-> p2.addr#0: NoAlias 10 11// p1.addr and p2.addr could both be wrapped inside boxes 12// CHECK-DAG: p1.addr#0 <-> boxp1.addr#0: MayAlias 13// CHECK-DAG: p2.addr#0 <-> boxp1.addr#0: MayAlias 14 15// TODO: To really see aliasing, we should be looking at a load of p1.addr 16// p1.addr is just a local address holding the address to the data 17// CHECK-DAG: p1.addr#0 <-> arg2.addr#0: NoAlias 18// CHECK-DAG: p2.addr#0 <-> arg2.addr#0: NoAlias 19 20// p1.addr and p2.addr are the result of an allocation 21// They cannot physically alias with an argument 22// CHECK-DAG: p1.addr#0 <-> func.region0#0: NoAlias 23// CHECK-DAG: p2.addr#0 <-> func.region0#0: NoAlias 24// CHECK-DAG: p1.addr#0 <-> func.region0#1: NoAlias 25// CHECK-DAG: p2.addr#0 <-> func.region0#1: NoAlias 26// CHECK-DAG: p1.addr#0 <-> func.region0#2: NoAlias 27// CHECK-DAG: p2.addr#0 <-> func.region0#2: NoAlias 28 29// All arguments are either pointers or targets 30// A pointer in a box may alias with both 31// CHECK-DAG: boxp1.addr#0 <-> func.region0#0: MayAlias 32// CHECK-DAG: boxp1.addr#0 <-> func.region0#1: MayAlias 33// CHECK-DAG: boxp1.addr#0 <-> func.region0#2: MayAlias 34 35// A target dummy may alias with another target 36// CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias 37 38// arg2 is a reference to a pointer. Modifying arg2 could 39// modify a target with a pointer component 40// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias 41// CHECK-DAG: arg2.load#0 <-> func.region0#1: MayAlias 42 43// However, the address wrapped by arg2, can alias with any target or 44// pointer arguments 45// CHECK-DAG: arg2.addr#0 <-> func.region0#0: MayAlias 46// CHECK-DAG: arg2.addr#0 <-> func.region0#1: MayAlias 47// CHECK-DAG: arg2.load#0 <-> arg2.addr#0: MustAlias 48// CHECK-DAG: boxp1.addr#0 <-> arg2.addr#0: MayAlias 49 50func.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"} { 51 52 %1 = fir.alloca !fir.ptr<f32> {test.ptr = "p1.addr"} 53 %2 = fir.zero_bits !fir.ptr<f32> 54 fir.store %2 to %1 : !fir.ref<!fir.ptr<f32>> 55 56 %4 = fir.alloca !fir.ptr<f32> {test.ptr = "p2.addr"} 57 fir.store %2 to %4 : !fir.ref<!fir.ptr<f32>> 58 59 %5 = fir.convert %arg0 : (!fir.ref<f32>) -> !fir.ptr<f32> 60 fir.store %5 to %1 : !fir.ref<!fir.ptr<f32>> 61 62 %6 = fir.convert %arg1 : (!fir.ref<f32>) -> !fir.ptr<f32> 63 fir.store %6 to %4 : !fir.ref<!fir.ptr<f32>> 64 65 %0 = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "p1", uniq_name = "_QFtestEp1"} 66 %7 = fir.load %1 : !fir.ref<!fir.ptr<f32>> 67 %8 = fir.embox %7 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>> 68 fir.store %8 to %0 : !fir.ref<!fir.box<!fir.ptr<f32>>> 69 70 %3 = fir.alloca !fir.box<!fir.ptr<f32>> {bindc_name = "p2", uniq_name = "_QFtestEp2"} 71 %9 = fir.load %4 : !fir.ref<!fir.ptr<f32>> 72 %10 = fir.embox %9 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>> 73 fir.store %10 to %3 : !fir.ref<!fir.box<!fir.ptr<f32>>> 74 75 %11 = fir.load %0 : !fir.ref<!fir.box<!fir.ptr<f32>>> 76 %12 = fir.box_addr %11 {test.ptr = "boxp1.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> 77 fir.store %12 to %1 : !fir.ref<!fir.ptr<f32>> 78 79 %13 = fir.load %3 : !fir.ref<!fir.box<!fir.ptr<f32>>> 80 %14 = fir.box_addr %13 : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> 81 fir.store %14 to %4 : !fir.ref<!fir.ptr<f32>> 82 83 %15 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>> 84 %16 = fir.box_addr %15 {test.ptr = "arg2.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> 85 return 86} 87 88// ----- 89 90// CHECK-LABEL: Testing : "_QFPtest2" 91 92// subroutine test2(v1,p1,p2) 93// real, target :: v1 94// real, pointer :: p1, p2 95// ... 96// end subroutine 97 98// Direct access to dummy POINTER references can modify other dummy POINTER references 99// CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias 100 101// They can also modify targets that have pointer components 102// CHECK-DAG: arg1.load#0 <-> func.region0#0: MayAlias 103// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias 104 105func.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"} { 106 %0 = fir.load %arg1 {test.ptr = "arg1.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>> 107 %1 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>> 108 return 109} 110 111// ----- 112 113// CHECK-LABEL: Testing : "_QFPtest3" 114 115// module pointers 116// real, pointer :: p 117// end module 118// 119// program main 120// use pointers 121// real, target :: var1 = 1, var2 =2 122// p => var1 123// 124// call test3(p) 125// 126// contains 127// subroutine test3(p1) 128// real, pointer :: p1 129// p1 => var2 130// print *, p 131// end subroutine 132// end 133 134// The global pointer p may alias with the dummy argument p1 135// but not with the dummy arg1 which is just a regular dummy 136// CHECK-DAG: p#0 <-> func.region0#0: MayAlias 137// CHECK-DAG: p#0 <-> func.region0#1: NoAlias 138 139// p could be pointing to var2 140// var2, being a target, could also be passed as argument arg0 141 142// This was the wrong question to ask. We are asking if the address of box _QMpointersEp can 143// alias with the wrapped scalar _QFEvar2. We meant box_addr of _QMpointersEp 144// CHECK-DAG: p#0 <-> box.addr#0: NoAlias 145 146// Handling gracefully the difference between !fir.ref<!fir.box<>> and !fir.box<> 147// CHECK-DAG: box.addr#0 <-> func.region0#0: NoAlias 148 149// var2, although it is a target, cannot alias with p 150// A modification of p would only make them point to a new target but not modify it 151// CHECK-DAG: var2#0 <-> p#0: NoAlias 152// It can alias with p1, if p1 is a pointer component 153// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias 154// It is the same as box.addr 155// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias 156 157// A global may not alias with a dummy 158// CHECK-DAG: var2#0 <-> func.region0#1: NoAlias 159 160// A pointer may only alias with a target but arg1 is a regular dummy 161// CHECK-DAG: box.addr#0 <-> func.region0#1: NoAlias 162 163// Dummy argument do not alias 164// CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias 165 166fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>> { 167 %0 = fir.zero_bits !fir.ptr<f32> 168 %1 = fir.embox %0 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>> 169 fir.has_value %1 : !fir.box<!fir.ptr<f32>> 170} 171 172fir.global internal @_QFEvar2 target : f32 { 173 %cst = arith.constant 2.000000e+00 : f32 174 fir.has_value %cst : f32 175} 176 177func.func @_QFPtest3(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg1: !fir.ref<f32>) attributes {test.ptr = "func"} { 178 %3 = fir.load %arg0 {test.ptr = "arg0.load"}: !fir.ref<!fir.box<!fir.ptr<f32>>> 179 %4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref<f32> 180 %5 = fir.address_of(@_QMpointersEp) {test.ptr = "p"} : !fir.ref<!fir.box<!fir.ptr<f32>>> 181 %6 = fir.embox %4 : (!fir.ref<f32>) -> !fir.box<!fir.ptr<f32>> 182 %13 = fir.box_addr %6 {test.ptr = "box.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> 183 return 184} 185 186// ----- 187 188// CHECK-LABEL: Testing : "_QFPtest4" 189 190// Same as test3 but check that the alias analysis can follow (hl)fir.declare 191// operations 192 193// CHECK-DAG: p#0 <-> func.region0#0: MayAlias 194// CHECK-DAG: p_fir#0 <-> func.region0#0: MayAlias 195// CHECK-DAG: p_hlfir#0 <-> func.region0#0: MayAlias 196// CHECK-DAG: p_hlfir#1 <-> func.region0#0: MayAlias 197 198// CHECK-DAG: p#0 <-> func.region0#1: NoAlias 199// CHECK-DAG: p_fir#0 <-> func.region0#1: NoAlias 200// CHECK-DAG: p_hlfir#0 <-> func.region0#1: NoAlias 201// CHECK-DAG: p_hlfir#1 <-> func.region0#1: NoAlias 202 203// CHECK-DAG: var2#0 <-> p#0: NoAlias 204// CHECK-DAG: var2#0 <-> p_fir#0: NoAlias 205// CHECK-DAG: var2#0 <-> p_hlfir#0: NoAlias 206// CHECK-DAG: var2#0 <-> p_hlfir#1: NoAlias 207// CHECK-DAG: var2_fir#0 <-> p#0: NoAlias 208// CHECK-DAG: var2_fir#0 <-> p_fir#0: NoAlias 209// CHECK-DAG: var2_fir#0 <-> p_hlfir#0: NoAlias 210// CHECK-DAG: var2_fir#0 <-> p_hlfir#1: NoAlias 211// CHECK-DAG: var2_hlfir#0 <-> p#0: NoAlias 212// CHECK-DAG: var2_hlfir#0 <-> p_fir#0: NoAlias 213// CHECK-DAG: var2_hlfir#0 <-> p_hlfir#0: NoAlias 214// CHECK-DAG: var2_hlfir#0 <-> p_hlfir#1: NoAlias 215// CHECK-DAG: var2_hlfir#1 <-> p#0: NoAlias 216// CHECK-DAG: var2_hlfir#1 <-> p_fir#0: NoAlias 217// CHECK-DAG: var2_hlfir#1 <-> p_hlfir#0: NoAlias 218// CHECK-DAG: var2_hlfir#1 <-> p_hlfir#1: NoAlias 219 220// The data cannot alias with the box references 221// CHECK-DAG: var2#0 <-> func.region0#0: NoAlias 222// CHECK-DAG: var2_fir#0 <-> func.region0#0: NoAlias 223// CHECK-DAG: var2_hlfir#0 <-> func.region0#0: NoAlias 224// CHECK-DAG: var2_hlfir#1 <-> func.region0#0: NoAlias 225 226// But it can alias with the box's own data 227// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias 228// CHECK-DAG: arg0.load#0 <-> var2_fir#0: MayAlias 229// CHECK-DAG: arg0.load#0 <-> var2_hlfir#0: MayAlias 230// CHECK-DAG: arg0.load#0 <-> var2_hlfir#1: MayAlias 231 232// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias 233// CHECK-DAG: var2#0 <-> box.addr_fir#0: MustAlias 234// CHECK-DAG: var2#0 <-> box.addr_hlfir#0: MustAlias 235// CHECK-DAG: var2#0 <-> box.addr_hlfir#1: MustAlias 236// CHECK-DAG: var2_fir#0 <-> box.addr#0: MustAlias 237// CHECK-DAG: var2_fir#0 <-> box.addr_fir#0: MustAlias 238// CHECK-DAG: var2_fir#0 <-> box.addr_hlfir#0: MustAlias 239// CHECK-DAG: var2_fir#0 <-> box.addr_hlfir#1: MustAlias 240// CHECK-DAG: var2_hlfir#0 <-> box.addr#0: MustAlias 241// CHECK-DAG: var2_hlfir#0 <-> box.addr_fir#0: MustAlias 242// CHECK-DAG: var2_hlfir#0 <-> box.addr_hlfir#0: MustAlias 243// CHECK-DAG: var2_hlfir#0 <-> box.addr_hlfir#1: MustAlias 244// CHECK-DAG: var2_hlfir#1 <-> box.addr#0: MustAlias 245// CHECK-DAG: var2_hlfir#1 <-> box.addr_fir#0: MustAlias 246// CHECK-DAG: var2_hlfir#1 <-> box.addr_hlfir#0: MustAlias 247// CHECK-DAG: var2_hlfir#1 <-> box.addr_hlfir#1: MustAlias 248 249// CHECK-DAG: var2#0 <-> func.region0#1: NoAlias 250// CHECK-DAG: var2_fir#0 <-> func.region0#1: NoAlias 251// CHECK-DAG: var2_hlfir#0 <-> func.region0#1: NoAlias 252// CHECK-DAG: var2_hlfir#1 <-> func.region0#1: NoAlias 253 254// CHECK-DAG: func.region0#0 <-> func.region0#1: NoAlias 255 256fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>> { 257 %0 = fir.zero_bits !fir.ptr<f32> 258 %1 = fir.embox %0 : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>> 259 fir.has_value %1 : !fir.box<!fir.ptr<f32>> 260} 261 262fir.global internal @_QFEvar2 target : f32 { 263 %cst = arith.constant 2.000000e+00 : f32 264 fir.has_value %cst : f32 265} 266 267func.func @_QFPtest4(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg1: !fir.ref<f32>) attributes {test.ptr = "func"} { 268 %3 = fir.load %arg0 {test.ptr = "arg0.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>> 269 %4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref<f32> 270 %fir_decl_var2 = fir.declare %4 {uniq_name = "var2_fir", test.ptr = "var2_fir"}: (!fir.ref<f32>) -> !fir.ref<f32> 271 %hlfir_decl_var2:2 = hlfir.declare %4 {uniq_name = "var2_hlfir", test.ptr = "var2_hlfir"}: (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) 272 %5 = fir.address_of(@_QMpointersEp) {test.ptr = "p"} : !fir.ref<!fir.box<!fir.ptr<f32>>> 273 %fir_decl_p = fir.declare %5 {uniq_name = "p_fir", test.ptr = "p_fir"}: (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<!fir.ptr<f32>>> 274 %hlfir_decl_p:2 = hlfir.declare %5 {uniq_name = "p_hlfir", test.ptr = "p_hlfir"}: (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>) 275 %13 = fir.convert %4 {test.ptr = "box.addr"} : (!fir.ref<f32>) -> !fir.ptr<f32> 276 %fir_decl_convert = fir.declare %13 {uniq_name = "box_addr_fir", test.ptr = "box.addr_fir"}: (!fir.ptr<f32>) -> !fir.ptr<f32> 277 %hlfir_decl_convert:2 = hlfir.declare %13 {uniq_name = "box_addr_hlfir", test.ptr = "box.addr_hlfir"}: (!fir.ptr<f32>) -> (!fir.ptr<f32>, !fir.ptr<f32>) 278 return 279} 280