diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 06697b2dbc1d5..82daa05c165cb 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -831,9 +831,9 @@ fir::ShapeOp genShapeOp(mlir::OpBuilder &builder, fir::SequenceType seqTy, template static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, - mlir::Type ty, mlir::Location loc) { + mlir::Type argTy, mlir::Location loc) { mlir::Value retVal = recipe.getInitRegion().front().getArgument(0); - ty = fir::unwrapRefType(ty); + mlir::Type unwrappedTy = fir::unwrapRefType(argTy); auto getDeclareOpForType = [&](mlir::Type ty) -> hlfir::DeclareOp { auto alloca = builder.create(loc, ty); @@ -843,9 +843,10 @@ static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, fir::FortranVariableFlagsAttr{}); }; - if (fir::isa_trivial(ty)) { - retVal = getDeclareOpForType(ty).getBase(); - } else if (auto seqTy = mlir::dyn_cast_or_null(ty)) { + if (fir::isa_trivial(unwrappedTy)) { + retVal = getDeclareOpForType(unwrappedTy).getBase(); + } else if (auto seqTy = + mlir::dyn_cast_or_null(unwrappedTy)) { if (fir::isa_trivial(seqTy.getEleTy())) { mlir::Value shape; llvm::SmallVector extents; @@ -866,15 +867,33 @@ static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{}); retVal = declareOp.getBase(); } - } else if (auto boxTy = mlir::dyn_cast_or_null(ty)) { + } else if (auto boxTy = + mlir::dyn_cast_or_null(unwrappedTy)) { mlir::Type innerTy = fir::unwrapRefType(boxTy.getEleTy()); if (fir::isa_trivial(innerTy)) { - retVal = getDeclareOpForType(ty).getBase(); + retVal = getDeclareOpForType(unwrappedTy).getBase(); } else if (mlir::isa(innerTy)) { fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; hlfir::Entity source = hlfir::Entity{retVal}; auto [temp, cleanup] = hlfir::createTempFromMold(loc, firBuilder, source); - retVal = temp; + if (fir::isa_ref_type(argTy)) { + // When the temp is created - it is not a reference - thus we can + // end up with a type inconsistency. Therefore ensure storage is created + // for it. + retVal = getDeclareOpForType(unwrappedTy).getBase(); + mlir::Value storeDst = retVal; + if (fir::unwrapRefType(retVal.getType()) != temp.getType()) { + // `createTempFromMold` makes the unfortunate choice to lose the + // `fir.heap` and `fir.ptr` types when wrapping with a box. Namely, + // when wrapping a `fir.heap`, it will create instead a + // `fir.box`. Cast here to deal with this inconsistency. + storeDst = firBuilder.createConvert( + loc, firBuilder.getRefType(temp.getType()), retVal); + } + builder.create(loc, temp, storeDst); + } else { + retVal = temp; + } } else { TODO(loc, "Unsupported boxed type in OpenACC privatization"); } diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index 76e23b8915e92..b1bfb02439f03 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -84,7 +84,11 @@ ! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> ! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} ! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box>> +! CHECK: %[[DECLAREBOX:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[CONV:.*]] = fir.convert %[[DECLAREBOX]]#0 : (!fir.ref>>>) -> !fir.ref>> +! CHECK: fir.store %[[DECLARE]]#0 to %[[CONV]] : !fir.ref>> +! CHECK: acc.yield %[[DECLAREBOX]]#0 : !fir.ref>>> ! CHECK: } ! CHECK-LABEL: @privatization_ref_box_heap_i32 : !fir.ref>> init { @@ -102,7 +106,11 @@ ! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> ! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} ! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) -! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box>> +! CHECK: %[[DECLAREBOX:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[CONV:.*]] = fir.convert %[[DECLAREBOX]]#0 : (!fir.ref>>>) -> !fir.ref>> +! CHECK: fir.store %[[DECLARE]]#0 to %[[CONV]] : !fir.ref>> +! CHECK: acc.yield %[[DECLAREBOX]]#0 : !fir.ref>>> ! CHECK: } ! CHECK-LABEL: acc.private.recipe @privatization_box_Uxi32 : !fir.box> init {