diff --git a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp index c536fd19fcc69..1bb91d252529f 100644 --- a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp +++ b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp @@ -103,6 +103,8 @@ class BoxprocTypeRewriter : public mlir::TypeConverter { return needsConversion(unwrapRefType(ty)); if (auto t = mlir::dyn_cast(ty)) return needsConversion(unwrapSequenceType(ty)); + if (auto t = mlir::dyn_cast(ty)) + return needsConversion(t.getOfTy()); return false; } @@ -167,6 +169,9 @@ class BoxprocTypeRewriter : public mlir::TypeConverter { rec.finalize(ps, cs); return rec; }); + addConversion([&](TypeDescType ty) { + return TypeDescType::get(convertType(ty.getOfTy())); + }); addArgumentMaterialization(materializeProcedure); addSourceMaterialization(materializeProcedure); addTargetMaterialization(materializeProcedure); @@ -220,7 +225,6 @@ class BoxedProcedurePass auto *context = &getContext(); mlir::IRRewriter rewriter(context); BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context)); - mlir::Dialect *firDialect = context->getLoadedDialect("fir"); getModule().walk([&](mlir::Operation *op) { bool opIsValid = true; typeConverter.setLocation(op->getLoc()); @@ -366,13 +370,22 @@ class BoxedProcedurePass index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); opIsValid = false; } - } else if (op->getDialect() == firDialect) { + } else { rewriter.startOpModification(op); + // Convert the operands if needed for (auto i : llvm::enumerate(op->getResultTypes())) if (typeConverter.needsConversion(i.value())) { auto toTy = typeConverter.convertType(i.value()); op->getResult(i.index()).setType(toTy); } + + // Convert the type attributes if needed + for (const mlir::NamedAttribute &attr : op->getAttrDictionary()) + if (auto tyAttr = llvm::dyn_cast(attr.getValue())) + if (typeConverter.needsConversion(tyAttr.getValue())) { + auto toTy = typeConverter.convertType(tyAttr.getValue()); + op->setAttr(attr.getName(), mlir::TypeAttr::get(toTy)); + } rewriter.finalizeOpModification(op); } // Ensure block arguments are updated if needed. diff --git a/flang/test/Fir/boxproc-2.fir b/flang/test/Fir/boxproc-2.fir index 84132f89afebb..963dfa03663cb 100644 --- a/flang/test/Fir/boxproc-2.fir +++ b/flang/test/Fir/boxproc-2.fir @@ -13,6 +13,9 @@ func.func private @test3(!fir.boxproc<() -> (!fir.type)>) -> no //CHECK-LABEL: func.func private @test5(((i32) -> f32) -> ()) func.func private @test5(!fir.boxproc<(!fir.boxproc<(i32) -> (f32)>) -> ()>) +//CHECK-LABEL: func.func private @test6(!fir.tdesc>) -> !fir.class>>,source_p:(!fir.class>, !fir.ref) -> !fir.class>>}>,c:!fir.box>>,dx:f32,dy:f32}>>) -> !fir.ref +func.func private @test6(!fir.tdesc>) -> !fir.class>>>,source_p:!fir.boxproc<(!fir.class>, !fir.ref) -> !fir.class>>>}>,c:!fir.box>>,dx:f32,dy:f32}>>) -> !fir.ref + // CHECK-LABEL: func.func @proc_pointer_component( // CHECK-SAME: %[[VAL_0:.*]]: (!fir.ref) -> f32, // CHECK-SAME: %[[VAL_1:.*]]: !fir.ref) { diff --git a/flang/test/Fir/boxproc-openmp.fir b/flang/test/Fir/boxproc-openmp.fir new file mode 100644 index 0000000000000..8b714539b5e85 --- /dev/null +++ b/flang/test/Fir/boxproc-openmp.fir @@ -0,0 +1,87 @@ +// RUN: fir-opt --boxed-procedure %s | FileCheck %s +// Test the boxed procedure pass with OpenMP declaration operations. +// Check minimally, only arguments, yields and the private types. + +// Test a private declaration with one region (alloc) +//CHECK: omp.private {type = private} @_QFsub1Et1_private_ref_rec__QFsub1Tt : !fir.ref ()}>> alloc { +omp.private {type = private} @_QFsub1Et1_private_ref_rec__QFsub1Tt : !fir.ref ()>}>> alloc { +//CHECK: ^bb0(%{{.*}}: !fir.ref ()}>>): +^bb0(%arg0: !fir.ref ()>}>>): + %c1_i32 = arith.constant 1 : i32 + %0 = fir.alloca !fir.type<_QFsub1Tt{p1:!fir.boxproc<() -> ()>}> {bindc_name = "t1", pinned, uniq_name = "_QFsub1Et1"} + %1 = fir.declare %0 {uniq_name = "_QFsub1Et1"} : (!fir.ref ()>}>>) -> !fir.ref ()>}>> + %2 = fir.embox %1 : (!fir.ref ()>}>>) -> !fir.box ()>}>> + %3 = fir.address_of(@_QQclXea6256ba131ddd9c2210e68030a0edd3) : !fir.ref> + %4 = fir.convert %2 : (!fir.box ()>}>>) -> !fir.box + %5 = fir.convert %3 : (!fir.ref>) -> !fir.ref + %6 = fir.call @_FortranAInitialize(%4, %5, %c1_i32) fastmath : (!fir.box, !fir.ref, i32) -> none +//CHECK: omp.yield(%{{.*}} : !fir.ref ()}>>) + omp.yield(%1 : !fir.ref ()>}>>) +} +func.func @_QPsub1() { + %0 = fir.alloca !fir.type<_QFsub1Tt{p1:!fir.boxproc<() -> ()>}> {bindc_name = "t1", uniq_name = "_QFsub1Et1"} + %1 = fir.declare %0 {uniq_name = "_QFsub1Et1"} : (!fir.ref ()>}>>) -> !fir.ref ()>}>> +//CHECK: omp.parallel private(@_QFsub1Et1_private_ref_rec__QFsub1Tt %{{.*}} -> %{{.*}} : !fir.ref ()}>>) { + omp.parallel private(@_QFsub1Et1_private_ref_rec__QFsub1Tt %1 -> %arg0 : !fir.ref ()>}>>) { + %2 = fir.declare %arg0 {uniq_name = "_QFsub1Et1"} : (!fir.ref ()>}>>) -> !fir.ref ()>}>> + omp.terminator + } + return +} + + +// Test a private declaration with all regions (alloc, copy, dealloc) +//CHECK: omp.private {type = firstprivate} @_QFsub2Et1_firstprivate_ref_box_heap_rec__QFsub2Tt : +//CHECK-SAME: !fir.ref ()}>>>> alloc { +omp.private {type = firstprivate} @_QFsub2Et1_firstprivate_ref_box_heap_rec__QFsub2Tt : !fir.ref ()>}>>>> alloc { +//CHECK: ^bb0(%{{.*}}: !fir.ref ()}>>>>): +^bb0(%arg0: !fir.ref ()>}>>>>): + %0 = fir.alloca !fir.box ()>}>>> {bindc_name = "t1", pinned, uniq_name = "_QFsub2Et1"} + %1 = fir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub2Et1"} : (!fir.ref ()>}>>>>) -> !fir.ref ()>}>>>> +//CHECK: omp.yield(%{{.*}} : !fir.ref ()}>>>>) + omp.yield(%1 : !fir.ref ()>}>>>>) +} copy { +//CHECK: ^bb0(%{{.*}}: !fir.ref ()}>>>>, +//CHECK-SAME: %{{.*}}: !fir.ref ()}>>>>): +^bb0(%arg0: !fir.ref ()>}>>>>, %arg1: !fir.ref ()>}>>>>): + %c5_i32 = arith.constant 5 : i32 + %0 = fir.load %arg0 : !fir.ref ()>}>>>> + %1 = fir.box_addr %0 : (!fir.box ()>}>>>) -> !fir.heap ()>}>> + %2 = fir.embox %1 : (!fir.heap ()>}>>) -> !fir.box ()>}>> + %3 = fir.address_of(@_QQclXea) : !fir.ref> + %4 = fir.convert %arg1 : (!fir.ref ()>}>>>>) -> !fir.ref> + %5 = fir.convert %2 : (!fir.box ()>}>>) -> !fir.box + %6 = fir.convert %3 : (!fir.ref>) -> !fir.ref + %7 = fir.call @_FortranAAssign(%4, %5, %6, %c5_i32) : (!fir.ref>, !fir.box, !fir.ref, i32) -> none +//CHECK: omp.yield(%{{.*}} : !fir.ref ()}>>>>) + omp.yield(%arg1 : !fir.ref ()>}>>>>) +} dealloc { +//CHECK: ^bb0(%{{.*}}: !fir.ref ()}>>>>): +^bb0(%arg0: !fir.ref ()>}>>>>): + %c5_i32 = arith.constant 5 : i32 + %false = arith.constant false + %0 = fir.absent !fir.box + %1 = fir.address_of(@_QQclXea) : !fir.ref> + %2 = fir.convert %arg0 : (!fir.ref ()>}>>>>) -> !fir.ref> + %3 = fir.convert %1 : (!fir.ref>) -> !fir.ref + %4 = fir.call @_FortranAAllocatableDeallocate(%2, %false, %0, %3, %c5_i32) fastmath : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 + omp.yield +} +func.func @_QPsub2() { + %0 = fir.alloca !fir.box ()>}>>> {bindc_name = "t1", uniq_name = "_QFsub2Et1"} + %1 = fir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub2Et1"} : (!fir.ref ()>}>>>>) -> !fir.ref ()>}>>>> +//CHECK: omp.parallel private(@_QFsub2Et1_firstprivate_ref_box_heap_rec__QFsub2Tt %{{.*}} -> %{{.*}} : +//CHECK-SAME: !fir.ref ()}>>>>) { + omp.parallel private(@_QFsub2Et1_firstprivate_ref_box_heap_rec__QFsub2Tt %1 -> %arg0 : !fir.ref ()>}>>>>) { + %2 = fir.declare %arg0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub2Et1"} : (!fir.ref ()>}>>>>) -> !fir.ref ()>}>>>> + omp.terminator + } + return +} +func.func private @_FortranAInitialize(!fir.box, !fir.ref, i32) -> none attributes {fir.runtime} +fir.global linkonce @_QQclXea constant : !fir.char<1,8> { + %0 = fir.string_lit "pp.f90\00"(8) : !fir.char<1,8> + fir.has_value %0 : !fir.char<1,8> +} +func.func private @_FortranAAllocatableDeallocate(!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 attributes {fir.runtime} +func.func private @_FortranAAssign(!fir.ref>, !fir.box, !fir.ref, i32) -> none attributes {fir.runtime}