brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.2 KiB · 058390a Raw
359 lines · plain
1// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-initialize-fir-analyses,acc-implicit-data)" -split-input-file | FileCheck %s2 3// -----4 5func.func @test_fir_scalar_in_serial() {6  %livein = fir.alloca i64 {bindc_name = "scalarvar"}7  acc.serial {8    %load = fir.load %livein : !fir.ref<i64>9    acc.yield10  }11  return12}13 14// CHECK: acc.firstprivate varPtr({{.*}} : !fir.ref<i64>) recipe({{.*}}) -> !fir.ref<i64> {implicit = true, name = "scalarvar"}15 16// -----17 18func.func @test_fir_scalar_in_parallel() {19  %livein = fir.alloca f32 {bindc_name = "scalarvar"}20  acc.parallel {21    %load = fir.load %livein : !fir.ref<f32>22    acc.yield23  }24  return25}26 27// CHECK: acc.firstprivate varPtr({{.*}} : !fir.ref<f32>) recipe({{.*}}) -> !fir.ref<f32> {implicit = true, name = "scalarvar"}28 29// -----30 31func.func @test_fir_scalar_in_kernels() {32  %livein = fir.alloca f64 {bindc_name = "scalarvar"}33  acc.kernels {34    %load = fir.load %livein : !fir.ref<f64>35    acc.terminator36  }37  return38}39 40// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<f64>) -> !fir.ref<f64> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"}41// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<f64>) to varPtr({{.*}} : !fir.ref<f64>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"}42 43// -----44 45func.func @test_fir_scalar_in_parallel_defaultnone() {46  %livein = fir.alloca f32 {bindc_name = "scalarvar"}47  acc.parallel {48    %load = fir.load %livein : !fir.ref<f32>49    acc.yield50  } attributes {defaultAttr = #acc<defaultvalue none>}51  return52}53 54// CHECK-NOT: acc.firstprivate55 56// -----57 58func.func @test_fir_scalar_in_kernels_defaultnone() {59  %livein = fir.alloca f64 {bindc_name = "scalarvar"}60  acc.kernels {61    %load = fir.load %livein : !fir.ref<f64>62    acc.terminator63  } attributes {defaultAttr = #acc<defaultvalue none>}64  return65}66 67// CHECK-NOT: acc.copyin68 69// -----70 71func.func @test_fir_derivedtype_in_parallel() {72  %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"}73  acc.parallel {74    %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>>75    acc.yield76  }77  return78}79 80// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"}81// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) to varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"}82 83// -----84 85func.func @test_fir_derivedtype_in_kernels() {86  %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"}87  acc.kernels {88    %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>>89    acc.terminator90  }91  return92}93 94// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"}95// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) to varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aggrvar"}96 97// -----98 99func.func @test_fir_array_in_parallel() {100  %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"}101  acc.parallel {102    %load = fir.load %livein : !fir.ref<!fir.array<10xf32>>103    acc.yield104  }105  return106}107 108// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"}109// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<10xf32>>) to varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"}110 111// -----112 113func.func @test_fir_array_in_kernels() {114  %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"}115  acc.kernels {116    %load = fir.load %livein : !fir.ref<!fir.array<10xf32>>117    acc.terminator118  }119  return120}121 122// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"}123// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<10xf32>>) to varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "arrayvar"}124 125// -----126 127func.func @test_fir_derivedtype_in_parallel_defaultpresent() {128  %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"}129  acc.parallel {130    %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>>131    acc.yield132  } attributes {defaultAttr = #acc<defaultvalue present>}133  return134}135 136// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {acc.from_default, implicit = true, name = "aggrvar"}137// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "aggrvar"}138 139// -----140 141func.func @test_fir_derivedtype_in_kernels_defaultpresent() {142  %livein = fir.alloca !fir.type<_QFTaggr{field:f32}> {bindc_name = "aggrvar"}143  acc.kernels {144    %load = fir.load %livein : !fir.ref<!fir.type<_QFTaggr{field:f32}>>145    acc.terminator146  } attributes {defaultAttr = #acc<defaultvalue present>}147  return148}149 150// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) -> !fir.ref<!fir.type<_QFTaggr{field:f32}>> {acc.from_default, implicit = true, name = "aggrvar"}151// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.type<_QFTaggr{field:f32}>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "aggrvar"}152 153// -----154 155func.func @test_fir_array_in_parallel_defaultpresent() {156  %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"}157  acc.parallel {158    %load = fir.load %livein : !fir.ref<!fir.array<10xf32>>159    acc.yield160  } attributes {defaultAttr = #acc<defaultvalue present>}161  return162}163 164// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {acc.from_default, implicit = true, name = "arrayvar"}165// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "arrayvar"}166 167// -----168 169func.func @test_fir_array_in_kernels_defaultpresent() {170  %livein = fir.alloca !fir.array<10xf32> {bindc_name = "arrayvar"}171  acc.kernels {172    %load = fir.load %livein : !fir.ref<!fir.array<10xf32>>173    acc.terminator174  } attributes {defaultAttr = #acc<defaultvalue present>}175  return176}177 178// CHECK: %[[PRESENT:.*]] = acc.present varPtr({{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {acc.from_default, implicit = true, name = "arrayvar"}179// CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_present>, implicit = true, name = "arrayvar"}180 181// -----182 183func.func @test_fir_scalar_in_parallel_defaultpresent() {184  %livein = fir.alloca f32 {bindc_name = "scalarvar"}185  acc.parallel {186    %load = fir.load %livein : !fir.ref<f32>187    acc.yield188  } attributes {defaultAttr = #acc<defaultvalue present>}189  return190}191 192// CHECK: acc.firstprivate varPtr({{.*}} : !fir.ref<f32>) recipe({{.*}}) -> !fir.ref<f32> {implicit = true, name = "scalarvar"}193 194// -----195 196func.func @test_fir_scalar_in_kernels_defaultpresent() {197  %livein = fir.alloca f64 {bindc_name = "scalarvar"}198  acc.kernels {199    %load = fir.load %livein : !fir.ref<f64>200    acc.terminator201  } attributes {defaultAttr = #acc<defaultvalue present>}202  return203}204 205// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<f64>) -> !fir.ref<f64> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"}206// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<f64>) to varPtr({{.*}} : !fir.ref<f64>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "scalarvar"}207 208// -----209 210func.func @test_fir_box_ref() {211  %livein = fir.alloca !fir.box<!fir.array<?xi32>> {bindc_name = "descriptor"}212  acc.parallel {213    %load = fir.load %livein : !fir.ref<!fir.box<!fir.array<?xi32>>>214    acc.yield215  }216  return217}218 219// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.array<?xi32>>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"}220// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) to varPtr({{.*}} : !fir.ref<!fir.box<!fir.array<?xi32>>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"}221 222// -----223 224func.func @test_fir_box_val() {225  %desc = fir.alloca !fir.box<!fir.array<?xi32>> {bindc_name = "descriptor"}226  %livein = fir.load %desc : !fir.ref<!fir.box<!fir.array<?xi32>>>227  acc.parallel {228    %addr = fir.box_addr %livein : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>229    acc.yield230  }231  return232}233 234// CHECK: %[[COPYIN:.*]] = acc.copyin var({{.*}} : !fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"}235// CHECK: acc.copyout accVar(%[[COPYIN]] : !fir.box<!fir.array<?xi32>>) to var({{.*}} : !fir.box<!fir.array<?xi32>>) {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "descriptor"}236 237 238// -----239 240// This test has an explicit data clause for the box - but the pointer held241// inside the box is used in the region instead of the box itself. Test that242// implicit present is actually used.243func.func @test_explicit_box_implicit_ptr() {244  %c1 = arith.constant 1 : index245  %c10 = arith.constant 10 : index246  %arr = fir.alloca !fir.array<10xf32> {bindc_name = "aa"}247  %shape = fir.shape %c10 : (index) -> !fir.shape<1>248  %arr_decl = fir.declare %arr(%shape) {uniq_name = "aa"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>249  %box = fir.embox %arr_decl(%shape) : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf32>>250  %copyin = acc.copyin var(%box : !fir.box<!fir.array<10xf32>>) -> !fir.box<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "aa"}251  acc.serial dataOperands(%copyin : !fir.box<!fir.array<10xf32>>) {252    // Use the pointer, not the box253    %elem = fir.array_coor %arr_decl(%shape) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>254    acc.yield255  }256  acc.copyout accVar(%copyin : !fir.box<!fir.array<10xf32>>) to var(%box : !fir.box<!fir.array<10xf32>>) {dataClause = #acc<data_clause acc_copy>, name = "aa"}257  return258}259 260// CHECK: acc.present varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>){{.*}}-> !fir.ref<!fir.array<10xf32>> {implicit = true, name = "aa"}261 262// -----263 264// This test uses an explicit-shape array with no data clause - it also has265// an optimization where the pointer is used instead of the boxed entity.266// It tests that the implicit data pass is able to recover the size despite267// it not being encoded in the FIR type.268// It was generated from the following Fortran source:269//   subroutine array(aa,nn)270//     integer :: nn271//     real :: aa(10:nn)272//     !$acc kernels loop273//     do ii = 10, nn274//       aa(ii) = ii275//     end do276//     !$acc end kernels277//   end subroutine278 279func.func @_QParray(%arg0: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "aa"}, %arg1: !fir.ref<i32> {fir.bindc_name = "nn"}) {280  %c0 = arith.constant 0 : index281  %c1 = arith.constant 1 : index282  %c10_i64 = arith.constant 10 : i64283  %0 = fir.dummy_scope : !fir.dscope284  %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFarrayEnn"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>285  %4 = fir.convert %c10_i64 : (i64) -> index286  %5 = fir.load %1 : !fir.ref<i32>287  %6 = fir.convert %5 : (i32) -> i64288  %7 = fir.convert %6 : (i64) -> index289  %8 = arith.subi %7, %4 : index290  %9 = arith.addi %8, %c1 : index291  %10 = arith.cmpi sgt, %9, %c0 : index292  %11 = arith.select %10, %9, %c0 : index293  %12 = fir.shape_shift %4, %11 : (index, index) -> !fir.shapeshift<1>294  %13 = fir.declare %arg0(%12) dummy_scope %0 {uniq_name = "_QFarrayEaa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, !fir.dscope) -> !fir.ref<!fir.array<?xf32>>295  acc.kernels {296    %elem = fir.array_coor %13(%12) %4 : (!fir.ref<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>297    acc.terminator298  }299  return300}301 302// This tries to confirm that the acc.bounds operation is as expected.303// Effectively the extent needs to be max(0, nn), stride needs to be 1,304// adjusted lowerbound is 0, and actual language start index is 10.305// CHECK: %[[NN:.*]] = fir.declare %{{.*}} dummy_scope %{{.*}} {uniq_name = "_QFarrayEnn"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>306// CHECK: %[[C10:.*]] = fir.convert %c10{{.*}} : (i64) -> index307// CHECK: %[[LOADEDNN:.*]] = fir.load %[[NN]] : !fir.ref<i32>308// CHECK: %[[CAST1:.*]] = fir.convert %[[LOADEDNN]] : (i32) -> i64309// CHECK: %[[CAST2:.*]]  = fir.convert %[[CAST1]] : (i64) -> index310// CHECK: %[[SUBI:.*]] = arith.subi %[[CAST2]], %[[C10]] : index311// CHECK: %[[ADDI:.*]] = arith.addi %[[SUBI]], %c1{{.*}} : index312// CHECK: %[[CMPI:.*]] = arith.cmpi sgt, %[[ADDI]], %c0{{.*}} : index313// CHECK: %[[SELECT:.*]] = arith.select %[[CMPI]], %[[ADDI]], %c0{{.*}} : index314// CHECK: %[[BOUNDS:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[SELECT]] : index) stride(%c1{{.*}} : index) startIdx(%[[C10]] : index)315// CHECK: acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_copy>, implicit = true, name = "aa"}316 317// -----318 319// Test to confirm that a copyin clause is not implicitly generated for deviceptr symbol.320func.func @test_deviceptr_no_implicit_copy() {321  %c10 = arith.constant 10 : index322  %arr = fir.alloca !fir.array<10xf64> {bindc_name = "a"}323  %shape = fir.shape %c10 : (index) -> !fir.shape<1>324  %arr_box = fir.embox %arr(%shape) : (!fir.ref<!fir.array<10xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf64>>325  %devptr = acc.deviceptr var(%arr_box : !fir.box<!fir.array<10xf64>>) -> !fir.box<!fir.array<10xf64>> {name = "a"}326  acc.parallel dataOperands(%devptr : !fir.box<!fir.array<10xf64>>) {327    %elem = fir.box_addr %arr_box : (!fir.box<!fir.array<10xf64>>) -> !fir.ref<!fir.array<10xf64>>328    acc.yield329  }330  return331}332 333// CHECK-NOT: acc.copyin334// CHECK: acc.deviceptr335 336// -----337 338// Test that acc.declare with deviceptr doesn't generate implicit copyin339func.func @test_acc_declare_deviceptr() {340  %c10 = arith.constant 10 : index341  %arr = fir.alloca !fir.array<10xf64> {bindc_name = "a"}342  %shape = fir.shape %c10 : (index) -> !fir.shape<1>343  %arr_box = fir.embox %arr(%shape) : (!fir.ref<!fir.array<10xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<10xf64>>344  %devptr = acc.deviceptr var(%arr_box : !fir.box<!fir.array<10xf64>>) -> !fir.box<!fir.array<10xf64>> {name = "a"}345  %token = acc.declare_enter dataOperands(%devptr : !fir.box<!fir.array<10xf64>>)346  acc.parallel {347    %elem = fir.box_addr %arr_box : (!fir.box<!fir.array<10xf64>>) -> !fir.ref<!fir.array<10xf64>>348    acc.yield349  }350  acc.declare_exit token(%token)351  return352}353 354// CHECK-LABEL: func.func @test_acc_declare_deviceptr355// CHECK: acc.deviceptr356// CHECK-NOT: acc.copyin357// CHECK: acc.deviceptr358 359