Skip to content

Commit 7e7b15d

Browse files
[flang] Add represention of volatile references
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. This change is a minimal draft of support for volatility in Fortran. This misses several important features that will be required for full support, such as volatile boxes and other reference-like types. This commit only supports volatility for !fir.ref<T> types and is the minimum needed to get end-to-end examples working.
1 parent 0794d5c commit 7e7b15d

File tree

15 files changed

+183
-38
lines changed

15 files changed

+183
-38
lines changed

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
150150
mlir::Block *getAllocaBlock();
151151

152152
/// Safely create a reference type to the type `eleTy`.
153-
mlir::Type getRefType(mlir::Type eleTy);
153+
mlir::Type getRefType(mlir::Type eleTy, bool isVolatile = false);
154154

155155
/// Create a sequence of `eleTy` with `rank` dimensions of unknown size.
156156
mlir::Type getVarLenSeqTy(mlir::Type eleTy, unsigned rank = 1);

flang/include/flang/Optimizer/Dialect/FIRType.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ inline bool isa_ref_type(mlir::Type t) {
111111
fir::LLVMPointerType>(t);
112112
}
113113

114+
inline bool isa_volatile_ref_type(mlir::Type t) {
115+
if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(t))
116+
return refTy.isVolatile();
117+
return false;
118+
}
119+
114120
/// Is `t` a boxed type?
115121
inline bool isa_box_type(mlir::Type t) {
116122
return mlir::isa<fir::BaseBoxType, fir::BoxCharType, fir::BoxProcType>(t);

flang/include/flang/Optimizer/Dialect/FIRTypes.td

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,18 +363,22 @@ def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
363363
The type of a reference to an entity in memory.
364364
}];
365365

366-
let parameters = (ins "mlir::Type":$eleTy);
366+
let parameters = (ins
367+
"mlir::Type":$eleTy,
368+
DefaultValuedParameter<"bool", "false">:$isVol);
367369

368370
let skipDefaultBuilders = 1;
369371

370372
let builders = [
371-
TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
372-
return Base::get(elementType.getContext(), elementType);
373+
TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType, CArg<"bool", "false">:$isVol), [{
374+
return Base::get(elementType.getContext(), elementType, isVol);
373375
}]>,
374376
];
375377

376378
let extraClassDeclaration = [{
377379
mlir::Type getElementType() const { return getEleTy(); }
380+
bool isVolatile() const { return (bool)getIsVol(); }
381+
static llvm::StringRef getVolatileKeyword() { return "volatile"; }
378382
}];
379383

380384
let genVerifyDecl = 1;

flang/lib/Lower/CallInterface.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,6 @@ class Fortran::lower::CallInterfaceImpl {
11121112
if (obj.attrs.test(Attrs::Value))
11131113
isValueAttr = true; // TODO: do we want an mlir::Attribute as well?
11141114
if (obj.attrs.test(Attrs::Volatile)) {
1115-
TODO(loc, "VOLATILE in procedure interface");
11161115
addMLIRAttr(fir::getVolatileAttrName());
11171116
}
11181117
// obj.attrs.test(Attrs::Asynchronous) does not impact the way the argument

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,37 @@ class HlfirDesignatorBuilder {
223223
designatorNode, getConverter().getFoldingContext(),
224224
/*namedConstantSectionsAreAlwaysContiguous=*/false))
225225
return fir::BoxType::get(resultValueType);
226+
227+
bool isVolatile = false;
228+
229+
// Check if the base type is volatile
230+
if (partInfo.base.has_value()) {
231+
mlir::Type baseType = partInfo.base.value().getType();
232+
isVolatile = fir::isa_volatile_ref_type(baseType);
233+
}
234+
235+
auto isVolatileSymbol = [](const Fortran::semantics::Symbol &symbol) {
236+
return symbol.GetUltimate().attrs().test(
237+
Fortran::semantics::Attr::VOLATILE);
238+
};
239+
240+
// Check if this should be a volatile reference
241+
if constexpr (std::is_same_v<std::decay_t<T>,
242+
Fortran::evaluate::SymbolRef>) {
243+
if (isVolatileSymbol(designatorNode.get()))
244+
isVolatile = true;
245+
} else if constexpr (std::is_same_v<std::decay_t<T>,
246+
Fortran::evaluate::Component>) {
247+
if (isVolatileSymbol(designatorNode.GetLastSymbol()))
248+
isVolatile = true;
249+
}
250+
251+
// If it's a reference to a ref, account for it
252+
if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(resultValueType))
253+
resultValueType = refTy.getEleTy();
254+
226255
// Other designators can be handled as raw addresses.
227-
return fir::ReferenceType::get(resultValueType);
256+
return fir::ReferenceType::get(resultValueType, isVolatile);
228257
}
229258

230259
template <typename T>
@@ -415,10 +444,16 @@ class HlfirDesignatorBuilder {
415444
.Case<fir::SequenceType>([&](fir::SequenceType seqTy) -> mlir::Type {
416445
return fir::SequenceType::get(seqTy.getShape(), newEleTy);
417446
})
418-
.Case<fir::PointerType, fir::HeapType, fir::ReferenceType, fir::BoxType,
419-
fir::ClassType>([&](auto t) -> mlir::Type {
420-
using FIRT = decltype(t);
421-
return FIRT::get(changeElementType(t.getEleTy(), newEleTy));
447+
// TODO: handle volatility for other types
448+
.Case<fir::PointerType, fir::HeapType, fir::BoxType, fir::ClassType>(
449+
[&](auto t) -> mlir::Type {
450+
using FIRT = decltype(t);
451+
return FIRT::get(changeElementType(t.getEleTy(), newEleTy));
452+
})
453+
.Case<fir::ReferenceType>([&](fir::ReferenceType refTy) -> mlir::Type {
454+
return fir::ReferenceType::get(
455+
changeElementType(refTy.getEleTy(), newEleTy),
456+
refTy.isVolatile());
422457
})
423458
.Default([newEleTy](mlir::Type t) -> mlir::Type { return newEleTy; });
424459
}
@@ -1809,6 +1844,7 @@ class HlfirBuilder {
18091844
auto &expr = std::get<const Fortran::lower::SomeExpr &>(iter);
18101845
auto &baseOp = std::get<hlfir::EntityWithAttributes>(iter);
18111846
std::string name = converter.getRecordTypeFieldName(sym);
1847+
const bool isVolatile = fir::isa_volatile_ref_type(baseOp.getType());
18121848

18131849
// Generate DesignateOp for the component.
18141850
// The designator's result type is just a reference to the component type,
@@ -1819,7 +1855,7 @@ class HlfirBuilder {
18191855
assert(compType && "failed to retrieve component type");
18201856
mlir::Value compShape =
18211857
designatorBuilder.genComponentShape(sym, compType);
1822-
mlir::Type designatorType = builder.getRefType(compType);
1858+
mlir::Type designatorType = builder.getRefType(compType, isVolatile);
18231859

18241860
mlir::Type fieldElemType = hlfir::getFortranElementType(compType);
18251861
llvm::SmallVector<mlir::Value, 1> typeParams;

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ fir::FirOpBuilder::getNamedGlobal(mlir::ModuleOp modOp,
104104
return modOp.lookupSymbol<fir::GlobalOp>(name);
105105
}
106106

107-
mlir::Type fir::FirOpBuilder::getRefType(mlir::Type eleTy) {
107+
mlir::Type fir::FirOpBuilder::getRefType(mlir::Type eleTy, bool isVolatile) {
108108
assert(!mlir::isa<fir::ReferenceType>(eleTy) && "cannot be a reference type");
109-
return fir::ReferenceType::get(eleTy);
109+
return fir::ReferenceType::get(eleTy, isVolatile);
110110
}
111111

112112
mlir::Type fir::FirOpBuilder::getVarLenSeqTy(mlir::Type eleTy, unsigned rank) {

flang/lib/Optimizer/Builder/HLFIRTools.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,8 @@ mlir::Type hlfir::getVariableElementType(hlfir::Entity variable) {
819819
} else if (fir::isRecordWithTypeParameters(eleTy)) {
820820
return fir::BoxType::get(eleTy);
821821
}
822-
return fir::ReferenceType::get(eleTy);
822+
const bool isVolatile = fir::isa_volatile_ref_type(variable.getType());
823+
return fir::ReferenceType::get(eleTy, isVolatile);
823824
}
824825

825826
mlir::Type hlfir::getEntityElementType(hlfir::Entity entity) {

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,6 +3224,8 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
32243224
mlir::ConversionPatternRewriter &rewriter) const override {
32253225

32263226
mlir::Type llvmLoadTy = convertObjectType(load.getType());
3227+
const bool isVolatile =
3228+
fir::isa_volatile_ref_type(load.getMemref().getType());
32273229
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(load.getType())) {
32283230
// fir.box is a special case because it is considered an ssa value in
32293231
// fir, but it is lowered as a pointer to a descriptor. So
@@ -3253,16 +3255,18 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
32533255
mlir::Value boxSize =
32543256
computeBoxSize(loc, boxTypePair, inputBoxStorage, rewriter);
32553257
auto memcpy = rewriter.create<mlir::LLVM::MemcpyOp>(
3256-
loc, newBoxStorage, inputBoxStorage, boxSize, /*isVolatile=*/false);
3258+
loc, newBoxStorage, inputBoxStorage, boxSize, isVolatile);
32573259

32583260
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
32593261
memcpy.setTBAATags(*optionalTag);
32603262
else
32613263
attachTBAATag(memcpy, boxTy, boxTy, nullptr);
32623264
rewriter.replaceOp(load, newBoxStorage);
32633265
} else {
3266+
// TODO: are we losing any attributes from the load op?
3267+
auto memref = adaptor.getOperands()[0];
32643268
auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(
3265-
load.getLoc(), llvmLoadTy, adaptor.getOperands(), load->getAttrs());
3269+
load.getLoc(), llvmLoadTy, memref, /*alignment=*/0, isVolatile);
32663270
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
32673271
loadOp.setTBAATags(*optionalTag);
32683272
else
@@ -3540,17 +3544,20 @@ struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> {
35403544
mlir::Value llvmValue = adaptor.getValue();
35413545
mlir::Value llvmMemref = adaptor.getMemref();
35423546
mlir::LLVM::AliasAnalysisOpInterface newOp;
3547+
const bool isVolatile =
3548+
fir::isa_volatile_ref_type(store.getMemref().getType());
35433549
if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(storeTy)) {
35443550
mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct(boxTy);
35453551
// Always use memcpy because LLVM is not as effective at optimizing
35463552
// aggregate loads/stores as it is optimizing memcpy.
35473553
TypePair boxTypePair{boxTy, llvmBoxTy};
35483554
mlir::Value boxSize =
35493555
computeBoxSize(loc, boxTypePair, llvmValue, rewriter);
3550-
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(
3551-
loc, llvmMemref, llvmValue, boxSize, /*isVolatile=*/false);
3556+
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(loc, llvmMemref, llvmValue,
3557+
boxSize, isVolatile);
35523558
} else {
3553-
newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref);
3559+
newOp = rewriter.create<mlir::LLVM::StoreOp>(loc, llvmValue, llvmMemref,
3560+
/*alignment=*/0, isVolatile);
35543561
}
35553562
if (std::optional<mlir::ArrayAttr> optionalTag = store.getTbaa())
35563563
newOp.setTBAATags(*optionalTag);

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -649,12 +649,17 @@ mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
649649
.Case<fir::SequenceType>([&](fir::SequenceType seqTy) -> mlir::Type {
650650
return fir::SequenceType::get(seqTy.getShape(), newElementType);
651651
})
652-
.Case<fir::PointerType, fir::HeapType, fir::ReferenceType,
653-
fir::ClassType>([&](auto t) -> mlir::Type {
654-
using FIRT = decltype(t);
655-
return FIRT::get(
656-
changeElementType(t.getEleTy(), newElementType, turnBoxIntoClass));
652+
.Case<fir::ReferenceType>([&](fir::ReferenceType refTy) -> mlir::Type {
653+
auto newEleTy = changeElementType(refTy.getEleTy(), newElementType,
654+
turnBoxIntoClass);
655+
return fir::ReferenceType::get(newEleTy, refTy.isVolatile());
657656
})
657+
.Case<fir::PointerType, fir::HeapType, fir::ClassType>(
658+
[&](auto t) -> mlir::Type {
659+
using FIRT = decltype(t);
660+
return FIRT::get(changeElementType(t.getEleTy(), newElementType,
661+
turnBoxIntoClass));
662+
})
658663
.Case<fir::BoxType>([&](fir::BoxType t) -> mlir::Type {
659664
mlir::Type newInnerType =
660665
changeElementType(t.getEleTy(), newElementType, false);
@@ -1057,18 +1062,38 @@ unsigned fir::RecordType::getFieldIndex(llvm::StringRef ident) {
10571062
// ReferenceType
10581063
//===----------------------------------------------------------------------===//
10591064

1060-
// `ref` `<` type `>`
1065+
// `ref` `<` type (`, volatile` $volatile^)? `>`
10611066
mlir::Type fir::ReferenceType::parse(mlir::AsmParser &parser) {
1062-
return parseTypeSingleton<fir::ReferenceType>(parser);
1067+
if (parser.parseLess())
1068+
return {};
1069+
1070+
mlir::Type eleTy;
1071+
if (parser.parseType(eleTy))
1072+
return {};
1073+
1074+
bool isVolatile = false;
1075+
if (!parser.parseOptionalComma()) {
1076+
if (parser.parseKeyword(getVolatileKeyword())) {
1077+
return {};
1078+
}
1079+
isVolatile = true;
1080+
}
1081+
1082+
if (parser.parseGreater())
1083+
return {};
1084+
return get(eleTy, isVolatile);
10631085
}
10641086

10651087
void fir::ReferenceType::print(mlir::AsmPrinter &printer) const {
1066-
printer << "<" << getEleTy() << '>';
1088+
printer << "<" << getEleTy();
1089+
if (isVolatile())
1090+
printer << ", " << getVolatileKeyword();
1091+
printer << '>';
10671092
}
10681093

10691094
llvm::LogicalResult fir::ReferenceType::verify(
1070-
llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1071-
mlir::Type eleTy) {
1095+
llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type eleTy,
1096+
bool isVolatile) {
10721097
if (mlir::isa<ShapeType, ShapeShiftType, SliceType, FieldType, LenType,
10731098
ReferenceType, TypeDescType>(eleTy))
10741099
return emitError() << "cannot build a reference to type: " << eleTy << '\n';
@@ -1319,11 +1344,15 @@ changeTypeShape(mlir::Type type,
13191344
return fir::SequenceType::get(*newShape, seqTy.getEleTy());
13201345
return seqTy.getEleTy();
13211346
})
1322-
.Case<fir::PointerType, fir::HeapType, fir::ReferenceType, fir::BoxType,
1323-
fir::ClassType>([&](auto t) -> mlir::Type {
1324-
using FIRT = decltype(t);
1325-
return FIRT::get(changeTypeShape(t.getEleTy(), newShape));
1347+
.Case<fir::ReferenceType>([&](fir::ReferenceType rt) -> mlir::Type {
1348+
return fir::ReferenceType::get(changeTypeShape(rt.getEleTy(), newShape),
1349+
rt.isVolatile());
13261350
})
1351+
.Case<fir::PointerType, fir::HeapType, fir::BoxType, fir::ClassType>(
1352+
[&](auto t) -> mlir::Type {
1353+
using FIRT = decltype(t);
1354+
return FIRT::get(changeTypeShape(t.getEleTy(), newShape));
1355+
})
13271356
.Default([&](mlir::Type t) -> mlir::Type {
13281357
assert((fir::isa_trivial(t) || llvm::isa<fir::RecordType>(t) ||
13291358
llvm::isa<mlir::NoneType>(t) ||

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
214214
auto nameAttr = builder.getStringAttr(uniq_name);
215215
mlir::Type inputType = memref.getType();
216216
bool hasExplicitLbs = hasExplicitLowerBounds(shape);
217+
if (fortran_attrs && mlir::isa<fir::ReferenceType>(inputType) &&
218+
bitEnumContainsAny(fortran_attrs.getFlags(),
219+
fir::FortranVariableFlagsEnum::fortran_volatile)) {
220+
auto refType = mlir::cast<fir::ReferenceType>(inputType);
221+
inputType = fir::ReferenceType::get(refType.getEleTy(), true);
222+
memref = builder.create<fir::ConvertOp>(memref.getLoc(), inputType, memref);
223+
}
217224
mlir::Type hlfirVariableType =
218225
getHLFIRVariableType(inputType, hasExplicitLbs);
219226
build(builder, result, {hlfirVariableType, inputType}, memref, shape,

flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,9 @@ class DesignateOpConversion
418418
firstElementIndices.push_back(indices[i]);
419419
i = i + (isTriplet ? 3 : 1);
420420
}
421-
mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy);
421+
mlir::Type originalDesignateType = designate.getResult().getType();
422+
const bool isVolatile = fir::isa_volatile_ref_type(originalDesignateType);
423+
mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy, isVolatile);
422424
base = builder.create<fir::ArrayCoorOp>(
423425
loc, arrayCoorType, base, shape,
424426
/*slice=*/mlir::Value{}, firstElementIndices, firBaseTypeParameters);
@@ -441,6 +443,7 @@ class DesignateOpConversion
441443
TODO(loc, "hlfir::designate load of pointer or allocatable");
442444

443445
mlir::Type designateResultType = designate.getResult().getType();
446+
const bool isVolatile = fir::isa_volatile_ref_type(designateResultType);
444447
llvm::SmallVector<mlir::Value> firBaseTypeParameters;
445448
auto [base, shape] = hlfir::genVariableFirBaseShapeAndParams(
446449
loc, builder, baseEntity, firBaseTypeParameters);
@@ -464,7 +467,7 @@ class DesignateOpConversion
464467
mlir::Type componentType =
465468
mlir::cast<fir::RecordType>(baseEleTy).getType(
466469
designate.getComponent().value());
467-
mlir::Type coorTy = fir::ReferenceType::get(componentType);
470+
mlir::Type coorTy = fir::ReferenceType::get(componentType, isVolatile);
468471
base = builder.create<fir::CoordinateOp>(loc, coorTy, base, fieldIndex);
469472
if (mlir::isa<fir::BaseBoxType>(componentType)) {
470473
auto variableInterface = mlir::cast<fir::FortranVariableOpInterface>(

flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,8 @@ class ReductionMaskConversion : public mlir::OpRewritePattern<Op> {
11261126
builder.create<fir::StoreOp>(loc, flagSet, flagRef);
11271127
mlir::Type resultElemTy =
11281128
hlfir::getFortranElementType(resultArr.getType());
1129-
mlir::Type returnRefTy = builder.getRefType(resultElemTy);
1129+
mlir::Type returnRefTy = builder.getRefType(
1130+
resultElemTy, fir::isa_volatile_ref_type(flagRef.getType()));
11301131
mlir::IndexType idxTy = builder.getIndexType();
11311132

11321133
for (unsigned int i = 0; i < rank; ++i) {
@@ -1153,7 +1154,8 @@ class ReductionMaskConversion : public mlir::OpRewritePattern<Op> {
11531154
auto getAddrFn = [](fir::FirOpBuilder builder, mlir::Location loc,
11541155
const mlir::Type &resultElemType, mlir::Value resultArr,
11551156
mlir::Value index) {
1156-
mlir::Type resultRefTy = builder.getRefType(resultElemType);
1157+
mlir::Type resultRefTy = builder.getRefType(
1158+
resultElemType, fir::isa_volatile_ref_type(resultArr.getType()));
11571159
mlir::Value oneIdx =
11581160
builder.createIntegerConstant(loc, builder.getIndexType(), 1);
11591161
index = builder.create<mlir::arith::AddIOp>(loc, index, oneIdx);
@@ -1162,8 +1164,9 @@ class ReductionMaskConversion : public mlir::OpRewritePattern<Op> {
11621164
};
11631165

11641166
// Initialize the result
1167+
const bool isVolatile = fir::isa_volatile_ref_type(resultArr.getType());
11651168
mlir::Type resultElemTy = hlfir::getFortranElementType(resultArr.getType());
1166-
mlir::Type resultRefTy = builder.getRefType(resultElemTy);
1169+
mlir::Type resultRefTy = builder.getRefType(resultElemTy, isVolatile);
11671170
mlir::Value returnValue =
11681171
builder.createIntegerConstant(loc, resultElemTy, 0);
11691172
for (unsigned int i = 0; i < rank; ++i) {

flang/test/Fir/volatile.fir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s -o - | FileCheck %s
2+
// CHECK: llvm.store volatile %{{.+}}, %{{.+}} : i32, !llvm.ptr
3+
// CHECK: %{{.+}} = llvm.load volatile %{{.+}} : !llvm.ptr -> i32
4+
func.func @foo() {
5+
%true = arith.constant true
6+
%false = arith.constant false
7+
%0 = fir.alloca !fir.logical<4> {bindc_name = "a", uniq_name = "_QFEa"}
8+
%1 = fir.convert %0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>, volatile>
9+
%2 = fir.alloca !fir.logical<4> {bindc_name = "b", uniq_name = "_QFEb"}
10+
%3 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
11+
%4 = fir.convert %false : (i1) -> !fir.logical<4>
12+
fir.store %4 to %1 : !fir.ref<!fir.logical<4>, volatile>
13+
%5 = fir.load %1 : !fir.ref<!fir.logical<4>, volatile>
14+
fir.store %5 to %2 : !fir.ref<!fir.logical<4>>
15+
%6 = fir.convert %true : (i1) -> !fir.logical<4>
16+
fir.store %6 to %1 : !fir.ref<!fir.logical<4>, volatile>
17+
return
18+
}

flang/test/Integration/volatile.f90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
! RUN: bbc %s -o - | FileCheck %s
2+
logical, volatile :: a
3+
logical :: b
4+
integer :: i
5+
a = .false.
6+
b = a
7+
a = .true.
8+
end
9+
10+
! CHECK: %{{.+}} = fir.load %{{.+}} : !fir.ref<!fir.logical<4>, volatile>
11+
! CHECK: hlfir.assign %{{.+}} to %{{.+}} : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>

0 commit comments

Comments
 (0)