[flang] Handle volatility in lowering and codegen (#135311)

* Enable lowering and conversion patterns to pass volatility information
from higher level operations to lower level ones.
* Enable codegen to pass volatility to LLVM dialect ops by setting an
attribute on loads, stores, and memory intrinsics.
* Add utilities for passing along the volatility from an input type to
an output type.

To introduce volatile types into the IR, entities with the volatile
attribute will be given a volatile type in the bridge; this is not
enabled in this patch. User code should not result in IR with volatile
types yet, so this patch contains no tests with Fortran source, only IR
that already contains volatile types.

Part 3 of #132486.
This commit is contained in:
Asher Mancinelli
2025-04-14 11:02:23 -07:00
committed by GitHub
parent df84aa8e06
commit c9ec1bc753
18 changed files with 674 additions and 67 deletions

View File

@@ -236,7 +236,7 @@ public:
auto ty = getBoxTy().getEleTy();
if (fir::isa_ref_type(ty))
return ty;
return fir::ReferenceType::get(ty);
return fir::ReferenceType::get(ty, fir::isa_volatile_type(ty));
}
/// Get the scalar type related to the described entity

View File

@@ -402,6 +402,10 @@ public:
mlir::Value createConvertWithVolatileCast(mlir::Location loc, mlir::Type toTy,
mlir::Value val);
/// Cast \p value to have \p isVolatile volatility.
mlir::Value createVolatileCast(mlir::Location loc, bool isVolatile,
mlir::Value value);
/// Create a fir.store of \p val into \p addr. A lazy conversion
/// of \p val to the element type of \p addr is created if needed.
void createStoreWithConvert(mlir::Location loc, mlir::Value val,

View File

@@ -327,7 +327,6 @@ Fortran::lower::genCallOpAndResult(
charFuncPointerLength = charBox->getLen();
}
}
const bool isExprCall =
converter.getLoweringOptions().getLowerToHighLevelFIR() &&
callSiteType.getNumResults() == 1 &&
@@ -519,7 +518,9 @@ Fortran::lower::genCallOpAndResult(
// Do not attempt any reboxing here that could break this.
bool legacyLowering =
!converter.getLoweringOptions().getLowerToHighLevelFIR();
cast = builder.convertWithSemantics(loc, snd, fst,
bool isVolatile = fir::isa_volatile_type(snd);
cast = builder.createVolatileCast(loc, isVolatile, fst);
cast = builder.convertWithSemantics(loc, snd, cast,
callingImplicitInterface,
/*allowRebox=*/legacyLowering);
}
@@ -1415,6 +1416,11 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
addr = hlfir::genVariableRawAddress(loc, builder, entity);
}
// If the volatility of the input type does not match the dummy type,
// we need to cast the argument.
const bool isToTypeVolatile = fir::isa_volatile_type(dummyTypeWithActualRank);
addr = builder.createVolatileCast(loc, isToTypeVolatile, addr);
// For ranked actual passed to assumed-rank dummy, the cast to assumed-rank
// box is inserted when building the fir.call op. Inserting it here would
// cause the fir.if results to be assumed-rank in case of OPTIONAL dummy,

View File

@@ -212,19 +212,25 @@ private:
auto charType = mlir::dyn_cast<fir::CharacterType>(resultValueType);
if (charType && charType.hasDynamicLen())
return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
// When volatile is enabled, enable volatility on the designatory type.
const bool isVolatile = false;
// Arrays with non default lower bounds or dynamic length or dynamic extent
// need a fir.box to hold the dynamic or lower bound information.
if (fir::hasDynamicSize(resultValueType) ||
mayHaveNonDefaultLowerBounds(partInfo))
return fir::BoxType::get(resultValueType);
return fir::BoxType::get(resultValueType, isVolatile);
// Non simply contiguous ref require a fir.box to carry the byte stride.
if (mlir::isa<fir::SequenceType>(resultValueType) &&
!Fortran::evaluate::IsSimplyContiguous(
designatorNode, getConverter().getFoldingContext(),
/*namedConstantSectionsAreAlwaysContiguous=*/false))
return fir::BoxType::get(resultValueType);
return fir::BoxType::get(resultValueType, isVolatile);
// Other designators can be handled as raw addresses.
return fir::ReferenceType::get(resultValueType);
return fir::ReferenceType::get(resultValueType, isVolatile);
}
template <typename T>
@@ -1824,7 +1830,10 @@ private:
assert(compType && "failed to retrieve component type");
mlir::Value compShape =
designatorBuilder.genComponentShape(sym, compType);
mlir::Type designatorType = builder.getRefType(compType);
const bool isDesignatorVolatile =
fir::isa_volatile_type(baseOp.getType());
mlir::Type designatorType =
builder.getRefType(compType, isDesignatorVolatile);
mlir::Type fieldElemType = hlfir::getFortranElementType(compType);
llvm::SmallVector<mlir::Value, 1> typeParams;

View File

@@ -194,8 +194,8 @@ public:
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy(args.addrInTuple.getType());
assert(typeInTuple && "addrInTuple must be an address");
mlir::Value castBox = builder.createConvert(args.loc, typeInTuple,
fir::getBase(args.hostValue));
mlir::Value castBox = builder.createConvertWithVolatileCast(
args.loc, typeInTuple, fir::getBase(args.hostValue));
builder.create<fir::StoreOp>(args.loc, castBox, args.addrInTuple);
}
@@ -265,8 +265,8 @@ public:
mlir::Location loc = args.loc;
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy(args.addrInTuple.getType());
assert(typeInTuple && "addrInTuple must be an address");
mlir::Value castBox = builder.createConvert(args.loc, typeInTuple,
fir::getBase(args.hostValue));
mlir::Value castBox = builder.createConvertWithVolatileCast(
args.loc, typeInTuple, fir::getBase(args.hostValue));
if (Fortran::semantics::IsOptional(sym)) {
auto isPresent =
builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), castBox);
@@ -329,8 +329,8 @@ public:
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy(args.addrInTuple.getType());
assert(typeInTuple && "addrInTuple must be an address");
mlir::Value castBox = builder.createConvert(args.loc, typeInTuple,
fir::getBase(args.hostValue));
mlir::Value castBox = builder.createConvertWithVolatileCast(
args.loc, typeInTuple, fir::getBase(args.hostValue));
builder.create<fir::StoreOp>(args.loc, castBox, args.addrInTuple);
}
static void getFromTuple(const GetFromTuple &args,

View File

@@ -720,7 +720,8 @@ static void genOutputItemList(
fir::factory::CharacterExprHelper helper{builder, loc};
if (mlir::isa<fir::BoxType>(argType)) {
mlir::Value box = fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));
outputFuncArgs.push_back(builder.createConvert(loc, argType, box));
outputFuncArgs.push_back(
builder.createConvertWithVolatileCast(loc, argType, box));
if (containsDerivedType(itemTy))
outputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
} else if (helper.isCharacterScalar(itemTy)) {
@@ -730,9 +731,9 @@ static void genOutputItemList(
if (!exv.getCharBox())
llvm::report_fatal_error(
"internal error: scalar character not in CharBox");
outputFuncArgs.push_back(builder.createConvert(
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(
loc, outputFunc.getFunctionType().getInput(1), fir::getBase(exv)));
outputFuncArgs.push_back(builder.createConvert(
outputFuncArgs.push_back(builder.createConvertWithVolatileCast(
loc, outputFunc.getFunctionType().getInput(2), fir::getLen(exv)));
} else {
fir::ExtendedValue itemBox = converter.genExprValue(loc, expr, stmtCtx);
@@ -743,7 +744,8 @@ static void genOutputItemList(
outputFuncArgs.push_back(parts.first);
outputFuncArgs.push_back(parts.second);
} else {
itemValue = builder.createConvert(loc, argType, itemValue);
itemValue =
builder.createConvertWithVolatileCast(loc, argType, itemValue);
outputFuncArgs.push_back(itemValue);
}
}
@@ -827,7 +829,8 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
mlir::Value box = fir::getBase(item);
auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(box.getType());
assert(boxTy && "must be previously emboxed");
inputFuncArgs.push_back(builder.createConvert(loc, argType, box));
auto casted = builder.createConvertWithVolatileCast(loc, argType, box);
inputFuncArgs.push_back(casted);
if (containsDerivedType(boxTy))
inputFuncArgs.push_back(getNonTbpDefinedIoTableAddr(converter));
} else {

View File

@@ -577,14 +577,20 @@ mlir::Value fir::FirOpBuilder::convertWithSemantics(
return createConvert(loc, toTy, val);
}
mlir::Value fir::FirOpBuilder::createVolatileCast(mlir::Location loc,
bool isVolatile,
mlir::Value val) {
mlir::Type volatileAdjustedType =
fir::updateTypeWithVolatility(val.getType(), isVolatile);
if (volatileAdjustedType == val.getType())
return val;
return create<fir::VolatileCastOp>(loc, volatileAdjustedType, val);
}
mlir::Value fir::FirOpBuilder::createConvertWithVolatileCast(mlir::Location loc,
mlir::Type toTy,
mlir::Value val) {
if (fir::isa_volatile_type(val.getType()) != fir::isa_volatile_type(toTy)) {
mlir::Type volatileAdjustedType = fir::updateTypeWithVolatility(
val.getType(), fir::isa_volatile_type(toTy));
val = create<fir::VolatileCastOp>(loc, volatileAdjustedType, val);
}
val = createVolatileCast(loc, fir::isa_volatile_type(toTy), val);
return createConvert(loc, toTy, val);
}

View File

@@ -382,7 +382,9 @@ hlfir::Entity hlfir::genVariableBox(mlir::Location loc,
mlir::Value addr = var.getBase();
if (mlir::isa<fir::BoxCharType>(var.getType()))
addr = genVariableRawAddress(loc, builder, var);
mlir::Type boxType = fir::BoxType::get(var.getElementOrSequenceType());
const bool isVolatile = fir::isa_volatile_type(var.getType());
mlir::Type boxType =
fir::BoxType::get(var.getElementOrSequenceType(), isVolatile);
if (forceBoxType) {
boxType = forceBoxType;
mlir::Type baseType =
@@ -793,15 +795,16 @@ mlir::Type hlfir::getVariableElementType(hlfir::Entity variable) {
if (variable.isScalar())
return variable.getType();
mlir::Type eleTy = variable.getFortranElementType();
const bool isVolatile = fir::isa_volatile_type(variable.getType());
if (variable.isPolymorphic())
return fir::ClassType::get(eleTy);
return fir::ClassType::get(eleTy, isVolatile);
if (auto charType = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
if (charType.hasDynamicLen())
return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
} else if (fir::isRecordWithTypeParameters(eleTy)) {
return fir::BoxType::get(eleTy);
return fir::BoxType::get(eleTy, isVolatile);
}
return fir::ReferenceType::get(eleTy);
return fir::ReferenceType::get(eleTy, isVolatile);
}
mlir::Type hlfir::getEntityElementType(hlfir::Entity entity) {

View File

@@ -76,7 +76,9 @@ createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc,
cleanedLengths = lengths;
}
mlir::Value emptySlice;
return builder.create<fir::EmboxOp>(loc, box.getBoxTy(), cleanedAddr, shape,
auto boxType = fir::updateTypeWithVolatility(
box.getBoxTy(), fir::isa_volatile_type(cleanedAddr.getType()));
return builder.create<fir::EmboxOp>(loc, boxType, cleanedAddr, shape,
emptySlice, cleanedLengths, tdesc);
}
@@ -281,6 +283,9 @@ private:
unsigned allocator = kDefaultAllocator) {
mlir::Value irBox = createNewFirBox(builder, loc, box, addr, lbounds,
extents, lengths, tdesc);
const bool valueTypeIsVolatile =
fir::isa_volatile_type(fir::unwrapRefType(box.getAddr().getType()));
irBox = builder.createVolatileCast(loc, valueTypeIsVolatile, irBox);
builder.create<fir::StoreOp>(loc, irBox, box.getAddr());
}
@@ -346,7 +351,8 @@ mlir::Value fir::factory::createUnallocatedBox(
baseBoxType = baseBoxType.getBoxTypeWithNewShape(/*rank=*/0);
auto baseAddrType = baseBoxType.getEleTy();
if (!fir::isa_ref_type(baseAddrType))
baseAddrType = builder.getRefType(baseAddrType);
baseAddrType =
builder.getRefType(baseAddrType, fir::isa_volatile_type(baseBoxType));
auto type = fir::unwrapRefType(baseAddrType);
auto eleTy = fir::unwrapSequenceType(type);
if (auto recTy = mlir::dyn_cast<fir::RecordType>(eleTy))
@@ -516,7 +522,7 @@ void fir::factory::associateMutableBox(fir::FirOpBuilder &builder,
source.match(
[&](const fir::PolymorphicValue &p) {
mlir::Value sourceBox;
if (auto polyBox = source.getBoxOf<fir::PolymorphicValue>())
if (auto *polyBox = source.getBoxOf<fir::PolymorphicValue>())
sourceBox = polyBox->getSourceBox();
writer.updateMutableBox(p.getAddr(), /*lbounds=*/std::nullopt,
/*extents=*/std::nullopt,

View File

@@ -689,6 +689,20 @@ struct CmpcOpConversion : public fir::FIROpConversion<fir::CmpcOp> {
}
};
/// fir.volatile_cast is only useful at the fir level. Once we lower to LLVM,
/// volatility is described by setting volatile attributes on the LLVM ops.
struct VolatileCastOpConversion
: public fir::FIROpConversion<fir::VolatileCastOp> {
using FIROpConversion::FIROpConversion;
llvm::LogicalResult
matchAndRewrite(fir::VolatileCastOp volatileCast, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
rewriter.replaceOp(volatileCast, adaptor.getOperands()[0]);
return mlir::success();
}
};
/// convert value of from-type to value of to-type
struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
using FIROpConversion::FIROpConversion;
@@ -3224,6 +3238,7 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
mlir::ConversionPatternRewriter &rewriter) const override {
mlir::Type llvmLoadTy = convertObjectType(load.getType());
const bool isVolatile = fir::isa_volatile_type(load.getMemref().getType());
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(load.getType())) {
// fir.box is a special case because it is considered an ssa value in
// fir, but it is lowered as a pointer to a descriptor. So
@@ -3253,7 +3268,7 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
mlir::Value boxSize =
computeBoxSize(loc, boxTypePair, inputBoxStorage, rewriter);
auto memcpy = rewriter.create<mlir::LLVM::MemcpyOp>(
loc, newBoxStorage, inputBoxStorage, boxSize, /*isVolatile=*/false);
loc, newBoxStorage, inputBoxStorage, boxSize, isVolatile);
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
memcpy.setTBAATags(*optionalTag);
@@ -3261,8 +3276,9 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
attachTBAATag(memcpy, boxTy, boxTy, nullptr);
rewriter.replaceOp(load, newBoxStorage);
} else {
auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(
mlir::LLVM::LoadOp loadOp = rewriter.create<mlir::LLVM::LoadOp>(
load.getLoc(), llvmLoadTy, adaptor.getOperands(), load->getAttrs());
loadOp.setVolatile_(isVolatile);
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
loadOp.setTBAATags(*optionalTag);
else
@@ -3540,6 +3556,7 @@ struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> {
mlir::Value llvmValue = adaptor.getValue();
mlir::Value llvmMemref = adaptor.getMemref();
mlir::LLVM::AliasAnalysisOpInterface newOp;
const bool isVolatile = fir::isa_volatile_type(store.getMemref().getType());
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(storeTy)) {
mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct(boxTy);
// Always use memcpy because LLVM is not as effective at optimizing
@@ -3547,10 +3564,14 @@ struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> {
TypePair boxTypePair{boxTy, llvmBoxTy};
mlir::Value boxSize =
computeBoxSize(loc, boxTypePair, llvmValue, rewriter);
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(
loc, llvmMemref, llvmValue, boxSize, /*isVolatile=*/false);
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(loc, llvmMemref, llvmValue,
boxSize, isVolatile);
} else {
newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref);
mlir::LLVM::StoreOp storeOp =
rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref);
if (isVolatile)
storeOp.setVolatile_(true);
newOp = storeOp;
}
if (std::optional<mlir::ArrayAttr> optionalTag = store.getTbaa())
newOp.setTBAATags(*optionalTag);
@@ -4193,21 +4214,22 @@ void fir::populateFIRToLLVMConversionPatterns(
BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion,
BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion,
BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion,
CmpcOpConversion, ConvertOpConversion, CoordinateOpConversion,
CopyOpConversion, DTEntryOpConversion, DeclareOpConversion,
DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion,
EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion,
FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion,
GlobalOpConversion, InsertOnRangeOpConversion, IsPresentOpConversion,
LenParamIndexOpConversion, LoadOpConversion, MulcOpConversion,
NegcOpConversion, NoReassocOpConversion, SelectCaseOpConversion,
SelectOpConversion, SelectRankOpConversion, SelectTypeOpConversion,
ShapeOpConversion, ShapeShiftOpConversion, ShiftOpConversion,
SliceOpConversion, StoreOpConversion, StringLitOpConversion,
SubcOpConversion, TypeDescOpConversion, TypeInfoOpConversion,
UnboxCharOpConversion, UnboxProcOpConversion, UndefOpConversion,
UnreachableOpConversion, XArrayCoorOpConversion, XEmboxOpConversion,
XReboxOpConversion, ZeroOpConversion>(converter, options);
CmpcOpConversion, VolatileCastOpConversion, ConvertOpConversion,
CoordinateOpConversion, CopyOpConversion, DTEntryOpConversion,
DeclareOpConversion, DivcOpConversion, EmboxOpConversion,
EmboxCharOpConversion, EmboxProcOpConversion, ExtractValueOpConversion,
FieldIndexOpConversion, FirEndOpConversion, FreeMemOpConversion,
GlobalLenOpConversion, GlobalOpConversion, InsertOnRangeOpConversion,
IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion,
MulcOpConversion, NegcOpConversion, NoReassocOpConversion,
SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion,
SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion,
ShiftOpConversion, SliceOpConversion, StoreOpConversion,
StringLitOpConversion, SubcOpConversion, TypeDescOpConversion,
TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion,
UndefOpConversion, UnreachableOpConversion, XArrayCoorOpConversion,
XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(converter,
options);
// Patterns that are populated without a type converter do not trigger
// target materializations for the operands of the root op.

View File

@@ -1345,21 +1345,38 @@ mlir::ParseResult fir::CmpcOp::parse(mlir::OpAsmParser &parser,
// VolatileCastOp
//===----------------------------------------------------------------------===//
llvm::LogicalResult fir::VolatileCastOp::verify() {
mlir::Type fromType = getValue().getType();
mlir::Type toType = getType();
// Other than volatility, are the types identical?
const bool sameBaseType =
static bool typesMatchExceptForVolatility(mlir::Type fromType,
mlir::Type toType) {
// If we can change only the volatility and get identical types, then we
// match.
if (fir::updateTypeWithVolatility(fromType, fir::isa_volatile_type(toType)) ==
toType)
return true;
// Otherwise, recurse on the element types if the base classes are the same.
const bool match =
llvm::TypeSwitch<mlir::Type, bool>(fromType)
.Case<fir::BoxType, fir::ReferenceType, fir::ClassType>(
[&](auto type) {
using TYPE = decltype(type);
return mlir::isa<TYPE>(toType);
// If we are not the same base class, then we don't match.
auto castedToType = mlir::dyn_cast<TYPE>(toType);
if (!castedToType)
return false;
// If we are the same base class, we match if the element types
// match.
return typesMatchExceptForVolatility(type.getEleTy(),
castedToType.getEleTy());
})
.Default([=](mlir::Type) { return fromType == toType; });
const bool sameElementType = fir::dyn_cast_ptrOrBoxEleTy(fromType) ==
fir::dyn_cast_ptrOrBoxEleTy(toType);
if (!sameBaseType || !sameElementType)
.Default([](mlir::Type) { return false; });
return match;
}
llvm::LogicalResult fir::VolatileCastOp::verify() {
mlir::Type fromType = getValue().getType();
mlir::Type toType = getType();
if (!typesMatchExceptForVolatility(fromType, toType))
return emitOpError("types must be identical except for volatility ")
<< fromType << " / " << toType;
return mlir::success();

View File

@@ -677,8 +677,13 @@ mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
.Case<fir::SequenceType>([&](fir::SequenceType seqTy) -> mlir::Type {
return fir::SequenceType::get(seqTy.getShape(), newElementType);
})
.Case<fir::PointerType, fir::HeapType, fir::ReferenceType,
fir::ClassType>([&](auto t) -> mlir::Type {
.Case<fir::ReferenceType, fir::ClassType>([&](auto t) -> mlir::Type {
using FIRT = decltype(t);
auto newEleTy =
changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass);
return FIRT::get(newEleTy, t.isVolatile());
})
.Case<fir::PointerType, fir::HeapType>([&](auto t) -> mlir::Type {
using FIRT = decltype(t);
return FIRT::get(
changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass));
@@ -687,8 +692,8 @@ mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
mlir::Type newInnerType =
changeElementType(t.getEleTy(), newElementType, false);
if (turnBoxIntoClass)
return fir::ClassType::get(newInnerType);
return fir::BoxType::get(newInnerType);
return fir::ClassType::get(newInnerType, t.isVolatile());
return fir::BoxType::get(newInnerType, t.isVolatile());
})
.Default([&](mlir::Type t) -> mlir::Type {
assert((fir::isa_trivial(t) || llvm::isa<fir::RecordType>(t) ||

View File

@@ -195,7 +195,7 @@ mlir::Type hlfir::DeclareOp::getHLFIRVariableType(mlir::Type inputType,
bool hasDynamicLengthParams = fir::characterWithDynamicLen(eleType) ||
fir::isRecordWithTypeParameters(eleType);
if (hasExplicitLowerBounds || hasDynamicExtents || hasDynamicLengthParams)
return fir::BoxType::get(type);
return fir::BoxType::get(type, fir::isa_volatile_type(inputType));
return inputType;
}

View File

@@ -418,7 +418,9 @@ class DesignateOpConversion
firstElementIndices.push_back(indices[i]);
i = i + (isTriplet ? 3 : 1);
}
mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy);
mlir::Type originalDesignateType = designate.getResult().getType();
const bool isVolatile = fir::isa_volatile_type(originalDesignateType);
mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy, isVolatile);
base = builder.create<fir::ArrayCoorOp>(
loc, arrayCoorType, base, shape,
/*slice=*/mlir::Value{}, firstElementIndices, firBaseTypeParameters);
@@ -441,6 +443,7 @@ public:
TODO(loc, "hlfir::designate load of pointer or allocatable");
mlir::Type designateResultType = designate.getResult().getType();
const bool isVolatile = fir::isa_volatile_type(designateResultType);
llvm::SmallVector<mlir::Value> firBaseTypeParameters;
auto [base, shape] = hlfir::genVariableFirBaseShapeAndParams(
loc, builder, baseEntity, firBaseTypeParameters);
@@ -464,7 +467,7 @@ public:
mlir::Type componentType =
mlir::cast<fir::RecordType>(baseEleTy).getType(
designate.getComponent().value());
mlir::Type coorTy = fir::ReferenceType::get(componentType);
mlir::Type coorTy = fir::ReferenceType::get(componentType, isVolatile);
base = builder.create<fir::CoordinateOp>(loc, coorTy, base, fieldIndex);
if (mlir::isa<fir::BaseBoxType>(componentType)) {
auto variableInterface = mlir::cast<fir::FortranVariableOpInterface>(

View File

@@ -0,0 +1,154 @@
// RUN: fir-opt %s --bufferize-hlfir --convert-hlfir-to-fir | FileCheck %s
func.func @_QQmain() attributes {fir.bindc_name = "p"} {
%0 = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
%c10 = arith.constant 10 : index
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
%2 = fir.volatile_cast %0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%3:2 = hlfir.declare %2(%1) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%4 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
%5 = fir.volatile_cast %4 : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
%6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
%7 = fir.volatile_cast %6#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
fir.call @_QFPnot_declared_volatile_in_this_scope(%7) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
%c1 = arith.constant 1 : index
fir.do_loop %arg0 = %c1 to %c10 step %c1 {
%22 = hlfir.designate %3#0 (%arg0) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.ref<i32, volatile>
%23 = fir.volatile_cast %22 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
fir.call @_QFPnot_declared_volatile_in_this_scope(%23) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
}
%c10_i32 = arith.constant 10 : i32
%8 = fir.volatile_cast %3#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
%9 = fir.convert %8 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>>
%10:3 = hlfir.associate %c10_i32 {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
fir.call @_QFPdeclared_volatile_in_this_scope(%9, %10#0) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) -> ()
hlfir.end_associate %10#1, %10#2 : !fir.ref<i32>, i1
%c6_i32 = arith.constant 6 : i32
%11 = fir.address_of(@_QQclX28a011e93b63ba43ee03b06f1598b113) : !fir.ref<!fir.char<1,79>>
%12 = fir.convert %11 : (!fir.ref<!fir.char<1,79>>) -> !fir.ref<i8>
%c8_i32 = arith.constant 8 : i32
%13 = fir.call @_FortranAioBeginExternalListOutput(%c6_i32, %12, %c8_i32) fastmath<contract> : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8>
%14 = fir.shape %c10 : (index) -> !fir.shape<1>
%15 = fir.embox %3#0(%14) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
%16 = fir.volatile_cast %15 : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
%17 = fir.convert %16 : (!fir.box<!fir.array<10xi32>>) -> !fir.box<none>
%18 = fir.call @_FortranAioOutputDescriptor(%13, %17) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>) -> i1
%19 = fir.load %6#0 : !fir.ref<i32, volatile>
%20 = fir.call @_FortranAioOutputInteger32(%13, %19) fastmath<contract> : (!fir.ref<i8>, i32) -> i1
%21 = fir.call @_FortranAioEndIoStatement(%13) fastmath<contract> : (!fir.ref<i8>) -> i32
return
}
func.func private @_QFPnot_declared_volatile_in_this_scope(%arg0: !fir.ref<i32> {fir.bindc_name = "v"}) attributes {fir.host_symbol = @_QQmain, fir.proc_attrs = #fir.proc_attrs<elemental, pure>, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFFnot_declared_volatile_in_this_scopeEv"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %1#0 : i32, !fir.ref<i32>
return
}
func.func private @_QFPdeclared_volatile_in_this_scope(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "v"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%1:2 = hlfir.declare %arg1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFFdeclared_volatile_in_this_scopeEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
%2 = fir.load %1#0 : !fir.ref<i32>
%3 = fir.convert %2 : (i32) -> i64
%4 = fir.convert %3 : (i64) -> index
%c0 = arith.constant 0 : index
%5 = arith.cmpi sgt, %4, %c0 : index
%6 = arith.select %5, %4, %c0 : index
%7 = fir.shape %6 : (index) -> !fir.shape<1>
%8 = fir.volatile_cast %arg0 : (!fir.ref<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>, volatile>
%9:2 = hlfir.declare %8(%7) dummy_scope %0 {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFdeclared_volatile_in_this_scopeEv"} : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.ref<!fir.array<?xi32>, volatile>)
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %9#0 : i32, !fir.box<!fir.array<?xi32>, volatile>
return
}
fir.global internal @_QFEarr : !fir.array<10xi32> {
%0 = fir.zero_bits !fir.array<10xi32>
fir.has_value %0 : !fir.array<10xi32>
}
// CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} {
// CHECK: %[[VAL_0:.*]] = fir.alloca i32 {adapt.valuebyref}
// CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
// CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_9:.*]] = fir.volatile_cast %[[VAL_8]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
// CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_9]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
// CHECK: %[[VAL_10:.*]] = arith.constant 1 : index
// CHECK: fir.do_loop %[[VAL_11:.*]] = %[[VAL_10]] to %[[VAL_2]] step %[[VAL_10]] {
// CHECK: %[[VAL_12:.*]] = fir.array_coor %[[VAL_5]](%[[VAL_3]]) %[[VAL_11]] : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, index) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
// CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_13]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
// CHECK: }
// CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32
// CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>>
// CHECK: fir.store %[[VAL_14]] to %[[VAL_0]] : !fir.ref<i32>
// CHECK: %[[VAL_17:.*]] = arith.constant false
// CHECK: fir.call @_QFPdeclared_volatile_in_this_scope(%[[VAL_16]], %[[VAL_0]]) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) -> ()
// CHECK: %[[VAL_18:.*]] = arith.constant 6 : i32
// CHECK: %[[VAL_19:.*]] = fir.address_of
// CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (
// CHECK: %[[VAL_21:.*]] = arith.constant 8 : i32
// CHECK: %[[VAL_22:.*]] = fir.call @_FortranAioBeginExternalListOutput(%[[VAL_18]], %[[VAL_20]], %[[VAL_21]]) fastmath<contract> : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8>
// CHECK: %[[VAL_23:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_5]](%[[VAL_23]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_25:.*]] = fir.volatile_cast %[[VAL_24]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
// CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<none>
// CHECK: %[[VAL_27:.*]] = fir.call @_FortranAioOutputDescriptor(%[[VAL_22]], %[[VAL_26]]) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>) -> i1
// CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_8]] : !fir.ref<i32, volatile>
// CHECK: %[[VAL_29:.*]] = fir.call @_FortranAioOutputInteger32(%[[VAL_22]], %[[VAL_28]]) fastmath<contract> : (!fir.ref<i8>, i32) -> i1
// CHECK: %[[VAL_30:.*]] = fir.call @_FortranAioEndIoStatement(%[[VAL_22]]) fastmath<contract> : (!fir.ref<i8>) -> i32
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPnot_declared_volatile_in_this_scope(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "v"}) attributes {fir.host_symbol = @_QQmain, fir.proc_attrs = #fir.proc_attrs<elemental, pure>, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFFnot_declared_volatile_in_this_scopeEv"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
// CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32
// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref<i32>
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPdeclared_volatile_in_this_scope(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "v"},
// CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "n"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?xi32>, volatile>
// CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_4:.*]] = fir.declare %[[VAL_1]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFFdeclared_volatile_in_this_scopeEn"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref<i32>
// CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64
// CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> index
// CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
// CHECK: %[[VAL_9:.*]] = arith.cmpi sgt, %[[VAL_7]], %[[VAL_8]] : index
// CHECK: %[[VAL_10:.*]] = arith.select %[[VAL_9]], %[[VAL_7]], %[[VAL_8]] : index
// CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_12:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>, volatile>
// CHECK: %[[VAL_13:.*]] = fir.declare %[[VAL_12]](%[[VAL_11]]) dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFdeclared_volatile_in_this_scopeEv"} : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<?xi32>, volatile>
// CHECK: %[[VAL_14:.*]] = fir.embox %[[VAL_13]](%[[VAL_11]]) : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>, volatile>
// CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32
// CHECK: %[[VAL_16:.*]] = fir.alloca i32
// CHECK: fir.store %[[VAL_15]] to %[[VAL_16]] : !fir.ref<i32>
// CHECK: %[[VAL_17:.*]] = fir.embox %[[VAL_16]] : (!fir.ref<i32>) -> !fir.box<i32>
// CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_13]](%[[VAL_18]]) : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>, volatile>
// CHECK: fir.store %[[VAL_19]] to %[[VAL_2]] : !fir.ref<!fir.box<!fir.array<?xi32>, volatile>>
// CHECK: %[[VAL_20:.*]] = fir.address_of(
// CHECK: %[[VAL_21:.*]] = arith.constant
// CHECK: %[[VAL_22:.*]] = arith.constant
// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.box<!fir.array<?xi32>, volatile>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_17]] : (!fir.box<i32>) -> !fir.box<none>
// CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_20]] : (
// CHECK: fir.call @_FortranAAssign(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_22]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
// CHECK: return
// CHECK: }
// CHECK-LABEL: fir.global internal @_QFEarr : !fir.array<10xi32> {
// CHECK: %[[VAL_0:.*]] = fir.zero_bits !fir.array<10xi32>
// CHECK: fir.has_value %[[VAL_0]] : !fir.array<10xi32>
// CHECK: }
// CHECK: func.func private @_FortranAAssign(!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) attributes {fir.runtime}

View File

@@ -0,0 +1,66 @@
// RUN: fir-opt %s --bufferize-hlfir --convert-hlfir-to-fir | FileCheck %s
func.func private @_QFPa() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFFaEa"}
%1 = fir.volatile_cast %0 : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
%2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFaEa"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %2#0 : i32, !fir.ref<i32, volatile>
%3 = fir.volatile_cast %2#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
%4 = fir.load %3 : !fir.ref<i32>
return %4 : i32
}
func.func private @_QFPb() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFFbEr"}
%1 = fir.volatile_cast %0 : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
%2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFbEr"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
%c2_i32 = arith.constant 2 : i32
hlfir.assign %c2_i32 to %2#0 : i32, !fir.ref<i32, volatile>
%3 = fir.volatile_cast %2#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
%4 = fir.load %3 : !fir.ref<i32>
return %4 : i32
}
func.func private @_QFPc() -> f32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFFcEr"}
%1 = fir.volatile_cast %0 : (!fir.ref<f32>) -> !fir.ref<f32, volatile>
%2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFcEr"} : (!fir.ref<f32, volatile>) -> (!fir.ref<f32, volatile>, !fir.ref<f32, volatile>)
%cst = arith.constant 3.000000e+00 : f32
hlfir.assign %cst to %2#0 : f32, !fir.ref<f32, volatile>
%3 = fir.volatile_cast %2#0 : (!fir.ref<f32, volatile>) -> !fir.ref<f32>
%4 = fir.load %3 : !fir.ref<f32>
return %4 : f32
}
// CHECK-LABEL: func.func private @_QFPa() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFFaEa"}
// CHECK: %[[VAL_1:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFaEa"} : (!fir.ref<i32, volatile>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32
// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref<i32, volatile>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref<i32>
// CHECK: return %[[VAL_5]] : i32
// CHECK: }
// CHECK-LABEL: func.func private @_QFPb() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFFbEr"}
// CHECK: %[[VAL_1:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFbEr"} : (!fir.ref<i32, volatile>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_3:.*]] = arith.constant 2 : i32
// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref<i32, volatile>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref<i32>
// CHECK: return %[[VAL_5]] : i32
// CHECK: }
// CHECK-LABEL: func.func private @_QFPc() -> f32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_0:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFFcEr"}
// CHECK: %[[VAL_1:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<f32>) -> !fir.ref<f32, volatile>
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFcEr"} : (!fir.ref<f32, volatile>) -> !fir.ref<f32, volatile>
// CHECK: %[[VAL_3:.*]] = arith.constant 3.000000e+00 : f32
// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref<f32, volatile>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref<f32, volatile>) -> !fir.ref<f32>
// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref<f32>
// CHECK: return %[[VAL_5]] : f32
// CHECK: }

View File

@@ -0,0 +1,150 @@
// RUN: fir-opt %s --bufferize-hlfir --convert-hlfir-to-fir | FileCheck %s
func.func @_QQmain() attributes {fir.bindc_name = "p"} {
%0 = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
%c10 = arith.constant 10 : index
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
%2 = fir.volatile_cast %0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%3:2 = hlfir.declare %2(%1) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%4 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
%5 = fir.volatile_cast %4 : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
%6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
%7 = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
%8 = fir.volatile_cast %7 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%9:2 = hlfir.declare %8 {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>)
%10 = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
%c10_0 = arith.constant 10 : index
%11 = fir.shape %c10_0 : (index) -> !fir.shape<1>
%12 = fir.volatile_cast %10 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%13:2 = hlfir.declare %12(%11) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%14 = fir.shape %c10_0 : (index) -> !fir.shape<1>
%15 = fir.embox %13#0(%14) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
fir.store %15 to %9#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%c0_i32 = arith.constant 0 : i32
hlfir.assign %c0_i32 to %6#0 : i32, !fir.ref<i32, volatile>
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %3#0 : i32, !fir.ref<!fir.array<10xi32>, volatile>
%16 = fir.volatile_cast %3#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
fir.call @_QFPd(%16) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
%17 = fir.embox %3#0(%1) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
%18 = fir.volatile_cast %17 : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
%19 = fir.convert %18 : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>>
fir.call @_QFPe(%19) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> ()
%20 = fir.volatile_cast %3#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
fir.call @_QFPf(%20) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
%21 = fir.convert %9#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>
fir.call @_QFPg(%21) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> ()
return
}
func.func private @_QFPd(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%c10 = arith.constant 10 : index
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
%2 = fir.volatile_cast %arg0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%3:2 = hlfir.declare %2(%1) dummy_scope %0 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFdEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
return
}
func.func private @_QFPe(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFeEarr"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
return
}
func.func private @_QFPf(%arg0: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%c10 = arith.constant 10 : index
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
%2 = fir.volatile_cast %arg0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%3:2 = hlfir.declare %2(%1) dummy_scope %0 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFfEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
return
}
func.func private @_QFPg(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%1 = fir.volatile_cast %arg0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%2:2 = hlfir.declare %1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFFgEarr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>)
return
}
// CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} {
// CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
// CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_9:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
// CHECK: %[[VAL_10:.*]] = fir.volatile_cast %[[VAL_9]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_11:.*]] = fir.declare %[[VAL_10]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_13:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_14:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_16:.*]] = fir.declare %[[VAL_15]](%[[VAL_14]]) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_16]](%[[VAL_17]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
// CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_19:.*]] = arith.constant 0 : i32
// CHECK: fir.store %[[VAL_19]] to %[[VAL_8]] : !fir.ref<i32, volatile>
// CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32
// CHECK: %[[VAL_21:.*]] = fir.alloca i32
// CHECK: fir.store %[[VAL_20]] to %[[VAL_21]] : !fir.ref<i32>
// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_21]] : (!fir.ref<i32>) -> !fir.box<i32>
// CHECK: %[[VAL_23:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_5]](%[[VAL_23]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
// CHECK: fir.store %[[VAL_24]] to %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<10xi32>, volatile>>
// CHECK: %[[VAL_25:.*]] = fir.address_of
// CHECK: %[[VAL_26:.*]] = arith.constant
// CHECK: %[[VAL_27:.*]] = arith.constant
// CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.box<!fir.array<10xi32>, volatile>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_22]] : (!fir.box<i32>) -> !fir.box<none>
// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_25]]
// CHECK: fir.call @_FortranAAssign(%[[VAL_28]], %[[VAL_29]], %[[VAL_30]], %[[VAL_27]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
// CHECK: %[[VAL_31:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
// CHECK: fir.call @_QFPd(%[[VAL_31]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
// CHECK: %[[VAL_32:.*]] = fir.embox %[[VAL_5]](%[[VAL_3]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_33:.*]] = fir.volatile_cast %[[VAL_32]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
// CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>>
// CHECK: fir.call @_QFPe(%[[VAL_34]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> ()
// CHECK: %[[VAL_35:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
// CHECK: fir.call @_QFPf(%[[VAL_35]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
// CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_11]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>
// CHECK: fir.call @_QFPg(%[[VAL_36]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> ()
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPd(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFdEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPe(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFeEarr"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> !fir.box<!fir.array<?xi32>>
// CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>>
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPf(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFfEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPg(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_2:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_2]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFFgEarr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.dscope) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: return
// CHECK: }

View File

@@ -0,0 +1,153 @@
// RUN: fir-opt %s --bufferize-hlfir --convert-hlfir-to-fir | FileCheck %s
func.func @_QQmain() attributes {fir.bindc_name = "p"} {
%0 = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
%c10 = arith.constant 10 : index
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
%2 = fir.volatile_cast %0 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%3:2 = hlfir.declare %2(%1) {fortran_attrs = #fir.var_attrs<volatile, internal_assoc>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%4 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
%5 = fir.volatile_cast %4 : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
%6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs<volatile, internal_assoc>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
%7 = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
%8 = fir.volatile_cast %7 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%9:2 = hlfir.declare %8 {fortran_attrs = #fir.var_attrs<pointer, volatile, internal_assoc>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>)
%10 = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
%c10_0 = arith.constant 10 : index
%11 = fir.shape %c10_0 : (index) -> !fir.shape<1>
%12 = fir.volatile_cast %10 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%13:2 = hlfir.declare %12(%11) {fortran_attrs = #fir.var_attrs<target, volatile, internal_assoc>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%14 = fir.alloca tuple<!fir.ref<i32>>
%c0_i32 = arith.constant 0 : i32
%15 = fir.coordinate_of %14, %c0_i32 : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>>
%16 = fir.volatile_cast %6#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
fir.store %16 to %15 : !fir.llvm_ptr<!fir.ref<i32>>
%17 = fir.shape %c10_0 : (index) -> !fir.shape<1>
%18 = fir.embox %13#0(%17) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
fir.store %18 to %9#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%c0_i32_1 = arith.constant 0 : i32
hlfir.assign %c0_i32_1 to %6#0 : i32, !fir.ref<i32, volatile>
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %3#0 : i32, !fir.ref<!fir.array<10xi32>, volatile>
fir.call @_QFPhost_assoc(%14) fastmath<contract> : (!fir.ref<tuple<!fir.ref<i32>>>) -> ()
return
}
func.func private @_QFPhost_assoc(%arg0: !fir.ref<tuple<!fir.ref<i32>>> {fir.host_assoc}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.dummy_scope : !fir.dscope
%1 = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
%c10 = arith.constant 10 : index
%2 = fir.shape %c10 : (index) -> !fir.shape<1>
%3 = fir.volatile_cast %1 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%4:2 = hlfir.declare %3(%2) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%5 = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
%6 = fir.volatile_cast %5 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%7:2 = hlfir.declare %6 {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>)
%8 = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
%c10_0 = arith.constant 10 : index
%9 = fir.shape %c10_0 : (index) -> !fir.shape<1>
%10 = fir.volatile_cast %8 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
%11:2 = hlfir.declare %10(%9) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
%c0_i32 = arith.constant 0 : i32
%12 = fir.coordinate_of %arg0, %c0_i32 : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>>
%13 = fir.load %12 : !fir.llvm_ptr<!fir.ref<i32>>
%14 = fir.volatile_cast %13 : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
%15:2 = hlfir.declare %14 {fortran_attrs = #fir.var_attrs<volatile, host_assoc>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
%16 = fir.shape %c10_0 : (index) -> !fir.shape<1>
%17 = fir.embox %11#0(%16) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
fir.store %17 to %7#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
%c0_i32_1 = arith.constant 0 : i32
hlfir.assign %c0_i32_1 to %15#0 : i32, !fir.ref<i32, volatile>
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %4#0 : i32, !fir.ref<!fir.array<10xi32>, volatile>
return
}
// CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} {
// CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs<volatile, internal_assoc>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
// CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {fortran_attrs = #fir.var_attrs<volatile, internal_assoc>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_9:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
// CHECK: %[[VAL_10:.*]] = fir.volatile_cast %[[VAL_9]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_11:.*]] = fir.declare %[[VAL_10]] {fortran_attrs = #fir.var_attrs<pointer, volatile, internal_assoc>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_13:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_14:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_16:.*]] = fir.declare %[[VAL_15]](%[[VAL_14]]) {fortran_attrs = #fir.var_attrs<target, volatile, internal_assoc>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_17:.*]] = fir.alloca tuple<!fir.ref<i32>>
// CHECK: %[[VAL_18:.*]] = arith.constant 0 : i32
// CHECK: %[[VAL_19:.*]] = fir.coordinate_of %[[VAL_17]], %[[VAL_18]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>>
// CHECK: %[[VAL_20:.*]] = fir.volatile_cast %[[VAL_8]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
// CHECK: fir.store %[[VAL_20]] to %[[VAL_19]] : !fir.llvm_ptr<!fir.ref<i32>>
// CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_16]](%[[VAL_21]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
// CHECK: fir.store %[[VAL_22]] to %[[VAL_11]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_23:.*]] = arith.constant 0 : i32
// CHECK: fir.store %[[VAL_23]] to %[[VAL_8]] : !fir.ref<i32, volatile>
// CHECK: %[[VAL_24:.*]] = arith.constant 1 : i32
// CHECK: %[[VAL_25:.*]] = fir.alloca i32
// CHECK: fir.store %[[VAL_24]] to %[[VAL_25]] : !fir.ref<i32>
// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]] : (!fir.ref<i32>) -> !fir.box<i32>
// CHECK: %[[VAL_27:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_5]](%[[VAL_27]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
// CHECK: fir.store %[[VAL_28]] to %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<10xi32>, volatile>>
// CHECK: %[[VAL_29:.*]] = fir.address_of
// CHECK: %[[VAL_30:.*]] = arith.constant
// CHECK: %[[VAL_31:.*]] = arith.constant
// CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.box<!fir.array<10xi32>, volatile>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_26]] : (!fir.box<i32>) -> !fir.box<none>
// CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_29]]
// CHECK: fir.call @_FortranAAssign(%[[VAL_32]], %[[VAL_33]], %[[VAL_34]], %[[VAL_31]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
// CHECK: fir.call @_QFPhost_assoc(%[[VAL_17]]) fastmath<contract> : (!fir.ref<tuple<!fir.ref<i32>>>) -> ()
// CHECK: return
// CHECK: }
// CHECK-LABEL: func.func private @_QFPhost_assoc(
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<tuple<!fir.ref<i32>>> {fir.host_assoc}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
// CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_3:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_4:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_3]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_7:.*]] = fir.declare %[[VAL_6]](%[[VAL_5]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_8:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
// CHECK: %[[VAL_9:.*]] = fir.volatile_cast %[[VAL_8]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_10:.*]] = fir.declare %[[VAL_9]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEptr"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_11:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
// CHECK: %[[VAL_12:.*]] = arith.constant 10 : index
// CHECK: %[[VAL_13:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_14:.*]] = fir.volatile_cast %[[VAL_11]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_15:.*]] = fir.declare %[[VAL_14]](%[[VAL_13]]) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEtgt"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
// CHECK: %[[VAL_16:.*]] = arith.constant 0 : i32
// CHECK: %[[VAL_17:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_16]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>>
// CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.llvm_ptr<!fir.ref<i32>>
// CHECK: %[[VAL_19:.*]] = fir.volatile_cast %[[VAL_18]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_20:.*]] = fir.declare %[[VAL_19]] {fortran_attrs = #fir.var_attrs<volatile, host_assoc>, uniq_name = "_QFEi"} : (!fir.ref<i32, volatile>) -> !fir.ref<i32, volatile>
// CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_15]](%[[VAL_21]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
// CHECK: fir.store %[[VAL_22]] to %[[VAL_10]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
// CHECK: %[[VAL_23:.*]] = arith.constant 0 : i32
// CHECK: fir.store %[[VAL_23]] to %[[VAL_20]] : !fir.ref<i32, volatile>
// CHECK: %[[VAL_24:.*]] = arith.constant 1 : i32
// CHECK: %[[VAL_25:.*]] = fir.alloca i32
// CHECK: fir.store %[[VAL_24]] to %[[VAL_25]] : !fir.ref<i32>
// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]] : (!fir.ref<i32>) -> !fir.box<i32>
// CHECK: %[[VAL_27:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_7]](%[[VAL_27]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
// CHECK: fir.store %[[VAL_28]] to %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<10xi32>, volatile>>
// CHECK: %[[VAL_29:.*]] = fir.address_of
// CHECK: %[[VAL_30:.*]] = arith.constant
// CHECK: %[[VAL_31:.*]] = arith.constant
// CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_1]] : (!fir.ref<!fir.box<!fir.array<10xi32>, volatile>>) -> !fir.ref<!fir.box<none>>
// CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_26]] : (!fir.box<i32>) -> !fir.box<none>
// CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_29]]
// CHECK: fir.call @_FortranAAssign(%[[VAL_32]], %[[VAL_33]], %[[VAL_34]], %[[VAL_31]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
// CHECK: return
// CHECK: }
// CHECK: func.func private @_FortranAAssign(!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) attributes {fir.runtime}