[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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) ||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>(
|
||||
|
||||
154
flang/test/HLFIR/volatile1.fir
Normal file
154
flang/test/HLFIR/volatile1.fir
Normal 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}
|
||||
66
flang/test/HLFIR/volatile2.fir
Normal file
66
flang/test/HLFIR/volatile2.fir
Normal 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: }
|
||||
|
||||
150
flang/test/HLFIR/volatile3.fir
Normal file
150
flang/test/HLFIR/volatile3.fir
Normal 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: }
|
||||
153
flang/test/HLFIR/volatile4.fir
Normal file
153
flang/test/HLFIR/volatile4.fir
Normal 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}
|
||||
|
||||
Reference in New Issue
Block a user