-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Handle volatility in lowering and codegen #135311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] Handle volatility in lowering and codegen #135311
Conversation
Enable lowering conversion patterns to pass volatility information to the LLVM dialect in the form of attributes on loads, stores, and memory intrinsics. For volatile types to enter the IR, entities with the volatile attribute will be given a volatile type in the bridge; this part is not enabled in this patch. Only the lowering from hlfir containing volatile types down to code generation supports volatile types, but user code should not produce volatile types yet. This is why this patch contains no tests with Fortran source, only IR that already contains volatile types.
@llvm/pr-subscribers-flang-codegen Author: Asher Mancinelli (ashermancinelli) Changes
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. Patch is 77.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135311.diff 18 Files Affected:
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<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 @@ 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<mlir::Value, 1> 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<CapturedProcedure> {
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 @@ 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<fir::IsPresentOp>(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<fir::StoreOp>(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<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 {
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<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);
}
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<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) {
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<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 @@ 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<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,
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index b54b497ee4ba1..d2987a5881c44 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::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, NoReassocOpConvers...
[truncated]
|
@llvm/pr-subscribers-flang-fir-hlfir Author: Asher Mancinelli (ashermancinelli) Changes
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. Patch is 77.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135311.diff 18 Files Affected:
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<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 @@ 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<mlir::Value, 1> 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<CapturedProcedure> {
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 @@ 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<fir::IsPresentOp>(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<fir::StoreOp>(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<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 {
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<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);
}
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<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) {
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<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 @@ 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<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,
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index b54b497ee4ba1..d2987a5881c44 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::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, NoReassocOpConvers...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
* origin/main: (199 commits) [NFC][AsmPrinter] Refactor AsmPrinter and AArch64AsmPrinter to prepare for jump table partitions on aarch64 (llvm#125993) [HEXAGON] Fix corner cases for hwloops pass (llvm#135439) [flang] Handle volatility in lowering and codegen (llvm#135311) [MLIR][Shape] Support >2 args in `shape.broadcast` folder (llvm#126808) [DirectX] Use scalar arguments for @llvm.dx.dot intrinsics (llvm#134570) Remove the redundant check for "WeakPtr" in isSmartPtrClass to fix the issue 135612. (llvm#135629) [BOLT] Support relative vtable (llvm#135449) [flang] Fix linking to libMLIR (llvm#135483) [AsmPrinter] Link .section_sizes to the correct section (llvm#135583) [ctxprof] Handle instrumenting functions with `musttail` calls (llvm#135121) [SystemZ] Consider VST/VL as SimpleBDXStore/Load (llvm#135623) [libc++][CI] Pin the XCode version. (llvm#135412) [lldb-dap] Fix win32 build. (llvm#135638) [Interp] Mark inline-virtual.cpp as unsupported with ASan (llvm#135402) [libc++] Removes the _LIBCPP_VERBOSE_ABORT_NOT_NOEXCEPT macro. (llvm#135494) [CVP] Add tests for ucmp/scmp with switch (NFC) [mlir][tosa] Align AbsOp example variable names (llvm#135268) [mlir][tosa] Align AddOp examples to spec (llvm#135266) [mlir][tosa] Align RFFT2d and FFT2d operator examples (llvm#135261) [flang][OpenMP][HLFIR] Support vector subscripted array sections for DEPEND (llvm#133892) ...
* 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 llvm#132486.
[RFC on discourse](https://discourse.llvm.org/t/rfc-volatile-representation-in-flang/85404/1) Flang currently lacks support for volatile variables. For some cases, the compiler produces TODO error messages and others are ignored. Some of our tests are like the example from _C.4 Clause 8 notes: The VOLATILE attribute (8.5.20)_ and require volatile variables. Prior commits: ``` c9ec1bc [flang] Handle volatility in lowering and codegen (#135311) e42f860 [flang][nfc] Support volatility in Fir ops (#134858) b2711e1 [flang][nfc] Support volatile on ref, box, and class types (#134386) ```
[RFC on discourse](https://discourse.llvm.org/t/rfc-volatile-representation-in-flang/85404/1) Flang currently lacks support for volatile variables. For some cases, the compiler produces TODO error messages and others are ignored. Some of our tests are like the example from _C.4 Clause 8 notes: The VOLATILE attribute (8.5.20)_ and require volatile variables. Prior commits: ``` c9ec1bc [flang] Handle volatility in lowering and codegen (llvm#135311) e42f860 [flang][nfc] Support volatility in Fir ops (llvm#134858) b2711e1 [flang][nfc] Support volatile on ref, box, and class types (llvm#134386) ```
[RFC on discourse](https://discourse.llvm.org/t/rfc-volatile-representation-in-flang/85404/1) Flang currently lacks support for volatile variables. For some cases, the compiler produces TODO error messages and others are ignored. Some of our tests are like the example from _C.4 Clause 8 notes: The VOLATILE attribute (8.5.20)_ and require volatile variables. Prior commits: ``` c9ec1bc [flang] Handle volatility in lowering and codegen (llvm#135311) e42f860 [flang][nfc] Support volatility in Fir ops (llvm#134858) b2711e1 [flang][nfc] Support volatile on ref, box, and class types (llvm#134386) ```
[RFC on discourse](https://discourse.llvm.org/t/rfc-volatile-representation-in-flang/85404/1) Flang currently lacks support for volatile variables. For some cases, the compiler produces TODO error messages and others are ignored. Some of our tests are like the example from _C.4 Clause 8 notes: The VOLATILE attribute (8.5.20)_ and require volatile variables. Prior commits: ``` c9ec1bc [flang] Handle volatility in lowering and codegen (llvm#135311) e42f860 [flang][nfc] Support volatility in Fir ops (llvm#134858) b2711e1 [flang][nfc] Support volatile on ref, box, and class types (llvm#134386) ```
[RFC on discourse](https://discourse.llvm.org/t/rfc-volatile-representation-in-flang/85404/1) Flang currently lacks support for volatile variables. For some cases, the compiler produces TODO error messages and others are ignored. Some of our tests are like the example from _C.4 Clause 8 notes: The VOLATILE attribute (8.5.20)_ and require volatile variables. Prior commits: ``` c9ec1bc [flang] Handle volatility in lowering and codegen (llvm#135311) e42f860 [flang][nfc] Support volatility in Fir ops (llvm#134858) b2711e1 [flang][nfc] Support volatile on ref, box, and class types (llvm#134386) ```
[RFC on discourse](https://discourse.llvm.org/t/rfc-volatile-representation-in-flang/85404/1) Flang currently lacks support for volatile variables. For some cases, the compiler produces TODO error messages and others are ignored. Some of our tests are like the example from _C.4 Clause 8 notes: The VOLATILE attribute (8.5.20)_ and require volatile variables. Prior commits: ``` c9ec1bc [flang] Handle volatility in lowering and codegen (llvm#135311) e42f860 [flang][nfc] Support volatility in Fir ops (llvm#134858) b2711e1 [flang][nfc] Support volatile on ref, box, and class types (llvm#134386) ```
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.