[flang] Allow conversion from hlfir.expr to fir::ExtendedValue

For now at least, the plan is to keep hlfir.expr usage limited as
sub-expression operand, assignment rhs, and a few other contexts (
e.g. Associate statements). The rest of lowering (statements lowering
in the bridge) will still expect to get and manipulate characters and
arrays in memory. That means that hlfir.expr must be converted to
variable in converter.genExprAddr/converter.genExprBox.

This is done using an hlfir.associate, and generating the related
hlfir.end_associate in the statement context.

hlfir::getFirBase of is updated to avoid bringing in the HLFIR
fir.boxchar/fir.box into FIR when the entity was created with
hlfir::AssociateOp.

Differential Revision: https://reviews.llvm.org/D139328
This commit is contained in:
Jean Perier 2022-12-06 13:53:08 +01:00
parent bda1f0b96c
commit 788960d628
4 changed files with 46 additions and 21 deletions

View File

@ -508,12 +508,16 @@ public:
hlfir::EntityWithAttributes loweredExpr =
Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols,
context);
if (fir::FortranVariableOpInterface variable =
loweredExpr.getIfVariable())
if (!variable.isBox())
return translateToExtendedValue(loc, loweredExpr, context);
TODO(loc, "lower expr that is not a scalar or explicit shape array "
"variable to HLFIR address");
if (expr.Rank() > 0 &&
!Fortran::evaluate::IsSimplyContiguous(expr, getFoldingContext()))
TODO(loc, "genExprAddr of non contiguous variables in HLFIR");
fir::ExtendedValue exv =
translateToExtendedValue(loc, loweredExpr, context);
if (fir::isa_trivial(fir::getBase(exv).getType()))
TODO(loc, "place trivial in memory");
if (const auto *mutableBox = exv.getBoxOf<fir::MutableBoxValue>())
exv = fir::factory::genMutableBoxRead(*builder, loc, *mutableBox);
return exv;
}
return Fortran::lower::createSomeExtendedAddress(loc, *this, expr,
localSymbols, context);
@ -564,14 +568,10 @@ public:
hlfir::EntityWithAttributes loweredExpr =
Fortran::lower::convertExprToHLFIR(loc, *this, expr, localSymbols,
stmtCtx);
if (fir::FortranVariableOpInterface variable =
loweredExpr.getIfVariable())
if (variable.isBoxValue() || !variable.isBoxAddress()) {
auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx);
return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv);
}
TODO(loc,
"lower expression value or pointer and allocatable to HLFIR box");
auto exv = translateToExtendedValue(loc, loweredExpr, stmtCtx);
if (fir::isa_trivial(fir::getBase(exv).getType()))
TODO(loc, "place trivial in memory");
return fir::factory::createBoxValue(getFirOpBuilder(), loc, exv);
}
return Fortran::lower::createBoxValue(loc, *this, expr, localSymbols,
stmtCtx);

View File

@ -76,16 +76,28 @@ hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
if (entity.isVariable())
TODO(loc, "HLFIR variable to fir::ExtendedValue without a "
"FortranVariableOpInterface");
if (entity.getType().isa<hlfir::ExprType>())
TODO(loc, "hlfir.expr to fir::ExtendedValue"); // use hlfir.associate
if (entity.getType().isa<hlfir::ExprType>()) {
hlfir::AssociateOp associate = hlfir::genAssociateExpr(
loc, builder, entity, entity.getType(), "adapt.valuebyref");
auto *bldr = &builder;
hlfir::CleanupFunction cleanup = [bldr, loc, associate]() -> void {
bldr->create<hlfir::EndAssociateOp>(loc, associate);
};
hlfir::Entity temp{associate.getBase()};
return {translateToExtendedValue(loc, builder, temp).first, cleanup};
}
return {{static_cast<mlir::Value>(entity)}, {}};
}
mlir::Value hlfir::Entity::getFirBase() const {
if (fir::FortranVariableOpInterface variable = getIfVariableInterface())
if (fir::FortranVariableOpInterface variable = getIfVariableInterface()) {
if (auto declareOp =
mlir::dyn_cast<hlfir::DeclareOp>(variable.getOperation()))
return declareOp.getOriginalBase();
if (auto associateOp =
mlir::dyn_cast<hlfir::AssociateOp>(variable.getOperation()))
return associateOp.getFirBase();
}
return getBase();
}

View File

@ -27,7 +27,7 @@ end subroutine
! CHECK-LABEL: func.func @_QPcall_int_arg_expr() {
! CHECK: %[[VAL_0:.*]] = arith.constant 42 : i32
! CHECK: %[[VAL_1:.*]]:3 = hlfir.associate %[[VAL_0]] {uniq_name = "adapt.valuebyref"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
! CHECK: fir.call @_QPtake_i4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> ()
! CHECK: fir.call @_QPtake_i4(%[[VAL_1]]#1) fastmath<contract> : (!fir.ref<i32>) -> ()
! CHECK: hlfir.end_associate %[[VAL_1]]#1, %[[VAL_1]]#2 : !fir.ref<i32>, i1
subroutine call_real_arg_expr()
@ -36,7 +36,7 @@ end subroutine
! CHECK-LABEL: func.func @_QPcall_real_arg_expr() {
! CHECK: %[[VAL_0:.*]] = arith.constant 4.200000e-01 : f32
! CHECK: %[[VAL_1:.*]]:3 = hlfir.associate %[[VAL_0]] {uniq_name = "adapt.valuebyref"} : (f32) -> (!fir.ref<f32>, !fir.ref<f32>, i1)
! CHECK: fir.call @_QPtake_r4(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<f32>) -> ()
! CHECK: fir.call @_QPtake_r4(%[[VAL_1]]#1) fastmath<contract> : (!fir.ref<f32>) -> ()
! CHECK: hlfir.end_associate %[[VAL_1]]#1, %[[VAL_1]]#2 : !fir.ref<f32>, i1
subroutine call_real_arg_var(x)
@ -64,7 +64,7 @@ end subroutine
! CHECK: %[[VAL_0:.*]] = arith.constant true
! CHECK: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<4>
! CHECK: %[[VAL_2:.*]]:3 = hlfir.associate %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!fir.logical<4>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>, i1)
! CHECK: fir.call @_QPtake_l4(%[[VAL_2]]#0) fastmath<contract> : (!fir.ref<!fir.logical<4>>) -> ()
! CHECK: fir.call @_QPtake_l4(%[[VAL_2]]#1) fastmath<contract> : (!fir.ref<!fir.logical<4>>) -> ()
! CHECK: hlfir.end_associate %[[VAL_2]]#1, %[[VAL_2]]#2 : !fir.ref<!fir.logical<4>>, i1
subroutine call_logical_arg_expr_2()
@ -74,7 +74,7 @@ end subroutine
! CHECK: %[[VAL_0:.*]] = arith.constant true
! CHECK: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<8>
! CHECK: %[[VAL_2:.*]]:3 = hlfir.associate %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!fir.logical<8>) -> (!fir.ref<!fir.logical<8>>, !fir.ref<!fir.logical<8>>, i1)
! CHECK: fir.call @_QPtake_l8(%[[VAL_2]]#0) fastmath<contract> : (!fir.ref<!fir.logical<8>>) -> ()
! CHECK: fir.call @_QPtake_l8(%[[VAL_2]]#1) fastmath<contract> : (!fir.ref<!fir.logical<8>>) -> ()
! CHECK: hlfir.end_associate %[[VAL_2]]#1, %[[VAL_2]]#2 : !fir.ref<!fir.logical<8>>, i1
subroutine call_char_arg_var(x)

View File

@ -10,3 +10,16 @@ subroutine foo(x)
! CHECK: %[[x_cast:.*]] = fir.convert %[[x]]#1 : (!fir.ref<i32>) -> !fir.ref<i64>
! CHECK: fir.call @_FortranAioInputInteger(%{{.*}}, %[[x_cast]], %{{.*}}) {{.*}}: (!fir.ref<i8>, !fir.ref<i64>, i32) -> i1
end subroutine
subroutine expr_to_var(c)
character(*) :: c
print *, c//c
end subroutine
! CHECK-LABEL: func.func @_QPexpr_to_var(
! CHECK: %[[VAL_9:.*]] = hlfir.concat %{{.*}}, %{{.*}} len %[[VAL_8:.*]] : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: %[[VAL_10:.*]]:3 = hlfir.associate %[[VAL_9]] typeparams %[[VAL_8]] {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_8]] : (index) -> i64
! CHECK: %[[VAL_13:.*]] = fir.call @_FortranAioOutputAscii(%{{.*}}, %[[VAL_11]], %[[VAL_12]]) {{.*}} : (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1
! CHECK: hlfir.end_associate %[[VAL_10]]#1, %[[VAL_10]]#2 : !fir.ref<!fir.char<1,?>>, i1