diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index e09266121cdb9..49db55047ff02 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -920,18 +920,27 @@ static mlir::Value genReductionInitRegion(fir::FirOpBuilder &builder, declareOp.getBase()); return declareOp.getBase(); } else if (auto seqTy = mlir::dyn_cast_or_null(ty)) { - if (seqTy.hasDynamicExtents()) - TODO(loc, "reduction recipe of array with dynamic extents"); if (fir::isa_trivial(seqTy.getEleTy())) { - mlir::Value alloca = builder.create(loc, seqTy); - auto shapeOp = genShapeOp(builder, seqTy, loc); + mlir::Value shape; + auto extents = builder.getBlock()->getArguments().drop_front(1); + if (seqTy.hasDynamicExtents()) + shape = builder.create(loc, extents); + else + shape = genShapeOp(builder, seqTy, loc); + mlir::Value alloca = builder.create( + loc, seqTy, /*typeparams=*/mlir::ValueRange{}, extents); auto declareOp = builder.create( - loc, alloca, accReductionInitName, shapeOp, + loc, alloca, accReductionInitName, shape, llvm::ArrayRef{}, fir::FortranVariableFlagsAttr{}); mlir::Type idxTy = builder.getIndexType(); mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); llvm::SmallVector loops; llvm::SmallVector ivs; + + if (seqTy.hasDynamicExtents()) { + builder.create(loc, initValue, declareOp.getBase()); + return declareOp.getBase(); + } for (auto ext : llvm::reverse(seqTy.getShape())) { auto lb = builder.createIntegerConstant(loc, idxTy, 0); auto ub = builder.createIntegerConstant(loc, idxTy, ext - 1); @@ -1052,6 +1061,18 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder, TODO(loc, "reduction operator"); } +static hlfir::DesignateOp::Subscripts +getTripletsFromArgs(mlir::acc::ReductionRecipeOp recipe) { + hlfir::DesignateOp::Subscripts triplets; + for (unsigned i = 2; i < recipe.getCombinerRegion().getArguments().size(); + i += 3) + triplets.emplace_back(hlfir::DesignateOp::Triplet{ + recipe.getCombinerRegion().getArgument(i), + recipe.getCombinerRegion().getArgument(i + 1), + recipe.getCombinerRegion().getArgument(i + 2)}); + return triplets; +} + static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::acc::ReductionOperator op, mlir::Type ty, mlir::Value value1, mlir::Value value2, @@ -1061,11 +1082,60 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, ty = fir::unwrapRefType(ty); if (auto seqTy = mlir::dyn_cast(ty)) { - assert(!seqTy.hasDynamicExtents() && - "Assumed shaped array should be boxed for reduction"); mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); llvm::SmallVector loops; llvm::SmallVector ivs; + if (seqTy.hasDynamicExtents()) { + auto shape = + genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds, + recipe.getCombinerRegion().getArguments()); + auto v1DeclareOp = builder.create( + loc, value1, llvm::StringRef{}, shape, llvm::ArrayRef{}, + fir::FortranVariableFlagsAttr{}); + auto v2DeclareOp = builder.create( + loc, value2, llvm::StringRef{}, shape, llvm::ArrayRef{}, + fir::FortranVariableFlagsAttr{}); + hlfir::DesignateOp::Subscripts triplets = getTripletsFromArgs(recipe); + + llvm::SmallVector lenParamsLeft; + auto leftEntity = hlfir::Entity{v1DeclareOp.getBase()}; + hlfir::genLengthParameters(loc, builder, leftEntity, lenParamsLeft); + auto leftDesignate = builder.create( + loc, v1DeclareOp.getBase().getType(), v1DeclareOp.getBase(), + /*component=*/"", + /*componentShape=*/mlir::Value{}, triplets, + /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, + shape, lenParamsLeft); + auto left = hlfir::Entity{leftDesignate.getResult()}; + + llvm::SmallVector lenParamsRight; + auto rightEntity = hlfir::Entity{v2DeclareOp.getBase()}; + hlfir::genLengthParameters(loc, builder, rightEntity, lenParamsLeft); + auto rightDesignate = builder.create( + loc, v2DeclareOp.getBase().getType(), v2DeclareOp.getBase(), + /*component=*/"", + /*componentShape=*/mlir::Value{}, triplets, + /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, + shape, lenParamsRight); + auto right = hlfir::Entity{rightDesignate.getResult()}; + + llvm::SmallVector typeParams; + auto genKernel = [&builder, &loc, op, seqTy, &left, &right]( + mlir::Location l, fir::FirOpBuilder &b, + mlir::ValueRange oneBasedIndices) -> hlfir::Entity { + auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices); + auto rightElement = hlfir::getElementAt(l, b, right, oneBasedIndices); + auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement); + auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement); + return hlfir::Entity{genScalarCombiner( + builder, loc, op, seqTy.getEleTy(), leftVal, rightVal)}; + }; + mlir::Value elemental = hlfir::genElementalOp( + loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel, + /*isUnordered=*/true); + builder.create(loc, elemental, v1DeclareOp.getBase()); + return; + } if (allConstantBound) { // Use the constant bound directly in the combiner region so they do not // need to be passed as block argument. @@ -1108,7 +1178,6 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, builder.create(loc, res, addr1); builder.setInsertionPointAfter(loops[0]); } else if (auto boxTy = mlir::dyn_cast(ty)) { - llvm::SmallVector tripletArgs; mlir::Type innerTy = extractSequenceType(boxTy); fir::SequenceType seqTy = mlir::dyn_cast_or_null(innerTy); @@ -1160,8 +1229,20 @@ mlir::acc::ReductionRecipeOp Fortran::lower::createOrGetReductionRecipe( mlir::OpBuilder modBuilder(mod.getBodyRegion()); auto recipe = modBuilder.create(loc, recipeName, ty, op); + llvm::SmallVector initArgsTy{ty}; + llvm::SmallVector initArgsLoc{loc}; + mlir::Type refTy = fir::unwrapRefType(ty); + if (auto seqTy = mlir::dyn_cast_or_null(refTy)) { + if (seqTy.hasDynamicExtents()) { + mlir::Type idxTy = builder.getIndexType(); + for (unsigned i = 0; i < seqTy.getDimension(); ++i) { + initArgsTy.push_back(idxTy); + initArgsLoc.push_back(loc); + } + } + } builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(), - {ty}, {loc}); + initArgsTy, initArgsLoc); builder.setInsertionPointToEnd(&recipe.getInitRegion().back()); mlir::Value initValue = genReductionInitRegion(builder, loc, ty, op); builder.create(loc, initValue); diff --git a/flang/test/Lower/OpenACC/acc-reduction.f90 b/flang/test/Lower/OpenACC/acc-reduction.f90 index 07979445394d9..b874d5219625d 100644 --- a/flang/test/Lower/OpenACC/acc-reduction.f90 +++ b/flang/test/Lower/OpenACC/acc-reduction.f90 @@ -3,6 +3,35 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefixes=CHECK,FIR ! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,HLFIR +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_UxUxf32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index): +! HLFIR: %[[CST:.*]] = arith.constant -1.401300e-45 : f32 +! HLFIR: %[[SHAPE:.*]] = fir.shape %arg1, %arg2 : (index, index) -> !fir.shape<2> +! HLFIR: %[[TEMP:.*]] = fir.alloca !fir.array, %arg1, %arg2 +! HLFIR: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.box>, !fir.ref>) +! HLFIR: hlfir.assign %[[CST]] to %[[DECL]]#0 : f32, !fir.box> +! HLFIR: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } combiner { +! CHECK: ^bb0(%[[V1:.*]]: !fir.ref>, %[[V2:.*]]: !fir.ref>, %[[LB0:.*]]: index, %[[UB0:.*]]: index, %[[STEP0:.*]]: index, %[[LB1:.*]]: index, %[[UB1:.*]]: index, %[[STEP1:.*]]: index): +! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! HLFIR: %[[DECL_V1:.*]]:2 = hlfir.declare %[[V1]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<2>) -> (!fir.box>, !fir.ref>) +! HLFIR: %[[DECL_V2:.*]]:2 = hlfir.declare %[[V2]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<2>) -> (!fir.box>, !fir.ref>) +! HLFIR: %[[DES_V1:.*]] = hlfir.designate %[[DECL_V1]]#0 (%arg2:%arg3:%arg4, %arg5:%arg6:%arg7) shape %10 : (!fir.box>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box> +! HLFIR: %[[DES_V2:.*]] = hlfir.designate %[[DECL_V2]]#0 (%arg2:%arg3:%arg4, %arg5:%arg6:%arg7) shape %10 : (!fir.box>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box> +! HLFIR: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<2>) -> !hlfir.expr { +! HLFIR: ^bb0(%[[ARG0:.*]]: index, %[[ARG1:.*]]: index): +! HLFIR: %[[D1:.*]] = hlfir.designate %13 (%[[ARG0]], %[[ARG1]]) : (!fir.box>, index, index) -> !fir.ref +! HLFIR: %[[D2:.*]] = hlfir.designate %14 (%[[ARG0]], %[[ARG1]]) : (!fir.box>, index, index) -> !fir.ref +! HLFIR: %[[LOAD1:.*]] = fir.load %[[D1]] : !fir.ref +! HLFIR: %[[LOAD2:.*]] = fir.load %[[D2]] : !fir.ref +! HLFIR: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD1]], %[[LOAD2]] : f32 +! HLFIR: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 +! HLFIR: hlfir.yield_element %[[SELECT]] : f32 +! HLFIR: } +! HLFIR: hlfir.assign %[[ELEMENTAL]] to %[[DECL_V1]]#0 : !hlfir.expr, !fir.box> +! HLFIR: acc.yield %[[V1]] : !fir.ref> +! CHECK: } + ! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_ptr_Uxf32 : !fir.box>> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.box>>): ! CHECK: } combiner { @@ -290,8 +319,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_max_section_ext100_ref_100xf32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant -1.401300e-45 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[LB:.*]] = arith.constant 0 : index ! CHECK: %[[UB:.*]] = arith.constant 99 : index @@ -338,8 +367,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_max_section_ext100xext10_ref_100x10xi32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%arg0: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -384,8 +413,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_min_section_ext100xext10_ref_100x10xf32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -430,8 +459,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_min_section_ext100_ref_100xi32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -487,8 +516,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_mul_section_ext100_ref_100xi32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 1 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -526,8 +555,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100_ref_100xf32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -565,8 +594,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100xext10xext2_ref_100x10x2xi32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10x2xi32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10x2xi32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<3>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -598,8 +627,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100xext10_ref_100x10xi32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -626,8 +655,8 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100_ref_100xi32 : !fir.ref> reduction_operator init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HFLIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } combiner { @@ -1134,13 +1163,13 @@ subroutine acc_reduction_add_dynamic_extent_add(a) ! HLFIR: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} ! HLFIR: acc.parallel reduction(@reduction_add_box_Uxi32 -> %[[RED:.*]] : !fir.ref>) -subroutine acc_reduction_add_dynamic_extent_max(a) +subroutine acc_reduction_add_assumed_shape_max(a) real :: a(:) !$acc parallel reduction(max:a) !$acc end parallel end subroutine -! CHECK-LABEL: func.func @_QPacc_reduction_add_dynamic_extent_max( +! CHECK-LABEL: func.func @_QPacc_reduction_add_assumed_shape_max( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"}) ! HLFIR: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] ! HLFIR: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} @@ -1189,3 +1218,16 @@ subroutine acc_reduction_add_pointer_array(a) ! HLFIR: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.ptr> ! HLFIR: %[[RED:.*]] = acc.reduction varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%[[BOUND]]) -> !fir.ptr> {name = "a"} ! HLFIR: acc.parallel reduction(@reduction_max_box_ptr_Uxf32 -> %[[RED]] : !fir.ptr>) + +subroutine acc_reduction_max_dynamic_extent_max(a, n) + integer :: n + real :: a(n, n) + !$acc parallel reduction(max:a) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_dynamic_extent_max( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}, %{{.*}}: !fir.ref {fir.bindc_name = "n"}) +! HLFIR: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) {uniq_name = "_QFacc_reduction_max_dynamic_extent_maxEa"} : (!fir.ref>, !fir.shape<2>) -> (!fir.box>, !fir.ref>) +! HLFIR: %[[RED:.*]] = acc.reduction varPtr(%[[DECL_A]]#1 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! HLFIR: acc.parallel reduction(@reduction_max_ref_UxUxf32 -> %[[RED]] : !fir.ref>)