diff --git a/flang/include/flang/Optimizer/Builder/BoxValue.h b/flang/include/flang/Optimizer/Builder/BoxValue.h index 5f9834bfb8ec9..432a42264f7fc 100644 --- a/flang/include/flang/Optimizer/Builder/BoxValue.h +++ b/flang/include/flang/Optimizer/Builder/BoxValue.h @@ -236,7 +236,7 @@ class AbstractIrBox : public AbstractBox, public AbstractArrayBox { 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 diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index 8fca4272636b1..5309ea2c0fc09 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -402,6 +402,10 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener { 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, diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index d674775ffb522..31f2650917781 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -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, diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 8f5d799ea4c57..5a4521140045c 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -212,19 +212,25 @@ class HlfirDesignatorBuilder { auto charType = mlir::dyn_cast(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(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 @@ -1824,7 +1830,10 @@ class HlfirBuilder { 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 typeParams; diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index 0f75a8a7c312e..ab6e76902b466 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -194,8 +194,8 @@ class CapturedProcedure : public CapturedSymbols { 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(args.loc, castBox, args.addrInTuple); } @@ -265,8 +265,8 @@ class CapturedPolymorphicScalar 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(loc, builder.getI1Type(), castBox); @@ -329,8 +329,8 @@ class CapturedAllocatableAndPointer 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(args.loc, castBox, args.addrInTuple); } static void getFromTuple(const GetFromTuple &args, diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 13d612354da84..d98f669496d6c 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -720,7 +720,8 @@ static void genOutputItemList( fir::factory::CharacterExprHelper helper{builder, loc}; if (mlir::isa(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(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 { diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index cfacb4b47854f..3cf9b5ae72d9e 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -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(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(loc, volatileAdjustedType, val); - } + val = createVolatileCast(loc, fir::isa_volatile_type(toTy), val); return createConvert(loc, toTy, val); } diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 06a3e177da1d0..558ebcb876ddb 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -382,7 +382,9 @@ hlfir::Entity hlfir::genVariableBox(mlir::Location loc, mlir::Value addr = var.getBase(); if (mlir::isa(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(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) { diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp index aeb737acbf567..e6d630412ec34 100644 --- a/flang/lib/Optimizer/Builder/MutableBox.cpp +++ b/flang/lib/Optimizer/Builder/MutableBox.cpp @@ -76,7 +76,9 @@ createNewFirBox(fir::FirOpBuilder &builder, mlir::Location loc, cleanedLengths = lengths; } mlir::Value emptySlice; - return builder.create(loc, box.getBoxTy(), cleanedAddr, shape, + auto boxType = fir::updateTypeWithVolatility( + box.getBoxTy(), fir::isa_volatile_type(cleanedAddr.getType())); + return builder.create(loc, boxType, cleanedAddr, shape, emptySlice, cleanedLengths, tdesc); } @@ -281,6 +283,9 @@ class MutablePropertyWriter { 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(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(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()) + if (auto *polyBox = source.getBoxOf()) sourceBox = polyBox->getSourceBox(); writer.updateMutableBox(p.getAddr(), /*lbounds=*/std::nullopt, /*extents=*/std::nullopt, diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 907cac2bcaf65..5c6ea7294682f 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -689,6 +689,20 @@ struct CmpcOpConversion : public fir::FIROpConversion { } }; +/// 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 { + 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 { using FIROpConversion::FIROpConversion; @@ -3224,6 +3238,7 @@ struct LoadOpConversion : public fir::FIROpConversion { 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(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 { mlir::Value boxSize = computeBoxSize(loc, boxTypePair, inputBoxStorage, rewriter); auto memcpy = rewriter.create( - loc, newBoxStorage, inputBoxStorage, boxSize, /*isVolatile=*/false); + loc, newBoxStorage, inputBoxStorage, boxSize, isVolatile); if (std::optional optionalTag = load.getTbaa()) memcpy.setTBAATags(*optionalTag); @@ -3261,8 +3276,9 @@ struct LoadOpConversion : public fir::FIROpConversion { attachTBAATag(memcpy, boxTy, boxTy, nullptr); rewriter.replaceOp(load, newBoxStorage); } else { - auto loadOp = rewriter.create( + mlir::LLVM::LoadOp loadOp = rewriter.create( load.getLoc(), llvmLoadTy, adaptor.getOperands(), load->getAttrs()); + loadOp.setVolatile_(isVolatile); if (std::optional optionalTag = load.getTbaa()) loadOp.setTBAATags(*optionalTag); else @@ -3540,6 +3556,7 @@ struct StoreOpConversion : public fir::FIROpConversion { 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(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 { TypePair boxTypePair{boxTy, llvmBoxTy}; mlir::Value boxSize = computeBoxSize(loc, boxTypePair, llvmValue, rewriter); - newOp = rewriter.create( - loc, llvmMemref, llvmValue, boxSize, /*isVolatile=*/false); + newOp = rewriter.create(loc, llvmMemref, llvmValue, + boxSize, isVolatile); } else { - newOp = rewriter.create(loc, llvmValue, llvmMemref); + mlir::LLVM::StoreOp storeOp = + rewriter.create(loc, llvmValue, llvmMemref); + if (isVolatile) + storeOp.setVolatile_(true); + newOp = storeOp; } if (std::optional 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. diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 5eaf6b7fc240d..21cedb1030896 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -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(fromType) .Case( [&](auto type) { using TYPE = decltype(type); - return mlir::isa(toType); + // If we are not the same base class, then we don't match. + auto castedToType = mlir::dyn_cast(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(); diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp index 1df0ea93b759f..4d40c2618a0d0 100644 --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -677,8 +677,13 @@ mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType, .Case([&](fir::SequenceType seqTy) -> mlir::Type { return fir::SequenceType::get(seqTy.getShape(), newElementType); }) - .Case([&](auto t) -> mlir::Type { + .Case([&](auto t) -> mlir::Type { + using FIRT = decltype(t); + auto newEleTy = + changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass); + return FIRT::get(newEleTy, t.isVolatile()); + }) + .Case([&](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(t) || diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 8851a3a7187b9..79e7ba8459c25 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -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; } diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp index 496a5560ac615..c5bd8b30d5214 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -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( loc, arrayCoorType, base, shape, /*slice=*/mlir::Value{}, firstElementIndices, firBaseTypeParameters); @@ -441,6 +443,7 @@ class DesignateOpConversion 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 firBaseTypeParameters; auto [base, shape] = hlfir::genVariableFirBaseShapeAndParams( loc, builder, baseEntity, firBaseTypeParameters); @@ -464,7 +467,7 @@ class DesignateOpConversion mlir::Type componentType = mlir::cast(baseEleTy).getType( designate.getComponent().value()); - mlir::Type coorTy = fir::ReferenceType::get(componentType); + mlir::Type coorTy = fir::ReferenceType::get(componentType, isVolatile); base = builder.create(loc, coorTy, base, fieldIndex); if (mlir::isa(componentType)) { auto variableInterface = mlir::cast( diff --git a/flang/test/HLFIR/volatile1.fir b/flang/test/HLFIR/volatile1.fir new file mode 100644 index 0000000000000..174acd77f9076 --- /dev/null +++ b/flang/test/HLFIR/volatile1.fir @@ -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> + %c10 = arith.constant 10 : index + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2 = fir.volatile_cast %0 : (!fir.ref>) -> !fir.ref, volatile> + %3:2 = hlfir.declare %2(%1) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %4 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %5 = fir.volatile_cast %4 : (!fir.ref) -> !fir.ref + %6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %7 = fir.volatile_cast %6#0 : (!fir.ref) -> !fir.ref + fir.call @_QFPnot_declared_volatile_in_this_scope(%7) proc_attrs fastmath : (!fir.ref) -> () + %c1 = arith.constant 1 : index + fir.do_loop %arg0 = %c1 to %c10 step %c1 { + %22 = hlfir.designate %3#0 (%arg0) : (!fir.ref, volatile>, index) -> !fir.ref + %23 = fir.volatile_cast %22 : (!fir.ref) -> !fir.ref + fir.call @_QFPnot_declared_volatile_in_this_scope(%23) proc_attrs fastmath : (!fir.ref) -> () + } + %c10_i32 = arith.constant 10 : i32 + %8 = fir.volatile_cast %3#0 : (!fir.ref, volatile>) -> !fir.ref> + %9 = fir.convert %8 : (!fir.ref>) -> !fir.ref> + %10:3 = hlfir.associate %c10_i32 {adapt.valuebyref} : (i32) -> (!fir.ref, !fir.ref, i1) + fir.call @_QFPdeclared_volatile_in_this_scope(%9, %10#0) fastmath : (!fir.ref>, !fir.ref) -> () + hlfir.end_associate %10#1, %10#2 : !fir.ref, i1 + %c6_i32 = arith.constant 6 : i32 + %11 = fir.address_of(@_QQclX28a011e93b63ba43ee03b06f1598b113) : !fir.ref> + %12 = fir.convert %11 : (!fir.ref>) -> !fir.ref + %c8_i32 = arith.constant 8 : i32 + %13 = fir.call @_FortranAioBeginExternalListOutput(%c6_i32, %12, %c8_i32) fastmath : (i32, !fir.ref, i32) -> !fir.ref + %14 = fir.shape %c10 : (index) -> !fir.shape<1> + %15 = fir.embox %3#0(%14) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> + %16 = fir.volatile_cast %15 : (!fir.box, volatile>) -> !fir.box> + %17 = fir.convert %16 : (!fir.box>) -> !fir.box + %18 = fir.call @_FortranAioOutputDescriptor(%13, %17) fastmath : (!fir.ref, !fir.box) -> i1 + %19 = fir.load %6#0 : !fir.ref + %20 = fir.call @_FortranAioOutputInteger32(%13, %19) fastmath : (!fir.ref, i32) -> i1 + %21 = fir.call @_FortranAioEndIoStatement(%13) fastmath : (!fir.ref) -> i32 + return +} +func.func private @_QFPnot_declared_volatile_in_this_scope(%arg0: !fir.ref {fir.bindc_name = "v"}) attributes {fir.host_symbol = @_QQmain, fir.proc_attrs = #fir.proc_attrs, llvm.linkage = #llvm.linkage} { + %0 = fir.dummy_scope : !fir.dscope + %1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFnot_declared_volatile_in_this_scopeEv"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) + %c1_i32 = arith.constant 1 : i32 + hlfir.assign %c1_i32 to %1#0 : i32, !fir.ref + return +} +func.func private @_QFPdeclared_volatile_in_this_scope(%arg0: !fir.ref> {fir.bindc_name = "v"}, %arg1: !fir.ref {fir.bindc_name = "n"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %0 = fir.dummy_scope : !fir.dscope + %1:2 = hlfir.declare %arg1 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFdeclared_volatile_in_this_scopeEn"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) + %2 = fir.load %1#0 : !fir.ref + %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.ref, volatile> + %9:2 = hlfir.declare %8(%7) dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFdeclared_volatile_in_this_scopeEv"} : (!fir.ref, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.box, volatile>, !fir.ref, volatile>) + %c1_i32 = arith.constant 1 : i32 + hlfir.assign %c1_i32 to %9#0 : i32, !fir.box, 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> +// 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.ref, volatile> +// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +// CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_9:.*]] = fir.volatile_cast %[[VAL_8]] : (!fir.ref) -> !fir.ref +// CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_9]]) proc_attrs fastmath : (!fir.ref) -> () +// 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, volatile>, !fir.shape<1>, index) -> !fir.ref +// CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref) -> !fir.ref +// CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_13]]) proc_attrs fastmath : (!fir.ref) -> () +// CHECK: } +// CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 +// CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref, volatile>) -> !fir.ref> +// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (!fir.ref>) -> !fir.ref> +// CHECK: fir.store %[[VAL_14]] to %[[VAL_0]] : !fir.ref +// CHECK: %[[VAL_17:.*]] = arith.constant false +// CHECK: fir.call @_QFPdeclared_volatile_in_this_scope(%[[VAL_16]], %[[VAL_0]]) fastmath : (!fir.ref>, !fir.ref) -> () +// 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 : (i32, !fir.ref, i32) -> !fir.ref +// CHECK: %[[VAL_23:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_5]](%[[VAL_23]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: %[[VAL_25:.*]] = fir.volatile_cast %[[VAL_24]] : (!fir.box, volatile>) -> !fir.box> +// CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (!fir.box>) -> !fir.box +// CHECK: %[[VAL_27:.*]] = fir.call @_FortranAioOutputDescriptor(%[[VAL_22]], %[[VAL_26]]) fastmath : (!fir.ref, !fir.box) -> i1 +// CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_8]] : !fir.ref +// CHECK: %[[VAL_29:.*]] = fir.call @_FortranAioOutputInteger32(%[[VAL_22]], %[[VAL_28]]) fastmath : (!fir.ref, i32) -> i1 +// CHECK: %[[VAL_30:.*]] = fir.call @_FortranAioEndIoStatement(%[[VAL_22]]) fastmath : (!fir.ref) -> 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 {fir.bindc_name = "v"}) attributes {fir.host_symbol = @_QQmain, fir.proc_attrs = #fir.proc_attrs, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope +// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFnot_declared_volatile_in_this_scopeEv"} : (!fir.ref, !fir.dscope) -> !fir.ref +// CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32 +// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref +// 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.bindc_name = "v"}, +// CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref {fir.bindc_name = "n"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box, 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, uniq_name = "_QFFdeclared_volatile_in_this_scopeEn"} : (!fir.ref, !fir.dscope) -> !fir.ref +// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref +// 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.ref, volatile> +// CHECK: %[[VAL_13:.*]] = fir.declare %[[VAL_12]](%[[VAL_11]]) dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFdeclared_volatile_in_this_scopeEv"} : (!fir.ref, volatile>, !fir.shape<1>, !fir.dscope) -> !fir.ref, volatile> +// CHECK: %[[VAL_14:.*]] = fir.embox %[[VAL_13]](%[[VAL_11]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_16:.*]] = fir.alloca i32 +// CHECK: fir.store %[[VAL_15]] to %[[VAL_16]] : !fir.ref +// CHECK: %[[VAL_17:.*]] = fir.embox %[[VAL_16]] : (!fir.ref) -> !fir.box +// CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_13]](%[[VAL_18]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: fir.store %[[VAL_19]] to %[[VAL_2]] : !fir.ref, 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, volatile>>) -> !fir.ref> +// CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_17]] : (!fir.box) -> !fir.box +// CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_20]] : ( +// CHECK: fir.call @_FortranAAssign(%[[VAL_23]], %[[VAL_24]], %[[VAL_25]], %[[VAL_22]]) : (!fir.ref>, !fir.box, !fir.ref, 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, !fir.ref, i32) attributes {fir.runtime} diff --git a/flang/test/HLFIR/volatile2.fir b/flang/test/HLFIR/volatile2.fir new file mode 100644 index 0000000000000..86ac683adad3f --- /dev/null +++ b/flang/test/HLFIR/volatile2.fir @@ -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} { + %0 = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFFaEa"} + %1 = fir.volatile_cast %0 : (!fir.ref) -> !fir.ref + %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFaEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c1_i32 = arith.constant 1 : i32 + hlfir.assign %c1_i32 to %2#0 : i32, !fir.ref + %3 = fir.volatile_cast %2#0 : (!fir.ref) -> !fir.ref + %4 = fir.load %3 : !fir.ref + return %4 : i32 +} +func.func private @_QFPb() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %0 = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFFbEr"} + %1 = fir.volatile_cast %0 : (!fir.ref) -> !fir.ref + %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFbEr"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c2_i32 = arith.constant 2 : i32 + hlfir.assign %c2_i32 to %2#0 : i32, !fir.ref + %3 = fir.volatile_cast %2#0 : (!fir.ref) -> !fir.ref + %4 = fir.load %3 : !fir.ref + return %4 : i32 +} +func.func private @_QFPc() -> f32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %0 = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFFcEr"} + %1 = fir.volatile_cast %0 : (!fir.ref) -> !fir.ref + %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFcEr"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %cst = arith.constant 3.000000e+00 : f32 + hlfir.assign %cst to %2#0 : f32, !fir.ref + %3 = fir.volatile_cast %2#0 : (!fir.ref) -> !fir.ref + %4 = fir.load %3 : !fir.ref + return %4 : f32 +} + + +// CHECK-LABEL: func.func private @_QFPa() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFFaEa"} +// CHECK: %[[VAL_1:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFaEa"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32 +// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref +// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref +// CHECK: return %[[VAL_5]] : i32 +// CHECK: } + +// CHECK-LABEL: func.func private @_QFPb() -> i32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFFbEr"} +// CHECK: %[[VAL_1:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFbEr"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_3:.*]] = arith.constant 2 : i32 +// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref +// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref +// CHECK: return %[[VAL_5]] : i32 +// CHECK: } + +// CHECK-LABEL: func.func private @_QFPc() -> f32 attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_0:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFFcEr"} +// CHECK: %[[VAL_1:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFcEr"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_3:.*]] = arith.constant 3.000000e+00 : f32 +// CHECK: fir.store %[[VAL_3]] to %[[VAL_2]] : !fir.ref +// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref +// CHECK: return %[[VAL_5]] : f32 +// CHECK: } + diff --git a/flang/test/HLFIR/volatile3.fir b/flang/test/HLFIR/volatile3.fir new file mode 100644 index 0000000000000..41e42916e8ee5 --- /dev/null +++ b/flang/test/HLFIR/volatile3.fir @@ -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> + %c10 = arith.constant 10 : index + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2 = fir.volatile_cast %0 : (!fir.ref>) -> !fir.ref, volatile> + %3:2 = hlfir.declare %2(%1) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %4 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %5 = fir.volatile_cast %4 : (!fir.ref) -> !fir.ref + %6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %7 = fir.address_of(@_QFEptr) : !fir.ref>>> + %8 = fir.volatile_cast %7 : (!fir.ref>>>) -> !fir.ref>, volatile>, volatile> + %9:2 = hlfir.declare %8 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptr"} : (!fir.ref>, volatile>, volatile>) -> (!fir.ref>, volatile>, volatile>, !fir.ref>, volatile>, volatile>) + %10 = fir.address_of(@_QFEtgt) : !fir.ref> + %c10_0 = arith.constant 10 : index + %11 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %12 = fir.volatile_cast %10 : (!fir.ref>) -> !fir.ref, volatile> + %13:2 = hlfir.declare %12(%11) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEtgt"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %14 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %15 = fir.embox %13#0(%14) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box>, volatile> + fir.store %15 to %9#0 : !fir.ref>, volatile>, volatile> + %c0_i32 = arith.constant 0 : i32 + hlfir.assign %c0_i32 to %6#0 : i32, !fir.ref + %c1_i32 = arith.constant 1 : i32 + hlfir.assign %c1_i32 to %3#0 : i32, !fir.ref, volatile> + %16 = fir.volatile_cast %3#0 : (!fir.ref, volatile>) -> !fir.ref> + fir.call @_QFPd(%16) fastmath : (!fir.ref>) -> () + %17 = fir.embox %3#0(%1) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> + %18 = fir.volatile_cast %17 : (!fir.box, volatile>) -> !fir.box> + %19 = fir.convert %18 : (!fir.box>) -> !fir.box> + fir.call @_QFPe(%19) fastmath : (!fir.box>) -> () + %20 = fir.volatile_cast %3#0 : (!fir.ref, volatile>) -> !fir.ref> + fir.call @_QFPf(%20) fastmath : (!fir.ref>) -> () + %21 = fir.convert %9#0 : (!fir.ref>, volatile>, volatile>) -> !fir.ref>>, volatile> + fir.call @_QFPg(%21) fastmath : (!fir.ref>>, volatile>) -> () + return +} +func.func private @_QFPd(%arg0: !fir.ref> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %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.ref, volatile> + %3:2 = hlfir.declare %2(%1) dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFdEarr"} : (!fir.ref, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref, volatile>, !fir.ref, volatile>) + return +} +func.func private @_QFPe(%arg0: !fir.box> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %0 = fir.dummy_scope : !fir.dscope + %1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFeEarr"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) + return +} +func.func private @_QFPf(%arg0: !fir.ref> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %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.ref, volatile> + %3:2 = hlfir.declare %2(%1) dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFfEarr"} : (!fir.ref, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref, volatile>, !fir.ref, volatile>) + return +} +func.func private @_QFPg(%arg0: !fir.ref>>, volatile> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.volatile_cast %arg0 : (!fir.ref>>, volatile>) -> !fir.ref>, volatile>, volatile> + %2:2 = hlfir.declare %1 dummy_scope %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFgEarr"} : (!fir.ref>, volatile>, volatile>, !fir.dscope) -> (!fir.ref>, volatile>, volatile>, !fir.ref>, volatile>, volatile>) + return +} + +// CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} { +// CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box, volatile> +// CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFEarr) : !fir.ref> +// 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.ref, volatile> +// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +// CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_9:.*]] = fir.address_of(@_QFEptr) : !fir.ref>>> +// CHECK: %[[VAL_10:.*]] = fir.volatile_cast %[[VAL_9]] : (!fir.ref>>>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_11:.*]] = fir.declare %[[VAL_10]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptr"} : (!fir.ref>, volatile>, volatile>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEtgt) : !fir.ref> +// 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.ref, volatile> +// CHECK: %[[VAL_16:.*]] = fir.declare %[[VAL_15]](%[[VAL_14]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEtgt"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_17:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_16]](%[[VAL_17]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box>, volatile> +// CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_19:.*]] = arith.constant 0 : i32 +// CHECK: fir.store %[[VAL_19]] to %[[VAL_8]] : !fir.ref +// CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_21:.*]] = fir.alloca i32 +// CHECK: fir.store %[[VAL_20]] to %[[VAL_21]] : !fir.ref +// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_21]] : (!fir.ref) -> !fir.box +// CHECK: %[[VAL_23:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_5]](%[[VAL_23]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: fir.store %[[VAL_24]] to %[[VAL_0]] : !fir.ref, 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, volatile>>) -> !fir.ref> +// CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_22]] : (!fir.box) -> !fir.box +// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_25]] +// CHECK: fir.call @_FortranAAssign(%[[VAL_28]], %[[VAL_29]], %[[VAL_30]], %[[VAL_27]]) : (!fir.ref>, !fir.box, !fir.ref, i32) -> () +// CHECK: %[[VAL_31:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref, volatile>) -> !fir.ref> +// CHECK: fir.call @_QFPd(%[[VAL_31]]) fastmath : (!fir.ref>) -> () +// CHECK: %[[VAL_32:.*]] = fir.embox %[[VAL_5]](%[[VAL_3]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: %[[VAL_33:.*]] = fir.volatile_cast %[[VAL_32]] : (!fir.box, volatile>) -> !fir.box> +// CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (!fir.box>) -> !fir.box> +// CHECK: fir.call @_QFPe(%[[VAL_34]]) fastmath : (!fir.box>) -> () +// CHECK: %[[VAL_35:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref, volatile>) -> !fir.ref> +// CHECK: fir.call @_QFPf(%[[VAL_35]]) fastmath : (!fir.ref>) -> () +// CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_11]] : (!fir.ref>, volatile>, volatile>) -> !fir.ref>>, volatile> +// CHECK: fir.call @_QFPg(%[[VAL_36]]) fastmath : (!fir.ref>>, 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.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// 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.ref, volatile> +// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFdEarr"} : (!fir.ref, volatile>, !fir.shape<1>, !fir.dscope) -> !fir.ref, 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.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope +// CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFeEarr"} : (!fir.box>, !fir.dscope) -> !fir.box> +// CHECK: %[[VAL_3:.*]] = fir.rebox %[[VAL_2]] : (!fir.box>) -> !fir.box> +// 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.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// 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.ref, volatile> +// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFfEarr"} : (!fir.ref, volatile>, !fir.shape<1>, !fir.dscope) -> !fir.ref, 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>>, volatile> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope +// CHECK: %[[VAL_2:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref>>, volatile>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_2]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFFgEarr"} : (!fir.ref>, volatile>, volatile>, !fir.dscope) -> !fir.ref>, volatile>, volatile> +// CHECK: return +// CHECK: } diff --git a/flang/test/HLFIR/volatile4.fir b/flang/test/HLFIR/volatile4.fir new file mode 100644 index 0000000000000..cbf0aa31cb9f3 --- /dev/null +++ b/flang/test/HLFIR/volatile4.fir @@ -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> + %c10 = arith.constant 10 : index + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2 = fir.volatile_cast %0 : (!fir.ref>) -> !fir.ref, volatile> + %3:2 = hlfir.declare %2(%1) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %4 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %5 = fir.volatile_cast %4 : (!fir.ref) -> !fir.ref + %6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %7 = fir.address_of(@_QFEptr) : !fir.ref>>> + %8 = fir.volatile_cast %7 : (!fir.ref>>>) -> !fir.ref>, volatile>, volatile> + %9:2 = hlfir.declare %8 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptr"} : (!fir.ref>, volatile>, volatile>) -> (!fir.ref>, volatile>, volatile>, !fir.ref>, volatile>, volatile>) + %10 = fir.address_of(@_QFEtgt) : !fir.ref> + %c10_0 = arith.constant 10 : index + %11 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %12 = fir.volatile_cast %10 : (!fir.ref>) -> !fir.ref, volatile> + %13:2 = hlfir.declare %12(%11) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEtgt"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %14 = fir.alloca tuple> + %c0_i32 = arith.constant 0 : i32 + %15 = fir.coordinate_of %14, %c0_i32 : (!fir.ref>>, i32) -> !fir.llvm_ptr> + %16 = fir.volatile_cast %6#0 : (!fir.ref) -> !fir.ref + fir.store %16 to %15 : !fir.llvm_ptr> + %17 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %18 = fir.embox %13#0(%17) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box>, volatile> + fir.store %18 to %9#0 : !fir.ref>, volatile>, volatile> + %c0_i32_1 = arith.constant 0 : i32 + hlfir.assign %c0_i32_1 to %6#0 : i32, !fir.ref + %c1_i32 = arith.constant 1 : i32 + hlfir.assign %c1_i32 to %3#0 : i32, !fir.ref, volatile> + fir.call @_QFPhost_assoc(%14) fastmath : (!fir.ref>>) -> () + return +} +func.func private @_QFPhost_assoc(%arg0: !fir.ref>> {fir.host_assoc}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.address_of(@_QFEarr) : !fir.ref> + %c10 = arith.constant 10 : index + %2 = fir.shape %c10 : (index) -> !fir.shape<1> + %3 = fir.volatile_cast %1 : (!fir.ref>) -> !fir.ref, volatile> + %4:2 = hlfir.declare %3(%2) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %5 = fir.address_of(@_QFEptr) : !fir.ref>>> + %6 = fir.volatile_cast %5 : (!fir.ref>>>) -> !fir.ref>, volatile>, volatile> + %7:2 = hlfir.declare %6 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptr"} : (!fir.ref>, volatile>, volatile>) -> (!fir.ref>, volatile>, volatile>, !fir.ref>, volatile>, volatile>) + %8 = fir.address_of(@_QFEtgt) : !fir.ref> + %c10_0 = arith.constant 10 : index + %9 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %10 = fir.volatile_cast %8 : (!fir.ref>) -> !fir.ref, volatile> + %11:2 = hlfir.declare %10(%9) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEtgt"} : (!fir.ref, volatile>, !fir.shape<1>) -> (!fir.ref, volatile>, !fir.ref, volatile>) + %c0_i32 = arith.constant 0 : i32 + %12 = fir.coordinate_of %arg0, %c0_i32 : (!fir.ref>>, i32) -> !fir.llvm_ptr> + %13 = fir.load %12 : !fir.llvm_ptr> + %14 = fir.volatile_cast %13 : (!fir.ref) -> !fir.ref + %15:2 = hlfir.declare %14 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %16 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %17 = fir.embox %11#0(%16) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box>, volatile> + fir.store %17 to %7#0 : !fir.ref>, volatile>, volatile> + %c0_i32_1 = arith.constant 0 : i32 + hlfir.assign %c0_i32_1 to %15#0 : i32, !fir.ref + %c1_i32 = arith.constant 1 : i32 + hlfir.assign %c1_i32 to %4#0 : i32, !fir.ref, volatile> + return +} +// CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} { +// CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box, volatile> +// CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFEarr) : !fir.ref> +// 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.ref, volatile> +// CHECK: %[[VAL_5:.*]] = fir.declare %[[VAL_4]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +// CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_9:.*]] = fir.address_of(@_QFEptr) : !fir.ref>>> +// CHECK: %[[VAL_10:.*]] = fir.volatile_cast %[[VAL_9]] : (!fir.ref>>>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_11:.*]] = fir.declare %[[VAL_10]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptr"} : (!fir.ref>, volatile>, volatile>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEtgt) : !fir.ref> +// 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.ref, volatile> +// CHECK: %[[VAL_16:.*]] = fir.declare %[[VAL_15]](%[[VAL_14]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEtgt"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_17:.*]] = fir.alloca tuple> +// CHECK: %[[VAL_18:.*]] = arith.constant 0 : i32 +// CHECK: %[[VAL_19:.*]] = fir.coordinate_of %[[VAL_17]], %[[VAL_18]] : (!fir.ref>>, i32) -> !fir.llvm_ptr> +// CHECK: %[[VAL_20:.*]] = fir.volatile_cast %[[VAL_8]] : (!fir.ref) -> !fir.ref +// CHECK: fir.store %[[VAL_20]] to %[[VAL_19]] : !fir.llvm_ptr> +// CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_13]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_16]](%[[VAL_21]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box>, volatile> +// CHECK: fir.store %[[VAL_22]] to %[[VAL_11]] : !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_23:.*]] = arith.constant 0 : i32 +// CHECK: fir.store %[[VAL_23]] to %[[VAL_8]] : !fir.ref +// CHECK: %[[VAL_24:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_25:.*]] = fir.alloca i32 +// CHECK: fir.store %[[VAL_24]] to %[[VAL_25]] : !fir.ref +// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]] : (!fir.ref) -> !fir.box +// CHECK: %[[VAL_27:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_5]](%[[VAL_27]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: fir.store %[[VAL_28]] to %[[VAL_0]] : !fir.ref, 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, volatile>>) -> !fir.ref> +// CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_26]] : (!fir.box) -> !fir.box +// CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_29]] +// CHECK: fir.call @_FortranAAssign(%[[VAL_32]], %[[VAL_33]], %[[VAL_34]], %[[VAL_31]]) : (!fir.ref>, !fir.box, !fir.ref, i32) -> () +// CHECK: fir.call @_QFPhost_assoc(%[[VAL_17]]) fastmath : (!fir.ref>>) -> () +// 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>> {fir.host_assoc}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} { +// CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box, volatile> +// CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope +// CHECK: %[[VAL_3:.*]] = fir.address_of(@_QFEarr) : !fir.ref> +// 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.ref, volatile> +// CHECK: %[[VAL_7:.*]] = fir.declare %[[VAL_6]](%[[VAL_5]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarr"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_8:.*]] = fir.address_of(@_QFEptr) : !fir.ref>>> +// CHECK: %[[VAL_9:.*]] = fir.volatile_cast %[[VAL_8]] : (!fir.ref>>>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_10:.*]] = fir.declare %[[VAL_9]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptr"} : (!fir.ref>, volatile>, volatile>) -> !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_11:.*]] = fir.address_of(@_QFEtgt) : !fir.ref> +// 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.ref, volatile> +// CHECK: %[[VAL_15:.*]] = fir.declare %[[VAL_14]](%[[VAL_13]]) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEtgt"} : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.ref, volatile> +// CHECK: %[[VAL_16:.*]] = arith.constant 0 : i32 +// CHECK: %[[VAL_17:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_16]] : (!fir.ref>>, i32) -> !fir.llvm_ptr> +// CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.llvm_ptr> +// CHECK: %[[VAL_19:.*]] = fir.volatile_cast %[[VAL_18]] : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_20:.*]] = fir.declare %[[VAL_19]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref +// CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_15]](%[[VAL_21]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box>, volatile> +// CHECK: fir.store %[[VAL_22]] to %[[VAL_10]] : !fir.ref>, volatile>, volatile> +// CHECK: %[[VAL_23:.*]] = arith.constant 0 : i32 +// CHECK: fir.store %[[VAL_23]] to %[[VAL_20]] : !fir.ref +// CHECK: %[[VAL_24:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_25:.*]] = fir.alloca i32 +// CHECK: fir.store %[[VAL_24]] to %[[VAL_25]] : !fir.ref +// CHECK: %[[VAL_26:.*]] = fir.embox %[[VAL_25]] : (!fir.ref) -> !fir.box +// CHECK: %[[VAL_27:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_7]](%[[VAL_27]]) : (!fir.ref, volatile>, !fir.shape<1>) -> !fir.box, volatile> +// CHECK: fir.store %[[VAL_28]] to %[[VAL_1]] : !fir.ref, 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, volatile>>) -> !fir.ref> +// CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_26]] : (!fir.box) -> !fir.box +// CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_29]] +// CHECK: fir.call @_FortranAAssign(%[[VAL_32]], %[[VAL_33]], %[[VAL_34]], %[[VAL_31]]) : (!fir.ref>, !fir.box, !fir.ref, i32) -> () +// CHECK: return +// CHECK: } +// CHECK: func.func private @_FortranAAssign(!fir.ref>, !fir.box, !fir.ref, i32) attributes {fir.runtime} +