[flang] emit declare for function result before call (#177615)

This change moves the declare of result storage alloca before the call
so that alias analysis can revert to linking fir.declare to the fisrt
dominating dummy_scope instead of the dominating one.

This is only relevant when MLIR inlining is enabled and is the first
step to fix issues recent TBAA changes that placed target data in its
own tree exposed an issue with the result storage of a TARGET result.
After inlining, the usages of the result storage inside the callee and
after the call ended-up being placed in different nodes (target and non
target) of the same TBAA tree (for the dominating function).

The fact that both nodes are placed in the same tree stems from
https://github.com/llvm/llvm-project/pull/146006 that fixed another TBAA
issue related to MLIR inlining and function result where the function
result was placed into the wrong TBAA tree, which with nested inlining
could end-up being the tree of a callee where the result storage was a
dummy, causing the TBAA to wrongfully tell that any access to the result
storage inside the nested callee did not alias with any access after the
call.

By moving the declare before the call that will be inlined, this patch
will allow reverting #146006 and fixing both issues: the TBAA emit for
usages of the result storage after the call will always be placed in a
different TBAA tree than any usages of the result storage inside the
callee.
This commit is contained in:
jeanPerier 2026-01-27 15:25:07 +01:00 committed by GitHub
parent 4848313824
commit 45102be5e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 77 additions and 50 deletions

View File

@ -21,6 +21,7 @@
#include "flang/Lower/CallInterface.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include <optional>
#include <tuple>
namespace Fortran::lower {
@ -37,7 +38,7 @@ using LoweredResult =
/// It is only used for HLFIR.
/// The returned boolean indicates if finalization has been emitted in
/// \p stmtCtx for the result.
std::pair<LoweredResult, bool> genCallOpAndResult(
std::tuple<LoweredResult, bool, mlir::Operation *> genCallOpAndResult(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,

View File

@ -342,7 +342,7 @@ getTypeWithIgnoreTkrC(mlir::FunctionType funcType,
return std::nullopt;
}
std::pair<Fortran::lower::LoweredResult, bool>
std::tuple<Fortran::lower::LoweredResult, bool, mlir::Operation *>
Fortran::lower::genCallOpAndResult(
mlir::Location loc, Fortran::lower::AbstractConverter &converter,
Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
@ -351,6 +351,7 @@ Fortran::lower::genCallOpAndResult(
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
using PassBy = Fortran::lower::CallerInterface::PassEntityBy;
bool mustPopSymMap = false;
mlir::Operation *callOp = nullptr;
llvm::SmallVector<mlir::Value> resultLengths;
if (isElemental)
@ -713,10 +714,10 @@ Fortran::lower::genCallOpAndResult(
}
}
cuf::KernelLaunchOp::create(builder, loc, funcType.getResults(),
funcSymbolAttr, grid_x, grid_y, grid_z, block_x,
block_y, block_z, bytes, stream, operands,
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr);
callOp = cuf::KernelLaunchOp::create(
builder, loc, funcType.getResults(), funcSymbolAttr, grid_x, grid_y,
grid_z, block_x, block_y, block_z, bytes, stream, operands,
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr);
callNumResults = 0;
} else if (caller.requireDispatchCall()) {
// Procedure call requiring a dynamic dispatch. Call is created with
@ -748,6 +749,7 @@ Fortran::lower::genCallOpAndResult(
passActual, operands, builder.getI32IntegerAttr(*passArg),
/*arg_attrs=*/nullptr,
/*res_attrs=*/nullptr, procAttrs);
callOp = dispatch;
} else {
// NOPASS
const Fortran::evaluate::Component *component =
@ -764,6 +766,7 @@ Fortran::lower::genCallOpAndResult(
builder, loc, funcType.getResults(), builder.getStringAttr(procName),
passObject, operands, nullptr, /*arg_attrs=*/nullptr,
/*res_attrs=*/nullptr, procAttrs);
callOp = dispatch;
}
callNumResults = dispatch.getNumResults();
if (callNumResults != 0)
@ -785,6 +788,7 @@ Fortran::lower::genCallOpAndResult(
builder, loc, funcType.getResults(), funcSymbolAttr, operands,
/*arg_attrs=*/nullptr, /*res_attrs=*/nullptr, procAttrs, inlineAttr,
/*accessGroups=*/mlir::ArrayAttr{});
callOp = call;
callNumResults = call.getNumResults();
if (callNumResults != 0)
@ -821,7 +825,7 @@ Fortran::lower::genCallOpAndResult(
/*finalize=*/mustFinalizeResult);
});
return {LoweredResult{hlfir::EntityWithAttributes{expr}},
mustFinalizeResult};
mustFinalizeResult, callOp};
}
if (allocatedResult) {
@ -880,13 +884,13 @@ Fortran::lower::genCallOpAndResult(
}
}
}
return {LoweredResult{*allocatedResult}, resultIsFinalized};
return {LoweredResult{*allocatedResult}, resultIsFinalized, callOp};
}
// subroutine call
if (!resultType)
return {LoweredResult{fir::ExtendedValue{mlir::Value{}}},
/*resultIsFinalized=*/false};
/*resultIsFinalized=*/false, callOp};
// For now, Fortran return values are implemented with a single MLIR
// function return value.
@ -902,11 +906,11 @@ Fortran::lower::genCallOpAndResult(
loc, builder.getCharacterLengthType(), charTy.getLen());
return {
LoweredResult{fir::ExtendedValue{fir::CharBoxValue{callResult, len}}},
/*resultIsFinalized=*/false};
/*resultIsFinalized=*/false, callOp};
}
return {LoweredResult{fir::ExtendedValue{callResult}},
/*resultIsFinalized=*/false};
/*resultIsFinalized=*/false, callOp};
}
static hlfir::EntityWithAttributes genStmtFunctionRef(
@ -1050,8 +1054,8 @@ using ExvAndCleanup =
// Helper to transform a fir::ExtendedValue to an hlfir::EntityWithAttributes.
static hlfir::EntityWithAttributes
extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder,
const fir::ExtendedValue &exv,
llvm::StringRef name) {
const fir::ExtendedValue &exv, llvm::StringRef name,
mlir::Operation *insertBefore = nullptr) {
mlir::Value firBase = fir::getBase(exv);
mlir::Type firBaseTy = firBase.getType();
if (fir::isa_trivial(firBaseTy))
@ -1073,8 +1077,26 @@ extendedValueToHlfirEntity(mlir::Location loc, fir::FirOpBuilder &builder,
builder, loc, storage, /*mustFree=*/builder.createBool(loc, false));
return hlfir::EntityWithAttributes{asExpr.getResult()};
}
return hlfir::genDeclare(loc, builder, exv, name,
fir::FortranVariableFlagsAttr{});
// TODO: better scoping model in FIR.
// The declare for result storage allocated on the callee side must
// currently be emitted before the call so that MLIR level inlining does not
// break aliasing by introducing a fir.dummy_scope between the alloca and
// fir.declare that leads the alias analysis to think that the result
// allocation is a local inside the callee scope that cannot alias with the
// usage of that temporary inside the callee because they are made through a
// declare with the TARGET attribute.
mlir::OpBuilder::InsertionGuard guard(builder);
if (insertBefore)
builder.setInsertionPoint(insertBefore);
hlfir::EntityWithAttributes declare = hlfir::genDeclare(
loc, builder, exv, name, fir::FortranVariableFlagsAttr{});
// Replace the fir.save_result "to" by the declare results instead of
// directly using the alloca.
if (insertBefore && insertBefore->getNumResults() == 1)
for (auto resUser : insertBefore->getResult(0).getUsers())
if (auto save_result = llvm::dyn_cast<fir::SaveResultOp>(resUser))
save_result.getMemrefMutable().assign(declare.getFirBase());
return declare;
}
namespace {
/// Structure to hold the clean-up related to a dummy argument preparation
@ -1909,10 +1931,11 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
// Prepare lowered arguments according to the interface
// and map the lowered values to the dummy
// arguments.
auto [loweredResult, resultIsFinalized] = Fortran::lower::genCallOpAndResult(
loc, callContext.converter, callContext.symMap, callContext.stmtCtx,
caller, callSiteType, callContext.resultType,
callContext.isElementalProcWithArrayArgs());
auto [loweredResult, resultIsFinalized, callOp] =
Fortran::lower::genCallOpAndResult(
loc, callContext.converter, callContext.symMap, callContext.stmtCtx,
caller, callSiteType, callContext.resultType,
callContext.isElementalProcWithArrayArgs());
// Clean-up associations and copy-in.
// The association clean-ups are postponed to the end of the statement
@ -1948,8 +1971,8 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
return extendedValueToHlfirEntity(loc, builder, result, tempResultName);
if (!resultIsFinalized) {
hlfir::Entity resultEntity =
extendedValueToHlfirEntity(loc, builder, result, tempResultName);
hlfir::Entity resultEntity = extendedValueToHlfirEntity(
loc, builder, result, tempResultName, /*insertBefore=*/callOp);
resultEntity = loadTrivialScalar(loc, builder, resultEntity);
if (resultEntity.isVariable()) {
// If the result has no finalization, it can be moved into an expression.
@ -1981,7 +2004,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
/*mayBePolymorphic=*/true,
/*preserveLowerBounds=*/false)
: result;
return extendedValueToHlfirEntity(loc, builder, loadedResult, tempResultName);
return extendedValueToHlfirEntity(
loc, builder, loadedResult, tempResultName,
/*insertBefore=*/!allocatable ? callOp : nullptr);
}
/// Create an optional dummy argument value from an entity that may be

View File

@ -2907,10 +2907,8 @@ public:
}
}
auto loweredResult =
Fortran::lower::genCallOpAndResult(loc, converter, symMap, stmtCtx,
caller, callSiteType, resultType)
.first;
auto loweredResult = std::get<0>(Fortran::lower::genCallOpAndResult(
loc, converter, symMap, stmtCtx, caller, callSiteType, resultType));
auto &result = std::get<ExtValue>(loweredResult);
// Sync pointers and allocatables that may have been modified during the
@ -4946,10 +4944,9 @@ private:
caller.placeInput(argIface, arg);
}
Fortran::lower::LoweredResult res =
Fortran::lower::genCallOpAndResult(loc, converter, symMap,
getElementCtx(), caller,
callSiteType, retTy)
.first;
std::get<0>(Fortran::lower::genCallOpAndResult(
loc, converter, symMap, getElementCtx(), caller, callSiteType,
retTy));
return std::get<ExtValue>(res);
};
}

View File

@ -164,8 +164,8 @@ end subroutine
! CHECK: %[[VAL_10:.*]] = arith.cmpi sgt, %[[VAL_8]], %[[VAL_9]] : index
! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_10]], %[[VAL_8]], %[[VAL_9]] : index
! CHECK: %[[VAL_13:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_11]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_14:.*]] = fir.call @_QPc2foo(%[[VAL_13]], %[[VAL_11]]) fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] typeparams %[[VAL_11]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_14:.*]] = fir.call @_QPc2foo(%[[VAL_13]], %[[VAL_11]]) fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
! -----------------------------------------------------------------------------
! Test calls with alternate returns

View File

@ -177,8 +177,8 @@ end subroutine char_return
! CHECK: ^bb0(%[[VAL_18:.*]]: index):
! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_12]]#0 (%[[VAL_18]]) typeparams %[[VAL_11]] : (!fir.box<!fir.array<?x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
! CHECK: %[[VAL_20:.*]] = fir.emboxchar %[[VAL_19]], %[[VAL_11]] : (!fir.ref<!fir.char<1,3>>, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_27:.*]] = fir.call @_QPcallee(%[[VAL_2]], %[[VAL_16]], %[[VAL_20]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,3>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_16]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
! CHECK: %[[VAL_27:.*]] = fir.call @_QPcallee(%[[VAL_2]], %[[VAL_16]], %[[VAL_20]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,3>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResultTemp:.*]] = hlfir.as_expr %[[VAL_28]]#0 move %[[MustFree]] : (!fir.ref<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
! CHECK: hlfir.yield_element %[[ResultTemp]] : !hlfir.expr<!fir.char<1,3>>

View File

@ -76,9 +76,9 @@ end subroutine
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>> {bindc_name = ".result"}
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}Ex
! CHECK: hlfir.where {
! CHECK: %[[VAL_6:.*]] = fir.call @_QPreturn_temporary_mask() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: fir.save_result %[[VAL_6]] to %[[VAL_1]] : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>)
! CHECK: %[[VAL_6:.*]] = fir.call @_QPreturn_temporary_mask() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>
! CHECK: fir.save_result %[[VAL_6]] to %[[VAL_7]]#0 : !fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[deref:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?x!fir.logical<4>>>>, i1) -> !hlfir.expr<?x!fir.logical<4>>
@ -87,9 +87,9 @@ end subroutine
! CHECK: }
! CHECK: } do {
! CHECK: hlfir.region_assign {
! CHECK: %[[VAL_14:.*]] = fir.call @_QPreturn_temporary_array() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?xf32>>>
! CHECK: fir.save_result %[[VAL_14]] to %[[VAL_0]] : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>)
! CHECK: %[[VAL_14:.*]] = fir.call @_QPreturn_temporary_array() fastmath<contract> : () -> !fir.box<!fir.heap<!fir.array<?xf32>>>
! CHECK: fir.save_result %[[VAL_14]] to %[[VAL_15]]#0 : !fir.box<!fir.heap<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[deref:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
! CHECK: %[[MustFree:.*]] = arith.constant false
! CHECK: %[[ResTemp:.*]] = hlfir.as_expr %[[deref]] move %[[MustFree]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>, i1) -> !hlfir.expr<?xf32>

View File

@ -11,8 +11,8 @@ subroutine test_storage_size(n)
end interface
integer n
print*, storage_size(return_char(n))
! CHECK: %[[val_16:.*]] = fir.call @_QPreturn_char(%[[res_addr:[^,]*]], %[[res_len:[^,]*]], {{.*}})
! CHECK: %[[res:.*]]:2 = hlfir.declare %[[res_addr]] typeparams %[[res_len]]
! CHECK: %[[res:.*]]:2 = hlfir.declare %[[res_addr:[^,]*]] typeparams %[[res_len:[^ ]*]]
! CHECK: %[[val_16:.*]] = fir.call @_QPreturn_char(%[[res_addr]], %[[res_len]], {{.*}})
! CHECK: %[[false:.*]] = arith.constant false
! CHECK: %[[expr:.*]] = hlfir.as_expr %[[res]]#0 move %[[false]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: %[[assoc:.*]]:3 = hlfir.associate %[[expr]] typeparams %[[res_len]] {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)

View File

@ -61,9 +61,9 @@ end module maxtype_mod
!CHECK: %[[OMP_IN_DECL:.*]]:2 = hlfir.declare %[[OMP_IN]] {uniq_name = "omp_in"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: fir.store %[[LHS_ARG]] to %[[OMP_OUT]] : !fir.ref<[[MAXTYPE]]>
!CHECK: %[[OMP_OUT_DECL:.*]]:2 = hlfir.declare %[[OMP_OUT]] {uniq_name = "omp_out"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: %[[COMBINE_RESULT:.*]] = fir.call @_QMmaxtype_modPmycombine(%[[OMP_OUT_DECL]]#0, %[[OMP_IN_DECL]]#0) fastmath<contract> : (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) -> [[MAXTYPE]]
!CHECK: fir.save_result %[[COMBINE_RESULT]] to %[[RESULT]] : [[MAXTYPE]], !fir.ref<[[MAXTYPE]]>
!CHECK: %[[TMPRESULT:.*]]:2 = hlfir.declare %[[RESULT]] {uniq_name = ".tmp.func_result"} : (!fir.ref<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>)
!CHECK: %[[COMBINE_RESULT:.*]] = fir.call @_QMmaxtype_modPmycombine(%[[OMP_OUT_DECL]]#0, %[[OMP_IN_DECL]]#0) fastmath<contract> : (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>) -> [[MAXTYPE]]
!CHECK: fir.save_result %[[COMBINE_RESULT]] to %[[TMPRESULT]]#0 : [[MAXTYPE]], !fir.ref<[[MAXTYPE]]>
!CHECK: %false = arith.constant false
!CHECK: %[[EXPRRESULT:.*]] = hlfir.as_expr %[[TMPRESULT]]#0 move %false : (!fir.ref<[[MAXTYPE]]>, i1) -> !hlfir.expr<[[MAXTYPE]]>
!CHECK: %[[ASSOCIATE:.*]]:3 = hlfir.associate %[[EXPRRESULT]] {adapt.valuebyref} : (!hlfir.expr<[[MAXTYPE]]>) -> (!fir.ref<[[MAXTYPE]]>, !fir.ref<[[MAXTYPE]]>, i1)

View File

@ -39,8 +39,8 @@ end subroutine
! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<i64>
! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_1]]#0 (%[[VAL_18]]) typeparams %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, i64, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_20:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_14]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_21:.*]] = fir.call @_QPbug_145151_1(%[[VAL_20]], %[[VAL_14]], %[[VAL_19]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] typeparams %[[VAL_14]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_21:.*]] = fir.call @_QPbug_145151_1(%[[VAL_20]], %[[VAL_14]], %[[VAL_19]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_23:.*]] = arith.constant false
! CHECK: %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_22]]#0 move %[[VAL_23]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_24]] : !hlfir.expr<!fir.char<1,?>>
@ -97,8 +97,8 @@ end subroutine
! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_14]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref<f32>
! CHECK: %[[VAL_17:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_12]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_18:.*]] = fir.call @_QPbug_145151_2(%[[VAL_17]], %[[VAL_12]], %[[VAL_16]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, f32) -> !fir.boxchar<1>
! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_17]] typeparams %[[VAL_12]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_18:.*]] = fir.call @_QPbug_145151_2(%[[VAL_17]], %[[VAL_12]], %[[VAL_16]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, f32) -> !fir.boxchar<1>
! CHECK: %[[VAL_20:.*]] = arith.constant false
! CHECK: %[[VAL_21:.*]] = hlfir.as_expr %[[VAL_19]]#0 move %[[VAL_20]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_21]] : !hlfir.expr<!fir.char<1,?>>
@ -165,8 +165,8 @@ end subroutine
! CHECK: fir.result %[[VAL_27]] : !fir.ref<f32>
! CHECK: }
! CHECK: %[[VAL_28:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_21]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_29:.*]] = fir.call @_QPf_opt(%[[VAL_28]], %[[VAL_21]], %[[VAL_24]], %[[VAL_25]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.ref<f32>, !fir.ref<f32>) -> !fir.boxchar<1>
! CHECK: %[[VAL_30:.*]]:2 = hlfir.declare %[[VAL_28]] typeparams %[[VAL_21]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_29:.*]] = fir.call @_QPf_opt(%[[VAL_28]], %[[VAL_21]], %[[VAL_24]], %[[VAL_25]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.ref<f32>, !fir.ref<f32>) -> !fir.boxchar<1>
! CHECK: %[[VAL_31:.*]] = arith.constant false
! CHECK: %[[VAL_32:.*]] = hlfir.as_expr %[[VAL_30]]#0 move %[[VAL_31]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_32]] : !hlfir.expr<!fir.char<1,?>>
@ -231,8 +231,8 @@ end subroutine
! CHECK: %[[VAL_32:.*]] = hlfir.designate %[[VAL_1]]#0 (%[[VAL_31]]) : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, index) -> !fir.class<!fir.type<_QFtest_polymorphicTt>>
! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_31]]) : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphicTt>>>, index) -> !fir.class<!fir.type<_QFtest_polymorphicTt>>
! CHECK: %[[VAL_34:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_29]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_35:.*]] = fir.call @_QPf_poly(%[[VAL_34]], %[[VAL_29]], %[[VAL_32]], %[[VAL_33]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.class<!fir.type<_QFtest_polymorphicTt>>, !fir.class<!fir.type<_QFtest_polymorphicTt>>) -> !fir.boxchar<1>
! CHECK: %[[VAL_36:.*]]:2 = hlfir.declare %[[VAL_34]] typeparams %[[VAL_29]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_35:.*]] = fir.call @_QPf_poly(%[[VAL_34]], %[[VAL_29]], %[[VAL_32]], %[[VAL_33]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.class<!fir.type<_QFtest_polymorphicTt>>, !fir.class<!fir.type<_QFtest_polymorphicTt>>) -> !fir.boxchar<1>
! CHECK: %[[VAL_37:.*]] = arith.constant false
! CHECK: %[[VAL_38:.*]] = hlfir.as_expr %[[VAL_36]]#0 move %[[VAL_37]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_38]] : !hlfir.expr<!fir.char<1,?>>
@ -278,8 +278,8 @@ end subroutine
! CHECK: %[[VAL_18:.*]] = hlfir.as_expr %[[VAL_17]] : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: %[[VAL_19:.*]]:3 = hlfir.associate %[[VAL_18]] typeparams %[[VAL_16]] {adapt.valuebyref} : (!hlfir.expr<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>, i1)
! CHECK: %[[VAL_20:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_13]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_21:.*]] = fir.call @_QPf_value(%[[VAL_20]], %[[VAL_13]], %[[VAL_19]]#0) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] typeparams %[[VAL_13]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_21:.*]] = fir.call @_QPf_value(%[[VAL_20]], %[[VAL_13]], %[[VAL_19]]#0) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_23:.*]] = arith.constant false
! CHECK: %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_22]]#0 move %[[VAL_23]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.end_associate %[[VAL_19]]#1, %[[VAL_19]]#2 : !fir.ref<!fir.char<1,?>>, i1

View File

@ -253,8 +253,8 @@ end subroutine
! CHECK: ^bb0(%[[VAL_17:.*]]: index):
! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_17]]) typeparams %[[VAL_2]]#1 : (!fir.box<!fir.array<10x!fir.char<1,?>>>, index, index) -> !fir.boxchar<1>
! CHECK: %[[VAL_28:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_15]] : index) {bindc_name = ".result"}
! CHECK: %[[VAL_29:.*]] = fir.call @_QMchar_elemPelem_return_char(%[[VAL_28]], %[[VAL_15]], %[[VAL_18]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_30:.*]]:2 = hlfir.declare %[[VAL_28]] typeparams %[[VAL_15]] {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
! CHECK: %[[VAL_29:.*]] = fir.call @_QMchar_elemPelem_return_char(%[[VAL_28]], %[[VAL_15]], %[[VAL_18]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<!fir.char<1,?>>, index, !fir.boxchar<1>) -> !fir.boxchar<1>
! CHECK: %[[VAL_31:.*]] = arith.constant false
! CHECK: %[[VAL_32:.*]] = hlfir.as_expr %[[VAL_30]]#0 move %[[VAL_31]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
! CHECK: hlfir.yield_element %[[VAL_32]] : !hlfir.expr<!fir.char<1,?>>

View File

@ -17,22 +17,25 @@ subroutine test_temp_io_options(status)
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: fir.call @_FortranAioBeginOpenUnit
! CHECK: %[[DECLARE3:.*]] = fir.declare %[[VAL_3]]
! CHECK: %[[VAL_15:.*]] = fir.call @_QPgen_temp_character() {{.*}}: () -> !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: fir.save_result %[[VAL_15]] to %[[VAL_3]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: fir.save_result %[[VAL_15]] to %[[DECLARE3]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_21:.*]] = fir.call @_FortranAioSetEncoding
! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_23:.*]] = fir.box_addr %[[VAL_22]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
! CHECK: fir.freemem %[[VAL_23]] : !fir.heap<!fir.char<1,?>>
! CHECK: fir.if %[[VAL_21]] {
! CHECK: %[[DECLARE2:.*]] = fir.declare %[[VAL_2]]
! CHECK: %[[VAL_27:.*]] = fir.call @_QPgen_temp_character() {{.*}}: () -> !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: fir.save_result %[[VAL_27]] to %[[VAL_2]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: fir.save_result %[[VAL_27]] to %[[DECLARE2]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_33:.*]] = fir.call @_FortranAioSetFile
! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_35:.*]] = fir.box_addr %[[VAL_34]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
! CHECK: fir.freemem %[[VAL_35]] : !fir.heap<!fir.char<1,?>>
! CHECK: fir.if %[[VAL_33]] {
! CHECK: %[[DECLARE1:.*]] = fir.declare %[[VAL_1]]
! CHECK: %[[VAL_39:.*]] = fir.call @_QPgen_temp_character() {{.*}}: () -> !fir.box<!fir.heap<!fir.char<1,?>>>
! CHECK: fir.save_result %[[VAL_39]] to %[[VAL_1]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: fir.save_result %[[VAL_39]] to %[[DECLARE1]] : !fir.box<!fir.heap<!fir.char<1,?>>>, !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: fir.call @_FortranAioSetPad
! CHECK: %[[VAL_46:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
! CHECK: %[[VAL_47:.*]] = fir.box_addr %[[VAL_46]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>

View File

@ -56,8 +56,9 @@ end program main
! DEVICE: omp.distribute {
! COMMON: omp.wsloop {
! COMMON: omp.loop_nest {{.*}} {
! COMMON: %[[DECLARE:.*]]:2 = hlfir.declare %[[LOCAL_TEMP]]
! COMMON: %[[TEMP_VAL:.*]] = fir.call @_QMstruct_modPconstruct_from_components
! COMMON: fir.save_result %[[TEMP_VAL]] to %[[LOCAL_TEMP]]
! COMMON: fir.save_result %[[TEMP_VAL]] to %[[DECLARE]]#0
! COMMON: %[[EMBOXED_LOCAL:.*]] = fir.embox %[[LOCAL_TEMP]]
! COMMON: %[[CONVERTED_LOCAL:.*]] = fir.convert %[[EMBOXED_LOCAL]]
! COMMON: fir.call @_FortranADestroy(%[[CONVERTED_LOCAL]])