diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index c10e1777614cd..69e9c53baa740 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -2150,6 +2150,70 @@ privatizeIv(Fortran::lower::AbstractConverter &converter, ivPrivate.push_back(privateValue); } +static void determineDefaultLoopParMode( + Fortran::lower::AbstractConverter &converter, mlir::acc::LoopOp &loopOp, + llvm::SmallVector &seqDeviceTypes, + llvm::SmallVector &independentDeviceTypes, + llvm::SmallVector &autoDeviceTypes) { + auto hasDeviceNone = [](mlir::Attribute attr) -> bool { + return mlir::dyn_cast(attr).getValue() == + mlir::acc::DeviceType::None; + }; + bool hasDefaultSeq = llvm::any_of(seqDeviceTypes, hasDeviceNone); + bool hasDefaultIndependent = + llvm::any_of(independentDeviceTypes, hasDeviceNone); + bool hasDefaultAuto = llvm::any_of(autoDeviceTypes, hasDeviceNone); + if (hasDefaultSeq || hasDefaultIndependent || hasDefaultAuto) + return; // Default loop par mode is already specified. + + mlir::Region *currentRegion = + converter.getFirOpBuilder().getBlock()->getParent(); + mlir::Operation *parentOp = mlir::acc::getEnclosingComputeOp(*currentRegion); + const bool isOrphanedLoop = !parentOp; + if (isOrphanedLoop || + mlir::isa_and_present(parentOp)) { + // As per OpenACC 3.3 standard section 2.9.6 independent clause: + // A loop construct with no auto or seq clause is treated as if it has the + // independent clause when it is an orphaned loop construct or its parent + // compute construct is a parallel construct. + independentDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get( + converter.getFirOpBuilder().getContext(), mlir::acc::DeviceType::None)); + } else if (mlir::isa_and_present(parentOp)) { + // Serial construct implies `seq` clause on loop. However, this + // conflicts with parallelism assignment if already set. Therefore check + // that first. + bool hasDefaultGangWorkerOrVector = + loopOp.hasVector() || loopOp.getVectorValue() || loopOp.hasWorker() || + loopOp.getWorkerValue() || loopOp.hasGang() || + loopOp.getGangValue(mlir::acc::GangArgType::Num) || + loopOp.getGangValue(mlir::acc::GangArgType::Dim) || + loopOp.getGangValue(mlir::acc::GangArgType::Static); + if (!hasDefaultGangWorkerOrVector) + seqDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get( + converter.getFirOpBuilder().getContext(), + mlir::acc::DeviceType::None)); + // Since the loop has some parallelism assigned - we cannot assign `seq`. + // However, the `acc.loop` verifier will check that one of seq, independent, + // or auto is marked. Seems reasonable to mark as auto since the OpenACC + // spec does say "If not, or if it is unable to make a determination, it + // must treat the auto clause as if it is a seq clause, and it must + // ignore any gang, worker, or vector clauses on the loop construct" + else + autoDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get( + converter.getFirOpBuilder().getContext(), + mlir::acc::DeviceType::None)); + } else { + // As per OpenACC 3.3 standard section 2.9.7 auto clause: + // When the parent compute construct is a kernels construct, a loop + // construct with no independent or seq clause is treated as if it has the + // auto clause. + assert(mlir::isa_and_present(parentOp) && + "Expected kernels construct"); + autoDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get( + converter.getFirOpBuilder().getContext(), mlir::acc::DeviceType::None)); + } +} + static mlir::acc::LoopOp createLoopOp( Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, @@ -2482,6 +2546,9 @@ static mlir::acc::LoopOp createLoopOp( loopOp.setTileOperandsSegmentsAttr( builder.getDenseI32ArrayAttr(tileOperandsSegments)); + // Determine the loop's default par mode - either seq, independent, or auto. + determineDefaultLoopParMode(converter, loopOp, seqDeviceTypes, + independentDeviceTypes, autoDeviceTypes); if (!seqDeviceTypes.empty()) loopOp.setSeqAttr(builder.getArrayAttr(seqDeviceTypes)); if (!independentDeviceTypes.empty()) diff --git a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 index 8608b0ad98ce6..4e968144399a8 100644 --- a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 @@ -47,7 +47,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels { ! CHECK: acc.loop private{{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type]{{.*}}} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -59,7 +59,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels combined(loop) { ! CHECK: acc.loop combined(kernels) private{{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type]{{.*}}} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -490,7 +490,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} gang {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -503,7 +503,7 @@ subroutine acc_kernels_loop ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 ! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -516,7 +516,7 @@ subroutine acc_kernels_loop ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -528,7 +528,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -540,7 +540,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} vector {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -553,7 +553,7 @@ subroutine acc_kernels_loop ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -566,7 +566,7 @@ subroutine acc_kernels_loop ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -578,7 +578,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} worker {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -591,7 +591,7 @@ subroutine acc_kernels_loop ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -605,7 +605,7 @@ subroutine acc_kernels_loop ! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {{{.*}}collapse = [2], collapseDeviceType = [#acc.device_type]{{.*}}} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} @@ -621,9 +621,9 @@ subroutine acc_kernels_loop ! CHECK: acc.loop {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type]{{.*}}} ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type]{{.*}}} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index 0246f60705898..5baa485534b2a 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -29,7 +29,7 @@ program acc_loop ! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]}{{$}} !$acc loop seq DO i = 1, n @@ -65,7 +65,7 @@ program acc_loop ! CHECK: acc.loop gang private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop gang(num: 8) DO i = 1, n @@ -75,7 +75,7 @@ program acc_loop ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 ! CHECK: acc.loop gang({num=[[GANGNUM1]] : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop gang(num: gangNum) DO i = 1, n @@ -85,7 +85,7 @@ program acc_loop ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop gang({num=[[GANGNUM2]] : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop gang(num: gangNum, static: gangStatic) DO i = 1, n @@ -94,7 +94,7 @@ program acc_loop ! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop vector DO i = 1, n @@ -103,7 +103,7 @@ program acc_loop ! CHECK: acc.loop vector private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop vector(128) DO i = 1, n @@ -113,7 +113,7 @@ program acc_loop ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop vector([[CONSTANT128]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop vector(vectorLength) DO i = 1, n @@ -123,7 +123,7 @@ program acc_loop ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop worker DO i = 1, n @@ -132,7 +132,7 @@ program acc_loop ! CHECK: acc.loop worker private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop worker(128) DO i = 1, n @@ -142,7 +142,7 @@ program acc_loop ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop worker([[WORKER128]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop private(c) DO i = 1, n @@ -151,7 +151,7 @@ program acc_loop ! CHECK: acc.loop private(@privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! When the induction variable is explicitly private - only a single private entry should be created. !$acc loop private(i) @@ -161,7 +161,7 @@ program acc_loop ! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop private(c, d) DO i = 1, n @@ -170,7 +170,7 @@ program acc_loop ! CHECK: acc.loop private(@privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop private(c) private(d) DO i = 1, n @@ -179,7 +179,7 @@ program acc_loop ! CHECK: acc.loop private(@privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop tile(2) DO i = 1, n @@ -189,7 +189,7 @@ program acc_loop ! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop tile(*) DO i = 1, n @@ -198,7 +198,7 @@ program acc_loop ! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop tile(2, 2) DO i = 1, n @@ -211,7 +211,7 @@ program acc_loop ! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop tile(tileSize) DO i = 1, n @@ -220,7 +220,7 @@ program acc_loop ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop tile(tileSize, tileSize) DO i = 1, n @@ -231,7 +231,7 @@ program acc_loop ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop collapse(2) DO i = 1, n @@ -244,7 +244,7 @@ program acc_loop ! CHECK: fir.store %arg0 to %{{.*}} : !fir.ref ! CHECK: fir.store %arg1 to %{{.*}} : !fir.ref ! CHECK: acc.yield -! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type]{{.*}}} !$acc loop DO i = 1, n @@ -257,9 +257,9 @@ program acc_loop ! CHECK: acc.loop {{.*}} control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.loop {{.*}} control(%arg1 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop reduction(+:reduction_r) reduction(*:reduction_i) do i = 1, n @@ -269,7 +269,7 @@ program acc_loop ! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop gang(dim: gangDim, static: gangStatic) DO i = 1, n @@ -278,7 +278,7 @@ program acc_loop ! CHECK: acc.loop gang({dim=%{{.*}}, static=%{{.*}} : i32}) {{.*}} control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop gang(dim: 1) DO i = 1, n @@ -287,7 +287,7 @@ program acc_loop ! CHECK: acc.loop gang({dim={{.*}} : i32}) {{.*}} control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} !$acc loop DO i = 1, n @@ -335,4 +335,4 @@ subroutine sub1(i, j, k) ! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]] : !fir.ref) -> !fir.ref {implicit = true, name = "j"} ! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]] : !fir.ref) -> !fir.ref {implicit = true, name = "k"} ! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref, @privatization_ref_i32 -> %[[P_J]] : !fir.ref, @privatization_ref_i32 -> %[[P_K]] : !fir.ref) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%c10{{.*}}, %c100{{.*}}, %c200{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) -! CHECK: } attributes {inclusiveUpperbound = array} +! CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index 4cf268d2517f5..32060179acdf1 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -49,7 +49,7 @@ subroutine acc_parallel_loop ! CHECK: acc.parallel { ! CHECK: acc.loop private{{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -61,7 +61,7 @@ subroutine acc_parallel_loop ! CHECK: acc.parallel combined(loop) { ! CHECK: acc.loop combined(parallel) private{{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -505,7 +505,7 @@ subroutine acc_parallel_loop ! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} gang ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -518,7 +518,7 @@ subroutine acc_parallel_loop ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 ! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -531,7 +531,7 @@ subroutine acc_parallel_loop ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -543,7 +543,7 @@ subroutine acc_parallel_loop ! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -555,7 +555,7 @@ subroutine acc_parallel_loop ! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} vector ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -568,7 +568,7 @@ subroutine acc_parallel_loop ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -582,7 +582,7 @@ subroutine acc_parallel_loop ! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -595,7 +595,7 @@ subroutine acc_parallel_loop ! CHECK: acc.loop {{.*}} worker {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -609,7 +609,7 @@ subroutine acc_parallel_loop ! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -623,7 +623,7 @@ subroutine acc_parallel_loop ! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {{{.*}}collapse = [2], collapseDeviceType = [#acc.device_type]{{.*}}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -639,9 +639,9 @@ subroutine acc_parallel_loop ! CHECK: acc.loop {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}independent = [#acc.device_type]} ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}independent = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 index 34391f78ae707..af7bb0fac158c 100644 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -68,7 +68,7 @@ subroutine acc_serial_loop ! CHECK: acc.serial { ! CHECK: acc.loop private{{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}seq = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -80,7 +80,7 @@ subroutine acc_serial_loop ! CHECK: acc.serial combined(loop) { ! CHECK: acc.loop combined(serial) private{{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}seq = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -446,7 +446,7 @@ subroutine acc_serial_loop ! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} gang {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -459,7 +459,7 @@ subroutine acc_serial_loop ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 ! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -472,7 +472,7 @@ subroutine acc_serial_loop ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -484,7 +484,7 @@ subroutine acc_serial_loop ! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -496,7 +496,7 @@ subroutine acc_serial_loop ! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} vector {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -509,7 +509,7 @@ subroutine acc_serial_loop ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -522,7 +522,7 @@ subroutine acc_serial_loop ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -534,7 +534,7 @@ subroutine acc_serial_loop ! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} worker {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -547,7 +547,7 @@ subroutine acc_serial_loop ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 ! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -562,7 +562,7 @@ subroutine acc_serial_loop ! CHECK: acc.loop {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield -! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK-NEXT: } attributes {{{.*}}collapse = [2], collapseDeviceType = [#acc.device_type]{{.*}}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -578,9 +578,9 @@ subroutine acc_serial_loop ! CHECK: acc.loop {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}seq = [#acc.device_type]} ! CHECK: acc.yield -! CHECK-NEXT: }{{$}} +! CHECK-NEXT: } attributes {{{.*}}seq = [#acc.device_type]} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h index ff5845343313c..4eb666239d4e4 100644 --- a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h +++ b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h @@ -151,6 +151,12 @@ mlir::ValueRange getDataOperands(mlir::Operation *accOp); /// Used to get a mutable range iterating over the data operands. mlir::MutableOperandRange getMutableDataOperands(mlir::Operation *accOp); +/// Used to obtain the enclosing compute construct operation that contains +/// the provided `region`. Returns nullptr if no compute construct operation +/// is found. The returns operation is one of types defined by +///`ACC_COMPUTE_CONSTRUCT_OPS`. +mlir::Operation *getEnclosingComputeOp(mlir::Region ®ion); + /// Used to check whether the provided `type` implements the `PointerLikeType` /// interface. inline bool isPointerLikeType(mlir::Type type) { diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp index 658ad28477ace..c72ec47be9f04 100644 --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -3820,3 +3820,14 @@ mlir::acc::getMutableDataOperands(mlir::Operation *accOp) { .Default([&](mlir::Operation *) { return nullptr; })}; return dataOperands; } + +mlir::Operation *mlir::acc::getEnclosingComputeOp(mlir::Region ®ion) { + mlir::Operation *parentOp = region.getParentOp(); + while (parentOp) { + if (mlir::isa(parentOp)) { + return parentOp; + } + parentOp = parentOp->getParentOp(); + } + return nullptr; +}