[flang] Add lowering of volatile references (#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: ``` c9ec1bc753b0 [flang] Handle volatility in lowering and codegen (#135311) e42f8609858f [flang][nfc] Support volatility in Fir ops (#134858) b2711e1526f9 [flang][nfc] Support volatile on ref, box, and class types (#134386) ```
This commit is contained in:
parent
f91a6e6dab
commit
8836bce842
@ -104,7 +104,6 @@ All features except those listed in the following table are supported.
|
||||
|------------------------------------------------------------|--------|---------------------------------------------------------|
|
||||
| Parameterized Derived Types | P | PDT with length type parameters is not supported. See [Proposal](ParameterizedDerivedTypes.md) |
|
||||
| Assignment to allocatable | P | Assignment to whole allocatable in FORALL is not implemented |
|
||||
| The VOLATILE attribute | P | VOLATILE in procedure interfaces is not implemented |
|
||||
| Asynchronous input/output | P | IO will happen synchronously |
|
||||
| MIN/MAX extensions for CHARACTER | P | Some variants are not supported |
|
||||
|
||||
|
@ -24,6 +24,8 @@ page](https://llvm.org/releases/).
|
||||
|
||||
## Major New Features
|
||||
|
||||
* Initial support for VOLATILE variables and procedure interface arguments has been added.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
## Non-comprehensive list of changes in this release
|
||||
|
@ -236,7 +236,7 @@ public:
|
||||
auto ty = getBoxTy().getEleTy();
|
||||
if (fir::isa_ref_type(ty))
|
||||
return ty;
|
||||
return fir::ReferenceType::get(ty, fir::isa_volatile_type(ty));
|
||||
return fir::ReferenceType::get(ty, fir::isa_volatile_type(getBoxTy()));
|
||||
}
|
||||
|
||||
/// Get the scalar type related to the described entity
|
||||
|
@ -829,14 +829,16 @@ template <int N, typename A>
|
||||
void createArguments(llvm::SmallVectorImpl<mlir::Value> &result,
|
||||
fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::FunctionType fTy, A arg) {
|
||||
result.emplace_back(builder.createConvert(loc, fTy.getInput(N), arg));
|
||||
result.emplace_back(
|
||||
builder.createConvertWithVolatileCast(loc, fTy.getInput(N), arg));
|
||||
}
|
||||
|
||||
template <int N, typename A, typename... As>
|
||||
void createArguments(llvm::SmallVectorImpl<mlir::Value> &result,
|
||||
fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::FunctionType fTy, A arg, As... args) {
|
||||
result.emplace_back(builder.createConvert(loc, fTy.getInput(N), arg));
|
||||
result.emplace_back(
|
||||
builder.createConvertWithVolatileCast(loc, fTy.getInput(N), arg));
|
||||
createArguments<N + 1>(result, builder, loc, fTy, args...);
|
||||
}
|
||||
} // namespace helper
|
||||
|
@ -2755,7 +2755,7 @@ def fir_AddrOfOp : fir_OneResultOp<"address_of", [NoMemoryEffect]> {
|
||||
let assemblyFormat = "`(` $symbol `)` attr-dict `:` type($resTy)";
|
||||
}
|
||||
|
||||
def fir_VolatileCastOp : fir_SimpleOneResultOp<"volatile_cast", [NoMemoryEffect]> {
|
||||
def fir_VolatileCastOp : fir_SimpleOneResultOp<"volatile_cast", [Pure]> {
|
||||
let summary = "cast between volatile and non-volatile types";
|
||||
let description = [{
|
||||
Cast between volatile and non-volatile types. The types must be otherwise
|
||||
|
@ -457,6 +457,10 @@ inline mlir::Type wrapInClassOrBoxType(mlir::Type eleTy,
|
||||
return fir::BoxType::get(eleTy);
|
||||
}
|
||||
|
||||
/// Re-create the given type with the given volatility, if this is a type
|
||||
/// that can represent volatility.
|
||||
mlir::Type updateTypeWithVolatility(mlir::Type type, bool isVolatile);
|
||||
|
||||
/// Return the elementType where intrinsic types are replaced with none for
|
||||
/// unlimited polymorphic entities.
|
||||
///
|
||||
|
@ -365,6 +365,11 @@ def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
|
||||
|
||||
let description = [{
|
||||
The type of a reference to an entity in memory.
|
||||
|
||||
References can be volatile. Any ops taking an operand of a volatile
|
||||
reference must set their memory effects appropriately. Accesses of
|
||||
volatile references are currently modeled as read and write effects
|
||||
to a specific memory resource.
|
||||
}];
|
||||
|
||||
let parameters = (ins "mlir::Type":$eleTy, "bool":$isVolatile);
|
||||
|
@ -1755,7 +1755,8 @@ private:
|
||||
// tags all result variables with one of the largest types to allow
|
||||
// them to share the same storage. Convert this to the actual type.
|
||||
if (resultRef.getType() != resultRefType)
|
||||
resultRef = builder->createConvert(loc, resultRefType, resultRef);
|
||||
resultRef = builder->createConvertWithVolatileCast(
|
||||
loc, resultRefType, resultRef);
|
||||
return builder->create<fir::LoadOp>(loc, resultRef);
|
||||
});
|
||||
genExitRoutine(false, resultVal);
|
||||
@ -3732,10 +3733,11 @@ private:
|
||||
builder->createMinusOneInteger(loc, builder->getIndexType())};
|
||||
mlir::Value baseAddr =
|
||||
hlfir::genVariableRawAddress(loc, *builder, selector);
|
||||
const bool isVolatile = fir::isa_volatile_type(selector.getType());
|
||||
mlir::Type eleType =
|
||||
fir::unwrapSequenceType(fir::unwrapRefType(baseAddr.getType()));
|
||||
mlir::Type rank1Type =
|
||||
fir::ReferenceType::get(builder->getVarLenSeqTy(eleType, 1));
|
||||
mlir::Type rank1Type = fir::ReferenceType::get(
|
||||
builder->getVarLenSeqTy(eleType, 1), isVolatile);
|
||||
baseAddr = builder->createConvert(loc, rank1Type, baseAddr);
|
||||
if (selector.isCharacter()) {
|
||||
mlir::Value len = hlfir::genCharLength(loc, *builder, selector);
|
||||
@ -3755,7 +3757,8 @@ private:
|
||||
mlir::cast<fir::BaseBoxType>(fir::unwrapRefType(selector.getType()));
|
||||
mlir::Type newBoxType = boxTy.getBoxTypeWithNewShape(rank);
|
||||
if (fir::isa_ref_type(selector.getType()))
|
||||
newBoxType = fir::ReferenceType::get(newBoxType);
|
||||
newBoxType = fir::ReferenceType::get(
|
||||
newBoxType, fir::isa_volatile_type(selector.getType()));
|
||||
// Give rank info to value via cast, and get rid of the box if not needed
|
||||
// (simple scalars, contiguous arrays... This is done by
|
||||
// translateVariableToExtendedValue).
|
||||
@ -5491,8 +5494,9 @@ private:
|
||||
// return, PassBy::AddressAndLength should be retired.
|
||||
mlir::Location loc = toLocation();
|
||||
fir::factory::CharacterExprHelper charHelp{*builder, loc};
|
||||
mlir::Value box =
|
||||
charHelp.createEmboxChar(arg.firArgument, arg.firLength);
|
||||
mlir::Value casted =
|
||||
builder->createVolatileCast(loc, false, arg.firArgument);
|
||||
mlir::Value box = charHelp.createEmboxChar(casted, arg.firLength);
|
||||
mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult);
|
||||
} else {
|
||||
if (arg.entity.has_value()) {
|
||||
|
@ -1111,10 +1111,7 @@ private:
|
||||
addMLIRAttr(fir::getContiguousAttrName());
|
||||
if (obj.attrs.test(Attrs::Value))
|
||||
isValueAttr = true; // TODO: do we want an mlir::Attribute as well?
|
||||
if (obj.attrs.test(Attrs::Volatile)) {
|
||||
TODO(loc, "VOLATILE in procedure interface");
|
||||
addMLIRAttr(fir::getVolatileAttrName());
|
||||
}
|
||||
|
||||
// obj.attrs.test(Attrs::Asynchronous) does not impact the way the argument
|
||||
// is passed given flang implement asynch IO synchronously. However, it's
|
||||
// added to determine whether the argument is captured.
|
||||
@ -1151,7 +1148,8 @@ private:
|
||||
|
||||
if (obj.attrs.test(Attrs::Allocatable) || obj.attrs.test(Attrs::Pointer)) {
|
||||
// Pass as fir.ref<fir.box> or fir.ref<fir.class>
|
||||
mlir::Type boxRefType = fir::ReferenceType::get(boxType);
|
||||
const bool isVolatile = obj.attrs.test(Attrs::Volatile);
|
||||
mlir::Type boxRefType = fir::ReferenceType::get(boxType, isVolatile);
|
||||
addFirOperand(boxRefType, nextPassedArgPosition(), Property::MutableBox,
|
||||
attrs);
|
||||
addPassedArg(PassEntityBy::MutableBox, entity, characteristics);
|
||||
|
@ -1369,7 +1369,10 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
|
||||
// it according to the interface.
|
||||
mlir::Value addr;
|
||||
if (mlir::isa<fir::BoxCharType>(dummyTypeWithActualRank)) {
|
||||
addr = hlfir::genVariableBoxChar(loc, builder, entity);
|
||||
// Cast the argument to match the volatility of the dummy argument.
|
||||
auto nonVolatileEntity = hlfir::Entity{builder.createVolatileCast(
|
||||
loc, fir::isa_volatile_type(dummyType), entity)};
|
||||
addr = hlfir::genVariableBoxChar(loc, builder, nonVolatileEntity);
|
||||
} else if (mlir::isa<fir::BaseBoxType>(dummyTypeWithActualRank)) {
|
||||
entity = hlfir::genVariableBox(loc, builder, entity);
|
||||
// Ensures the box has the right attributes and that it holds an
|
||||
|
@ -2705,7 +2705,7 @@ public:
|
||||
mlir::isa<fir::BoxCharType>(funcTy.getResult(0))) {
|
||||
auto boxTy =
|
||||
mlir::cast<fir::BoxCharType>(funcTy.getResult(0));
|
||||
mlir::Value ref = builder.createConvert(
|
||||
mlir::Value ref = builder.createConvertWithVolatileCast(
|
||||
loc, builder.getRefType(boxTy.getEleTy()), x.getAddr());
|
||||
auto len = builder.create<fir::UndefOp>(
|
||||
loc, builder.getCharacterLengthType());
|
||||
@ -6306,7 +6306,8 @@ private:
|
||||
mlir::Value buffi = computeCoordinate(buff, off);
|
||||
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
|
||||
builder, loc, memcpyType(), buffi, v.getAddr(), byteSz);
|
||||
createCallMemcpy(args, /*isVolatile=*/false);
|
||||
const bool isVolatile = fir::isa_volatile_type(v.getAddr().getType());
|
||||
createCallMemcpy(args, isVolatile);
|
||||
|
||||
// Save the incremented buffer position.
|
||||
builder.create<fir::StoreOp>(loc, endOff, buffPos);
|
||||
@ -6356,7 +6357,9 @@ private:
|
||||
mlir::Value buffi = computeCoordinate(buff, off);
|
||||
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
|
||||
builder, loc, memcpyType(), buffi, v.getAddr(), eleSz);
|
||||
createCallMemcpy(args, /*isVolatile=*/false);
|
||||
const bool isVolatile =
|
||||
fir::isa_volatile_type(v.getAddr().getType());
|
||||
createCallMemcpy(args, isVolatile);
|
||||
|
||||
builder.create<fir::StoreOp>(loc, plusOne, buffPos);
|
||||
}
|
||||
@ -7013,7 +7016,8 @@ private:
|
||||
components.resetExtendCoorRef();
|
||||
auto ptrEleTy = fir::PointerType::get(eleTy);
|
||||
auto ptrAddr = builder.createConvert(loc, ptrEleTy, addr);
|
||||
auto boxTy = fir::BoxType::get(ptrEleTy);
|
||||
auto boxTy = fir::BoxType::get(
|
||||
ptrEleTy, fir::isa_volatile_type(addr.getType()));
|
||||
// FIXME: The typeparams to the load may be different than those of
|
||||
// the subobject.
|
||||
if (components.hasExtendCoorRef())
|
||||
|
@ -204,6 +204,7 @@ private:
|
||||
!partInfo.resultShape)
|
||||
partInfo.resultShape =
|
||||
hlfir::genShape(getLoc(), getBuilder(), *partInfo.base);
|
||||
|
||||
// Dynamic type of polymorphic base must be kept if the designator is
|
||||
// polymorphic.
|
||||
if (isPolymorphic(designatorNode))
|
||||
@ -215,7 +216,25 @@ private:
|
||||
return fir::BoxCharType::get(charType.getContext(), charType.getFKind());
|
||||
|
||||
// When volatile is enabled, enable volatility on the designatory type.
|
||||
const bool isVolatile = false;
|
||||
bool isVolatile = false;
|
||||
|
||||
// Check if this should be a volatile reference
|
||||
if constexpr (std::is_same_v<std::decay_t<T>,
|
||||
Fortran::evaluate::SymbolRef>) {
|
||||
if (designatorNode.get().GetUltimate().attrs().test(
|
||||
Fortran::semantics::Attr::VOLATILE))
|
||||
isVolatile = true;
|
||||
} else if constexpr (std::is_same_v<std::decay_t<T>,
|
||||
Fortran::evaluate::ArrayRef>) {
|
||||
if (designatorNode.base().GetLastSymbol().attrs().test(
|
||||
Fortran::semantics::Attr::VOLATILE))
|
||||
isVolatile = true;
|
||||
} else if constexpr (std::is_same_v<std::decay_t<T>,
|
||||
Fortran::evaluate::Component>) {
|
||||
if (designatorNode.GetLastSymbol().attrs().test(
|
||||
Fortran::semantics::Attr::VOLATILE))
|
||||
isVolatile = true;
|
||||
}
|
||||
|
||||
// Arrays with non default lower bounds or dynamic length or dynamic extent
|
||||
// need a fir.box to hold the dynamic or lower bound information.
|
||||
@ -230,6 +249,12 @@ private:
|
||||
/*namedConstantSectionsAreAlwaysContiguous=*/false))
|
||||
return fir::BoxType::get(resultValueType, isVolatile);
|
||||
|
||||
// Check if the base type is volatile
|
||||
if (partInfo.base.has_value()) {
|
||||
mlir::Type baseType = partInfo.base.value().getType();
|
||||
isVolatile = fir::isa_volatile_type(baseType);
|
||||
}
|
||||
|
||||
// Other designators can be handled as raw addresses.
|
||||
return fir::ReferenceType::get(resultValueType, isVolatile);
|
||||
}
|
||||
@ -441,7 +466,10 @@ private:
|
||||
// hlfir.designate result will be a pointer/allocatable.
|
||||
PartInfo partInfo;
|
||||
mlir::Type componentType = visitComponentImpl(component, partInfo).second;
|
||||
mlir::Type designatorType = fir::ReferenceType::get(componentType);
|
||||
const auto isVolatile =
|
||||
fir::isa_volatile_type(partInfo.base.value().getBase().getType());
|
||||
mlir::Type designatorType =
|
||||
fir::ReferenceType::get(componentType, isVolatile);
|
||||
fir::FortranVariableFlagsAttr attributes =
|
||||
Fortran::lower::translateSymbolAttributes(getBuilder().getContext(),
|
||||
component.GetLastSymbol());
|
||||
|
@ -163,8 +163,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);
|
||||
}
|
||||
|
||||
|
@ -836,7 +836,11 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
|
||||
} else {
|
||||
mlir::Value itemAddr = fir::getBase(item);
|
||||
mlir::Type itemTy = fir::unwrapPassByRefType(itemAddr.getType());
|
||||
inputFuncArgs.push_back(builder.createConvert(loc, argType, itemAddr));
|
||||
|
||||
// Handle conversion between volatile and non-volatile reference types
|
||||
// Need to explicitly cast when volatility qualification differs
|
||||
inputFuncArgs.push_back(
|
||||
builder.createConvertWithVolatileCast(loc, argType, itemAddr));
|
||||
fir::factory::CharacterExprHelper charHelper{builder, loc};
|
||||
if (charHelper.isCharacterScalar(itemTy)) {
|
||||
mlir::Value len = fir::getLen(item);
|
||||
|
@ -271,7 +271,9 @@ fir::factory::CharacterExprHelper::createElementAddr(mlir::Value buffer,
|
||||
auto extent = fir::SequenceType::getUnknownExtent();
|
||||
if (charTy.getLen() != fir::CharacterType::unknownLen())
|
||||
extent = charTy.getLen();
|
||||
auto coorTy = builder.getRefType(fir::SequenceType::get({extent}, singleTy));
|
||||
const bool isVolatile = fir::isa_volatile_type(buffer.getType());
|
||||
auto sequenceType = fir::SequenceType::get({extent}, singleTy);
|
||||
auto coorTy = builder.getRefType(sequenceType, isVolatile);
|
||||
|
||||
auto coor = builder.createConvert(loc, coorTy, buffer);
|
||||
auto i = builder.createConvert(loc, builder.getIndexType(), index);
|
||||
@ -330,6 +332,8 @@ void fir::factory::CharacterExprHelper::createCopy(
|
||||
// If the src and dest are the same KIND, then use memmove to move the bits.
|
||||
// We don't have to worry about overlapping ranges with memmove.
|
||||
if (getCharacterKind(dest.getBuffer().getType()) == kind) {
|
||||
const bool isVolatile = fir::isa_volatile_type(fromBuff.getType()) ||
|
||||
fir::isa_volatile_type(toBuff.getType());
|
||||
auto bytes = builder.getKindMap().getCharacterBitsize(kind) / 8;
|
||||
auto i64Ty = builder.getI64Type();
|
||||
auto kindBytes = builder.createIntegerConstant(loc, i64Ty, bytes);
|
||||
@ -341,7 +345,7 @@ void fir::factory::CharacterExprHelper::createCopy(
|
||||
auto toPtr = builder.createConvert(loc, llvmPointerType, toBuff);
|
||||
auto fromPtr = builder.createConvert(loc, llvmPointerType, fromBuff);
|
||||
builder.create<mlir::LLVM::MemmoveOp>(loc, toPtr, fromPtr, totalBytes,
|
||||
/*isVolatile=*/false);
|
||||
isVolatile);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -615,8 +615,9 @@ mlir::Value fir::FirOpBuilder::createConvert(mlir::Location loc,
|
||||
void fir::FirOpBuilder::createStoreWithConvert(mlir::Location loc,
|
||||
mlir::Value val,
|
||||
mlir::Value addr) {
|
||||
mlir::Value cast =
|
||||
createConvert(loc, fir::unwrapRefType(addr.getType()), val);
|
||||
mlir::Type unwrapedRefType = fir::unwrapRefType(addr.getType());
|
||||
val = createVolatileCast(loc, fir::isa_volatile_type(unwrapedRefType), val);
|
||||
mlir::Value cast = createConvert(loc, unwrapedRefType, val);
|
||||
create<fir::StoreOp>(loc, cast, addr);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "flang/Optimizer/Builder/MutableBox.h"
|
||||
#include "flang/Optimizer/Builder/Runtime/Allocatable.h"
|
||||
#include "flang/Optimizer/Builder/Todo.h"
|
||||
#include "flang/Optimizer/Dialect/FIRType.h"
|
||||
#include "flang/Optimizer/HLFIR/HLFIROps.h"
|
||||
#include "mlir/IR/IRMapping.h"
|
||||
#include "mlir/Support/LLVM.h"
|
||||
|
@ -3556,7 +3556,9 @@ 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());
|
||||
const bool isVolatile =
|
||||
fir::isa_volatile_type(store.getMemref().getType()) ||
|
||||
fir::isa_volatile_type(store.getValue().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
|
||||
@ -3595,6 +3597,9 @@ struct CopyOpConversion : public fir::FIROpConversion<fir::CopyOp> {
|
||||
matchAndRewrite(fir::CopyOp copy, OpAdaptor adaptor,
|
||||
mlir::ConversionPatternRewriter &rewriter) const override {
|
||||
mlir::Location loc = copy.getLoc();
|
||||
const bool isVolatile =
|
||||
fir::isa_volatile_type(copy.getSource().getType()) ||
|
||||
fir::isa_volatile_type(copy.getDestination().getType());
|
||||
mlir::Value llvmSource = adaptor.getSource();
|
||||
mlir::Value llvmDestination = adaptor.getDestination();
|
||||
mlir::Type i64Ty = mlir::IntegerType::get(rewriter.getContext(), 64);
|
||||
@ -3605,10 +3610,10 @@ struct CopyOpConversion : public fir::FIROpConversion<fir::CopyOp> {
|
||||
mlir::LLVM::AliasAnalysisOpInterface newOp;
|
||||
if (copy.getNoOverlap())
|
||||
newOp = rewriter.create<mlir::LLVM::MemcpyOp>(
|
||||
loc, llvmDestination, llvmSource, copySize, /*isVolatile=*/false);
|
||||
loc, llvmDestination, llvmSource, copySize, isVolatile);
|
||||
else
|
||||
newOp = rewriter.create<mlir::LLVM::MemmoveOp>(
|
||||
loc, llvmDestination, llvmSource, copySize, /*isVolatile=*/false);
|
||||
loc, llvmDestination, llvmSource, copySize, isVolatile);
|
||||
|
||||
// TODO: propagate TBAA once FirAliasTagOpInterface added to CopyOp.
|
||||
attachTBAATag(newOp, copyTy, copyTy, nullptr);
|
||||
|
@ -1529,7 +1529,14 @@ bool fir::ConvertOp::canBeConverted(mlir::Type inType, mlir::Type outType) {
|
||||
llvm::LogicalResult fir::ConvertOp::verify() {
|
||||
mlir::Type inType = getValue().getType();
|
||||
mlir::Type outType = getType();
|
||||
if (fir::isa_volatile_type(inType) != fir::isa_volatile_type(outType))
|
||||
// If we're converting to an LLVM pointer type or an integer, we don't
|
||||
// need to check for volatility mismatch - volatility will be handled by the
|
||||
// memory operations themselves in llvm code generation and ptr-to-int can't
|
||||
// represent volatility.
|
||||
const bool toLLVMPointer = mlir::isa<mlir::LLVM::LLVMPointerType>(outType);
|
||||
const bool toInteger = fir::isa_integer(outType);
|
||||
if (fir::isa_volatile_type(inType) != fir::isa_volatile_type(outType) &&
|
||||
!toLLVMPointer && !toInteger)
|
||||
return emitOpError("cannot convert between volatile and non-volatile "
|
||||
"types, use fir.volatile_cast instead ")
|
||||
<< inType << " / " << outType;
|
||||
@ -1830,6 +1837,29 @@ llvm::LogicalResult fir::TypeInfoOp::verify() {
|
||||
// EmboxOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Conversions from reference types to box types must preserve volatility.
|
||||
static llvm::LogicalResult
|
||||
verifyEmboxOpVolatilityInvariants(mlir::Type memrefType,
|
||||
mlir::Type resultType) {
|
||||
mlir::Type boxElementType =
|
||||
llvm::TypeSwitch<mlir::Type, mlir::Type>(resultType)
|
||||
.Case<fir::BoxType, fir::ClassType>(
|
||||
[&](auto type) { return type.getEleTy(); })
|
||||
.Default([&](mlir::Type type) { return type; });
|
||||
|
||||
// If the embox is simply wrapping a non-volatile type into a volatile box,
|
||||
// we're not losing any volatility information.
|
||||
if (boxElementType == memrefType) {
|
||||
return mlir::success();
|
||||
}
|
||||
|
||||
// Otherwise, the volatility of the input and result must match.
|
||||
const bool volatilityMatches =
|
||||
fir::isa_volatile_type(memrefType) == fir::isa_volatile_type(resultType);
|
||||
|
||||
return mlir::success(volatilityMatches);
|
||||
}
|
||||
|
||||
llvm::LogicalResult fir::EmboxOp::verify() {
|
||||
auto eleTy = fir::dyn_cast_ptrEleTy(getMemref().getType());
|
||||
bool isArray = false;
|
||||
@ -1859,10 +1889,11 @@ llvm::LogicalResult fir::EmboxOp::verify() {
|
||||
return emitOpError("slice must not be provided for a scalar");
|
||||
if (getSourceBox() && !mlir::isa<fir::ClassType>(getResult().getType()))
|
||||
return emitOpError("source_box must be used with fir.class result type");
|
||||
if (fir::isa_volatile_type(getMemref().getType()) !=
|
||||
fir::isa_volatile_type(getResult().getType()))
|
||||
return emitOpError("cannot convert between volatile and non-volatile "
|
||||
"types, use fir.volatile_cast instead");
|
||||
if (failed(verifyEmboxOpVolatilityInvariants(getMemref().getType(),
|
||||
getResult().getType())))
|
||||
return emitOpError(
|
||||
"cannot convert between volatile and non-volatile types:")
|
||||
<< " " << getMemref().getType() << " " << getResult().getType();
|
||||
return mlir::success();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mlir/IR/BuiltinDialect.h"
|
||||
#include "mlir/IR/Diagnostics.h"
|
||||
#include "mlir/IR/DialectImplementation.h"
|
||||
#include "mlir/Support/LLVM.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/ADT/TypeSwitch.h"
|
||||
@ -32,21 +33,6 @@ using namespace fir;
|
||||
|
||||
namespace {
|
||||
|
||||
static llvm::StringRef getVolatileKeyword() { return "volatile"; }
|
||||
|
||||
static mlir::ParseResult parseOptionalCommaAndKeyword(mlir::AsmParser &parser,
|
||||
mlir::StringRef keyword,
|
||||
bool &parsedKeyword) {
|
||||
if (!parser.parseOptionalComma()) {
|
||||
if (parser.parseKeyword(keyword))
|
||||
return mlir::failure();
|
||||
parsedKeyword = true;
|
||||
return mlir::success();
|
||||
}
|
||||
parsedKeyword = false;
|
||||
return mlir::success();
|
||||
}
|
||||
|
||||
template <typename TYPE>
|
||||
TYPE parseIntSingleton(mlir::AsmParser &parser) {
|
||||
int kind = 0;
|
||||
@ -91,6 +77,21 @@ bool verifySameLists(llvm::ArrayRef<RecordType::TypePair> a1,
|
||||
return a1 == a2;
|
||||
}
|
||||
|
||||
static llvm::StringRef getVolatileKeyword() { return "volatile"; }
|
||||
|
||||
static mlir::ParseResult parseOptionalCommaAndKeyword(mlir::AsmParser &parser,
|
||||
mlir::StringRef keyword,
|
||||
bool &parsedKeyword) {
|
||||
if (!parser.parseOptionalComma()) {
|
||||
if (parser.parseKeyword(keyword))
|
||||
return mlir::failure();
|
||||
parsedKeyword = true;
|
||||
return mlir::success();
|
||||
}
|
||||
parsedKeyword = false;
|
||||
return mlir::success();
|
||||
}
|
||||
|
||||
RecordType verifyDerived(mlir::AsmParser &parser, RecordType derivedTy,
|
||||
llvm::ArrayRef<RecordType::TypePair> lenPList,
|
||||
llvm::ArrayRef<RecordType::TypePair> typeList) {
|
||||
@ -1419,8 +1420,13 @@ changeTypeShape(mlir::Type type,
|
||||
return fir::SequenceType::get(*newShape, seqTy.getEleTy());
|
||||
return seqTy.getEleTy();
|
||||
})
|
||||
.Case<fir::PointerType, fir::HeapType, fir::ReferenceType, fir::BoxType,
|
||||
fir::ClassType>([&](auto t) -> mlir::Type {
|
||||
.Case<fir::ReferenceType, fir::BoxType, fir::ClassType>(
|
||||
[&](auto t) -> mlir::Type {
|
||||
using FIRT = decltype(t);
|
||||
return FIRT::get(changeTypeShape(t.getEleTy(), newShape),
|
||||
t.isVolatile());
|
||||
})
|
||||
.Case<fir::PointerType, fir::HeapType>([&](auto t) -> mlir::Type {
|
||||
using FIRT = decltype(t);
|
||||
return FIRT::get(changeTypeShape(t.getEleTy(), newShape));
|
||||
})
|
||||
|
@ -61,6 +61,7 @@ getIntrinsicEffects(mlir::Operation *self,
|
||||
// }
|
||||
for (mlir::OpOperand &operand : self->getOpOperands()) {
|
||||
mlir::Type opTy = operand.get().getType();
|
||||
fir::addVolatileMemoryEffects({opTy}, effects);
|
||||
if (fir::isa_ref_type(opTy) || fir::isa_box_type(opTy))
|
||||
effects.emplace_back(mlir::MemoryEffects::Read::get(), &operand,
|
||||
mlir::SideEffects::DefaultResource::get());
|
||||
@ -95,7 +96,7 @@ static llvm::LogicalResult areMatchingTypes(Op &op, mlir::Type type1,
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DeclareOp
|
||||
// AssignOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Is this a fir.[ref/ptr/heap]<fir.[box/class]<fir.heap<T>>> type?
|
||||
@ -164,6 +165,8 @@ void hlfir::AssignOp::getEffects(
|
||||
}
|
||||
}
|
||||
|
||||
fir::addVolatileMemoryEffects({lhsType, rhsType}, effects);
|
||||
|
||||
if (getRealloc()) {
|
||||
// Reallocation of the data cannot be precisely described by this API.
|
||||
effects.emplace_back(mlir::MemoryEffects::Free::get(),
|
||||
@ -204,6 +207,34 @@ static bool hasExplicitLowerBounds(mlir::Value shape) {
|
||||
mlir::isa<fir::ShapeShiftType, fir::ShiftType>(shape.getType());
|
||||
}
|
||||
|
||||
static std::pair<mlir::Type, mlir::Value> updateDeclareInputTypeWithVolatility(
|
||||
mlir::Type inputType, mlir::Value memref, mlir::OpBuilder &builder,
|
||||
fir::FortranVariableFlagsAttr fortran_attrs) {
|
||||
if (mlir::isa<fir::BoxType, fir::ReferenceType>(inputType) && fortran_attrs &&
|
||||
bitEnumContainsAny(fortran_attrs.getFlags(),
|
||||
fir::FortranVariableFlagsEnum::fortran_volatile)) {
|
||||
const bool isPointer = bitEnumContainsAny(
|
||||
fortran_attrs.getFlags(), fir::FortranVariableFlagsEnum::pointer);
|
||||
auto updateType = [&](auto t) {
|
||||
using FIRT = decltype(t);
|
||||
// If an entity is a pointer, the entity it points to is volatile, as far
|
||||
// as consumers of the pointer are concerned.
|
||||
auto elementType = t.getEleTy();
|
||||
const bool elementTypeIsVolatile =
|
||||
isPointer || fir::isa_volatile_type(elementType);
|
||||
auto newEleTy =
|
||||
fir::updateTypeWithVolatility(elementType, elementTypeIsVolatile);
|
||||
inputType = FIRT::get(newEleTy, true);
|
||||
};
|
||||
llvm::TypeSwitch<mlir::Type>(inputType)
|
||||
.Case<fir::ReferenceType, fir::BoxType>(updateType)
|
||||
.Default([](mlir::Type t) { return t; });
|
||||
memref =
|
||||
builder.create<fir::VolatileCastOp>(memref.getLoc(), inputType, memref);
|
||||
}
|
||||
return std::make_pair(inputType, memref);
|
||||
}
|
||||
|
||||
void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
|
||||
mlir::OperationState &result, mlir::Value memref,
|
||||
llvm::StringRef uniq_name, mlir::Value shape,
|
||||
@ -214,6 +245,8 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
|
||||
auto nameAttr = builder.getStringAttr(uniq_name);
|
||||
mlir::Type inputType = memref.getType();
|
||||
bool hasExplicitLbs = hasExplicitLowerBounds(shape);
|
||||
std::tie(inputType, memref) = updateDeclareInputTypeWithVolatility(
|
||||
inputType, memref, builder, fortran_attrs);
|
||||
mlir::Type hlfirVariableType =
|
||||
getHLFIRVariableType(inputType, hasExplicitLbs);
|
||||
build(builder, result, {hlfirVariableType, inputType}, memref, shape,
|
||||
@ -390,6 +423,12 @@ llvm::LogicalResult hlfir::DesignateOp::verify() {
|
||||
unsigned outputRank = 0;
|
||||
mlir::Type outputElementType;
|
||||
bool hasBoxComponent;
|
||||
if (fir::isa_volatile_type(memrefType) !=
|
||||
fir::isa_volatile_type(getResult().getType())) {
|
||||
return emitOpError("volatility mismatch between memref and result type")
|
||||
<< " memref type: " << memrefType
|
||||
<< " result type: " << getResult().getType();
|
||||
}
|
||||
if (getComponent()) {
|
||||
auto component = getComponent().value();
|
||||
auto recType = mlir::dyn_cast<fir::RecordType>(baseElementType);
|
||||
|
@ -421,6 +421,7 @@ class DesignateOpConversion
|
||||
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);
|
||||
@ -443,10 +444,11 @@ 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);
|
||||
const bool isVolatile = fir::isa_volatile_type(designateResultType) ||
|
||||
fir::isa_volatile_type(base.getType());
|
||||
mlir::Type baseEleTy = hlfir::getFortranElementType(base.getType());
|
||||
mlir::Type resultEleTy = hlfir::getFortranElementType(designateResultType);
|
||||
|
||||
@ -468,6 +470,7 @@ public:
|
||||
mlir::cast<fir::RecordType>(baseEleTy).getType(
|
||||
designate.getComponent().value());
|
||||
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>(
|
||||
@ -566,15 +569,19 @@ public:
|
||||
builder.create<fir::SliceOp>(loc, triples, sliceFields, substring);
|
||||
else
|
||||
assert(sliceFields.empty() && substring.empty());
|
||||
llvm::SmallVector<mlir::Type> resultType{designateResultType};
|
||||
|
||||
llvm::SmallVector<mlir::Type> resultType{
|
||||
fir::updateTypeWithVolatility(designateResultType, isVolatile)};
|
||||
|
||||
mlir::Value resultBox;
|
||||
if (mlir::isa<fir::BaseBoxType>(base.getType()))
|
||||
if (mlir::isa<fir::BaseBoxType>(base.getType())) {
|
||||
resultBox =
|
||||
builder.create<fir::ReboxOp>(loc, resultType, base, shape, slice);
|
||||
else
|
||||
} else {
|
||||
resultBox =
|
||||
builder.create<fir::EmboxOp>(loc, resultType, base, shape, slice,
|
||||
firBaseTypeParameters, sourceBox);
|
||||
}
|
||||
rewriter.replaceOp(designate, resultBox);
|
||||
return mlir::success();
|
||||
}
|
||||
@ -585,7 +592,8 @@ public:
|
||||
mlir::Type resultAddressType = designateResultType;
|
||||
if (auto boxCharType =
|
||||
mlir::dyn_cast<fir::BoxCharType>(designateResultType))
|
||||
resultAddressType = fir::ReferenceType::get(boxCharType.getEleTy());
|
||||
resultAddressType =
|
||||
fir::ReferenceType::get(boxCharType.getEleTy(), isVolatile);
|
||||
|
||||
// Array element indexing.
|
||||
if (!designate.getIndices().empty()) {
|
||||
@ -609,7 +617,8 @@ public:
|
||||
assert(!mlir::isa<fir::SequenceType>(designateResultType));
|
||||
auto index = builder.createIntegerConstant(loc, builder.getIndexType(),
|
||||
*designate.getComplexPart());
|
||||
auto coorTy = fir::ReferenceType::get(resultEleTy);
|
||||
auto coorTy = fir::ReferenceType::get(resultEleTy, isVolatile);
|
||||
|
||||
base = builder.create<fir::CoordinateOp>(loc, coorTy, base, index);
|
||||
}
|
||||
|
||||
@ -619,9 +628,11 @@ public:
|
||||
"must have character length");
|
||||
auto emboxChar = builder.create<fir::EmboxCharOp>(
|
||||
loc, designateResultType, base, designate.getTypeparams()[0]);
|
||||
|
||||
rewriter.replaceOp(designate, emboxChar.getResult());
|
||||
} else {
|
||||
base = builder.createConvert(loc, designateResultType, base);
|
||||
|
||||
rewriter.replaceOp(designate, base);
|
||||
}
|
||||
return mlir::success();
|
||||
|
@ -75,3 +75,39 @@ func.func @fun(%arg0: !fir.ref<i64, volatile>) -> i64 {
|
||||
// CHECK: fir.store %[[VAL_3]] to %arg0 : !fir.ref<i64, volatile>
|
||||
// CHECK: return %[[VAL_3]] : i64
|
||||
// CHECK: }
|
||||
|
||||
// -----
|
||||
|
||||
// Check that volatile hlfir assignments are PRESERVED.
|
||||
func.func @_QPdot_product2(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "lhs"}, %arg1: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "rhs"}, %arg2: !fir.ref<!fir.logical<4>> {fir.bindc_name = "res"}) {
|
||||
%0 = fir.dummy_scope : !fir.dscope
|
||||
%1 = fir.volatile_cast %arg0 : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<!fir.array<?x!fir.logical<4>>, volatile>
|
||||
%2:2 = hlfir.declare %1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFdot_product2Elhs"} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>)
|
||||
%3 = fir.volatile_cast %arg2 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>, volatile>
|
||||
%4:2 = hlfir.declare %3 dummy_scope %0 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFdot_product2Eres"} : (!fir.ref<!fir.logical<4>, volatile>, !fir.dscope) -> (!fir.ref<!fir.logical<4>, volatile>, !fir.ref<!fir.logical<4>, volatile>)
|
||||
%5 = fir.volatile_cast %arg1 : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<!fir.array<?x!fir.logical<4>>, volatile>
|
||||
%6:2 = hlfir.declare %5 dummy_scope %0 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFdot_product2Erhs"} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>)
|
||||
%7 = hlfir.dot_product %2#0 %6#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>) -> !fir.logical<4>
|
||||
hlfir.assign %7 to %4#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
|
||||
%8 = hlfir.dot_product %2#0 %6#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>) -> !fir.logical<4>
|
||||
hlfir.assign %8 to %4#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func.func @_QPdot_product2(
|
||||
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "lhs"},
|
||||
// CHECK-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "rhs"},
|
||||
// CHECK-SAME: %[[VAL_2:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "res"}) {
|
||||
// CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
// CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<!fir.array<?x!fir.logical<4>>, volatile>
|
||||
// CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFdot_product2Elhs"} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>)
|
||||
// CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFdot_product2Eres"} : (!fir.ref<!fir.logical<4>, volatile>, !fir.dscope) -> (!fir.ref<!fir.logical<4>, volatile>, !fir.ref<!fir.logical<4>, volatile>)
|
||||
// CHECK: %[[VAL_8:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> !fir.box<!fir.array<?x!fir.logical<4>>, volatile>
|
||||
// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFdot_product2Erhs"} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>)
|
||||
// CHECK: %[[VAL_10:.*]] = hlfir.dot_product %[[VAL_5]]#0 %[[VAL_9]]#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>) -> !fir.logical<4>
|
||||
// CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: %[[VAL_11:.*]] = hlfir.dot_product %[[VAL_5]]#0 %[[VAL_9]]#0 {fastmath = #arith.fastmath<contract>} : (!fir.box<!fir.array<?x!fir.logical<4>>, volatile>, !fir.box<!fir.array<?x!fir.logical<4>>, volatile>) -> !fir.logical<4>
|
||||
// CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: return
|
||||
// CHECK: }
|
||||
|
18
flang/test/Fir/volatile.fir
Normal file
18
flang/test/Fir/volatile.fir
Normal file
@ -0,0 +1,18 @@
|
||||
// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s -o - | FileCheck %s
|
||||
// CHECK: llvm.store volatile %{{.+}}, %{{.+}} : i32, !llvm.ptr
|
||||
// CHECK: %{{.+}} = llvm.load volatile %{{.+}} : !llvm.ptr -> i32
|
||||
func.func @foo() {
|
||||
%true = arith.constant true
|
||||
%false = arith.constant false
|
||||
%0 = fir.alloca !fir.logical<4> {bindc_name = "a", uniq_name = "_QFEa"}
|
||||
%1 = fir.volatile_cast %0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>, volatile>
|
||||
%2 = fir.alloca !fir.logical<4> {bindc_name = "b", uniq_name = "_QFEb"}
|
||||
%3 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
|
||||
%4 = fir.convert %false : (i1) -> !fir.logical<4>
|
||||
fir.store %4 to %1 : !fir.ref<!fir.logical<4>, volatile>
|
||||
%5 = fir.load %1 : !fir.ref<!fir.logical<4>, volatile>
|
||||
fir.store %5 to %2 : !fir.ref<!fir.logical<4>>
|
||||
%6 = fir.convert %true : (i1) -> !fir.logical<4>
|
||||
fir.store %6 to %1 : !fir.ref<!fir.logical<4>, volatile>
|
||||
return
|
||||
}
|
54
flang/test/Fir/volatile2.fir
Normal file
54
flang/test/Fir/volatile2.fir
Normal file
@ -0,0 +1,54 @@
|
||||
// RUN: fir-opt --fir-to-llvm-ir %s | FileCheck %s
|
||||
func.func @_QQmain() {
|
||||
%0 = fir.alloca !fir.box<!fir.array<10xi32>, volatile>
|
||||
%c1 = arith.constant 1 : index
|
||||
%c5_i32 = arith.constant 5 : i32
|
||||
%c10 = arith.constant 10 : index
|
||||
%1 = fir.address_of(@_QFEa) : !fir.ref<!fir.array<10xi32>>
|
||||
%2 = fir.volatile_cast %1 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
%3 = fir.address_of(@_QFEb) : !fir.ref<!fir.array<10xi32>>
|
||||
%4 = fir.volatile_cast %3 : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
%5 = arith.subi %c10, %c1 : index
|
||||
%6 = arith.addi %5, %c1 : index
|
||||
%7 = arith.divsi %6, %c1 : index
|
||||
cf.br ^bb1(%c1, %7 : index, index)
|
||||
^bb1(%8: index, %9: index): // 2 preds: ^bb0, ^bb2
|
||||
%c0 = arith.constant 0 : index
|
||||
%10 = arith.cmpi sgt, %9, %c0 : index
|
||||
cf.cond_br %10, ^bb2, ^bb3
|
||||
^bb2: // pred: ^bb1
|
||||
%11 = fircg.ext_array_coor %4(%c10)<%8> : (!fir.ref<!fir.array<10xi32>, volatile>, index, index) -> !fir.ref<i32, volatile>
|
||||
fir.store %c5_i32 to %11 : !fir.ref<i32, volatile>
|
||||
%12 = arith.addi %8, %c1 overflow<nsw> : index
|
||||
%c1_0 = arith.constant 1 : index
|
||||
%13 = arith.subi %9, %c1_0 : index
|
||||
cf.br ^bb1(%12, %13 : index, index)
|
||||
^bb3: // pred: ^bb1
|
||||
%14 = fircg.ext_embox %4(%c10) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.box<!fir.array<10xi32>, volatile>
|
||||
%15 = fircg.ext_embox %2(%c10) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.box<!fir.array<10xi32>, volatile>
|
||||
fir.store %15 to %0 : !fir.ref<!fir.box<!fir.array<10xi32>, volatile>>
|
||||
%16 = fir.address_of(@_QQclX8b2af12247fe2a74a66d92bb35ca5038) : !fir.ref<!fir.char<1,13>>
|
||||
%c3_i32 = arith.constant 3 : i32
|
||||
%17 = fir.convert %0 : (!fir.ref<!fir.box<!fir.array<10xi32>, volatile>>) -> !fir.ref<!fir.box<none>>
|
||||
%18 = fir.volatile_cast %14 : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
|
||||
%19 = fir.convert %18 : (!fir.box<!fir.array<10xi32>>) -> !fir.box<none>
|
||||
%20 = fir.convert %16 : (!fir.ref<!fir.char<1,13>>) -> !fir.ref<i8>
|
||||
fir.call @_FortranAAssign(%17, %19, %20, %c3_i32) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
|
||||
return
|
||||
}
|
||||
fir.global internal @_QFEa : !fir.array<10xi32> {
|
||||
%0 = fir.zero_bits !fir.array<10xi32>
|
||||
fir.has_value %0 : !fir.array<10xi32>
|
||||
}
|
||||
fir.global internal @_QFEb : !fir.array<10xi32> {
|
||||
%0 = fir.zero_bits !fir.array<10xi32>
|
||||
fir.has_value %0 : !fir.array<10xi32>
|
||||
}
|
||||
func.func private @_FortranAAssign(!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) attributes {fir.runtime}
|
||||
fir.global linkonce @_QQclX8b2af12247fe2a74a66d92bb35ca5038 constant : !fir.char<1,13> {
|
||||
%0 = fir.string_lit "filename.f90\00"(13) : !fir.char<1,13>
|
||||
fir.has_value %0 : !fir.char<1,13>
|
||||
}
|
||||
// CHECK-LABEL: llvm.func @_QQmain() {
|
||||
// CHECK: llvm.store volatile %{{.+}}, %{{.+}} : i32, !llvm.ptr
|
||||
// CHECK: "llvm.intr.memcpy"(%{{.+}}, %{{.+}}, %{{.+}}) <{isVolatile = true}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
|
86
flang/test/HLFIR/volatile.fir
Normal file
86
flang/test/HLFIR/volatile.fir
Normal file
@ -0,0 +1,86 @@
|
||||
// RUN: fir-opt --convert-hlfir-to-fir %s -o - | FileCheck %s
|
||||
|
||||
func.func @foo() {
|
||||
%true = arith.constant true
|
||||
%false = arith.constant false
|
||||
%0 = fir.alloca !fir.logical<4> {bindc_name = "a", uniq_name = "_QFEa"}
|
||||
%1 = fir.volatile_cast %0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>, volatile>
|
||||
%2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEa"} : (!fir.ref<!fir.logical<4>, volatile>) -> (!fir.ref<!fir.logical<4>, volatile>, !fir.ref<!fir.logical<4>, volatile>)
|
||||
%3 = fir.alloca !fir.logical<4> {bindc_name = "b", uniq_name = "_QFEb"}
|
||||
%4:2 = hlfir.declare %3 {uniq_name = "_QFEb"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
|
||||
%5 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
|
||||
%6:2 = hlfir.declare %5 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
||||
%7 = fir.convert %false : (i1) -> !fir.logical<4>
|
||||
hlfir.assign %7 to %2#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
|
||||
%8 = fir.load %2#0 : !fir.ref<!fir.logical<4>, volatile>
|
||||
hlfir.assign %8 to %4#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
|
||||
%9 = fir.convert %true : (i1) -> !fir.logical<4>
|
||||
hlfir.assign %9 to %2#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>, volatile>
|
||||
return
|
||||
}
|
||||
// CHECK-LABEL: func.func @foo() {
|
||||
// CHECK: %[[VAL_0:.*]] = arith.constant true
|
||||
// CHECK: %[[VAL_1:.*]] = arith.constant false
|
||||
// CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "a", uniq_name = "_QFEa"}
|
||||
// CHECK: %[[VAL_3:.*]] = fir.volatile_cast %[[VAL_2]] : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: %[[VAL_4:.*]] = fir.declare %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEa"} : (!fir.ref<!fir.logical<4>, volatile>) -> !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: %[[VAL_5:.*]] = fir.alloca !fir.logical<4> {bindc_name = "b", uniq_name = "_QFEb"}
|
||||
// CHECK: %[[VAL_6:.*]] = fir.declare %[[VAL_5]] {uniq_name = "_QFEb"} : (!fir.ref<!fir.logical<4>>) -> !fir.ref<!fir.logical<4>>
|
||||
// CHECK: %[[VAL_7:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
|
||||
// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
|
||||
// CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4>
|
||||
// CHECK: fir.store %[[VAL_9]] to %[[VAL_4]] : !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]] : !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: fir.store %[[VAL_10]] to %[[VAL_6]] : !fir.ref<!fir.logical<4>>
|
||||
// CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_0]] : (i1) -> !fir.logical<4>
|
||||
// CHECK: fir.store %[[VAL_11]] to %[[VAL_4]] : !fir.ref<!fir.logical<4>, volatile>
|
||||
// CHECK: return
|
||||
// CHECK: }
|
||||
|
||||
// -----
|
||||
|
||||
func.func private @_QFPassign_different_length(%arg0: !fir.boxchar<1> {fir.bindc_name = "string"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
|
||||
%c2 = arith.constant 2 : index
|
||||
%c3 = arith.constant 3 : index
|
||||
%0 = fir.dummy_scope : !fir.dscope
|
||||
%1:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%2 = fir.convert %1#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,3>>
|
||||
%3 = fir.volatile_cast %2 : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile>
|
||||
%4:2 = hlfir.declare %3 typeparams %c3 dummy_scope %0 {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_different_lengthEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>)
|
||||
%5 = fir.address_of(@_QQclX626F) : !fir.ref<!fir.char<1,2>>
|
||||
%6:2 = hlfir.declare %5 typeparams %c2 {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX626F"} : (!fir.ref<!fir.char<1,2>>, index) -> (!fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,2>>)
|
||||
hlfir.assign %6#0 to %4#0 : !fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,3>, volatile>
|
||||
return
|
||||
}
|
||||
// CHECK-LABEL: func.func private @_QFPassign_different_length(
|
||||
// CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "string"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
|
||||
// CHECK: %[[VAL_1:.*]] = arith.constant 2 : index
|
||||
// CHECK: %[[VAL_2:.*]] = arith.constant 3 : index
|
||||
// CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
// CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,3>>
|
||||
// CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile>
|
||||
// CHECK: %[[VAL_7:.*]] = fir.declare %[[VAL_6]] typeparams %[[VAL_2]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_different_lengthEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> !fir.ref<!fir.char<1,3>, volatile>
|
||||
// CHECK: %[[VAL_8:.*]] = fir.address_of(@_QQclX626F) : !fir.ref<!fir.char<1,2>>
|
||||
// CHECK: %[[VAL_9:.*]] = fir.declare %[[VAL_8]] typeparams %[[VAL_1]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX626F"} : (!fir.ref<!fir.char<1,2>>, index) -> !fir.ref<!fir.char<1,2>>
|
||||
// CHECK: %[[VAL_10:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_1]] : index
|
||||
// CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_10]], %[[VAL_2]], %[[VAL_1]] : index
|
||||
// CHECK: %[[VAL_12:.*]] = arith.constant 1 : i64
|
||||
// CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_11]] : (index) -> i64
|
||||
// CHECK: %[[VAL_14:.*]] = arith.muli %[[VAL_12]], %[[VAL_13]] : i64
|
||||
// CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<!fir.char<1,3>, volatile>) -> !llvm.ptr
|
||||
// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.char<1,2>>) -> !llvm.ptr
|
||||
// CHECK: "llvm.intr.memmove"(%[[VAL_15]], %[[VAL_16]], %[[VAL_14]]) <{isVolatile = true}> : (!llvm.ptr, !llvm.ptr, i64) -> ()
|
||||
// CHECK: %[[VAL_17:.*]] = arith.constant 1 : index
|
||||
// CHECK: %[[VAL_18:.*]] = arith.subi %[[VAL_2]], %[[VAL_17]] : index
|
||||
// CHECK: %[[VAL_19:.*]] = arith.constant 32 : i8
|
||||
// CHECK: %[[VAL_20:.*]] = fir.undefined !fir.char<1>
|
||||
// CHECK: %[[VAL_21:.*]] = fir.insert_value %[[VAL_20]], %[[VAL_19]], [0 : index] : (!fir.char<1>, i8) -> !fir.char<1>
|
||||
// CHECK: %[[VAL_22:.*]] = arith.constant 1 : index
|
||||
// CHECK: fir.do_loop %[[VAL_23:.*]] = %[[VAL_11]] to %[[VAL_18]] step %[[VAL_22]] {
|
||||
// CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_7]] : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.ref<!fir.array<3x!fir.char<1>>, volatile>
|
||||
// CHECK: %[[VAL_25:.*]] = fir.coordinate_of %[[VAL_24]], %[[VAL_23]] : (!fir.ref<!fir.array<3x!fir.char<1>>, volatile>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: fir.store %[[VAL_21]] to %[[VAL_25]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: }
|
||||
// CHECK: return
|
||||
// CHECK: }
|
53
flang/test/Lower/volatile-openmp.f90
Normal file
53
flang/test/Lower/volatile-openmp.f90
Normal file
File diff suppressed because one or more lines are too long
116
flang/test/Lower/volatile-string.f90
Normal file
116
flang/test/Lower/volatile-string.f90
Normal file
@ -0,0 +1,116 @@
|
||||
! RUN: bbc %s -o - | FileCheck %s
|
||||
program p
|
||||
character(3), volatile :: string = 'foo'
|
||||
character(3) :: nonvolatile_string
|
||||
integer :: i
|
||||
call assign_same_length(string)
|
||||
call assign_different_length(string)
|
||||
i = index(string, 'o')
|
||||
i = len(string)
|
||||
string = adjustl(string)
|
||||
nonvolatile_string = trim(string)
|
||||
nonvolatile_string = string
|
||||
contains
|
||||
subroutine assign_same_length(x)
|
||||
character(3), intent(inout), volatile :: x
|
||||
x = 'bar'
|
||||
end subroutine
|
||||
subroutine assign_different_length(string)
|
||||
character(3), intent(inout), volatile :: string
|
||||
string = 'bo'
|
||||
end subroutine
|
||||
end program
|
||||
|
||||
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 11 : i32
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant true
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 10 : i32
|
||||
! CHECK: %[[VAL_4:.*]] = arith.constant 3 : i32
|
||||
! CHECK: %[[VAL_5:.*]] = arith.constant false
|
||||
! CHECK: %[[VAL_6:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index
|
||||
! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
|
||||
! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,3>>>
|
||||
! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
|
||||
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
||||
! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.char<1,3> {bindc_name = "nonvolatile_string", uniq_name = "_QFEnonvolatile_string"}
|
||||
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] typeparams %[[VAL_7]] {uniq_name = "_QFEnonvolatile_string"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
|
||||
! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFEstring) : !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile>
|
||||
! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] typeparams %[[VAL_7]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>)
|
||||
! CHECK: %[[VAL_17:.*]] = fir.volatile_cast %[[VAL_16]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_18:.*]] = fir.emboxchar %[[VAL_17]], %[[VAL_7]] : (!fir.ref<!fir.char<1,3>>, index) -> !fir.boxchar<1>
|
||||
! CHECK: fir.call @_QFPassign_same_length(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
|
||||
! CHECK: fir.call @_QFPassign_different_length(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
|
||||
! CHECK: %[[VAL_19:.*]] = fir.address_of(@_QQclX6F) : !fir.ref<!fir.char<1>>
|
||||
! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX6F"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
|
||||
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_17]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<i8>
|
||||
! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_7]] : (index) -> i64
|
||||
! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_20]]#0 : (!fir.ref<!fir.char<1>>) -> !fir.ref<i8>
|
||||
! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_6]] : (index) -> i64
|
||||
! CHECK: %[[VAL_25:.*]] = fir.call @_FortranAIndex1(%[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_5]]) fastmath<contract> : (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i1) -> i64
|
||||
! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i64) -> i32
|
||||
! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_11]]#0 : i32, !fir.ref<i32>
|
||||
! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_11]]#0 : i32, !fir.ref<i32>
|
||||
! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_16]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>, volatile>
|
||||
! CHECK: %[[VAL_28:.*]] = fir.zero_bits !fir.heap<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_29:.*]] = fir.embox %[[VAL_28]] : (!fir.heap<!fir.char<1,3>>) -> !fir.box<!fir.heap<!fir.char<1,3>>>
|
||||
! CHECK: fir.store %[[VAL_29]] to %[[VAL_9]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>
|
||||
! CHECK: %[[VAL_30:.*]] = fir.address_of(
|
||||
! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>) -> !fir.ref<!fir.box<none>>
|
||||
! CHECK: %[[VAL_32:.*]] = fir.volatile_cast %[[VAL_27]] : (!fir.box<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (!fir.box<!fir.char<1,3>>) -> !fir.box<none>
|
||||
! CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_30]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
|
||||
! CHECK: fir.call @_FortranAAdjustl(%[[VAL_31]], %[[VAL_33]], %[[VAL_34]], %[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
|
||||
! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>
|
||||
! CHECK: %[[VAL_36:.*]] = fir.box_elesize %[[VAL_35]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> index
|
||||
! CHECK: %[[VAL_37:.*]] = fir.box_addr %[[VAL_35]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> !fir.heap<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_38:.*]]:2 = hlfir.declare %[[VAL_37]] typeparams %[[VAL_36]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,3>>, index) -> (!fir.heap<!fir.char<1,3>>, !fir.heap<!fir.char<1,3>>)
|
||||
! CHECK: %[[VAL_39:.*]] = hlfir.as_expr %[[VAL_38]]#0 move %[[VAL_2]] : (!fir.heap<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
|
||||
! CHECK: hlfir.assign %[[VAL_39]] to %[[VAL_16]]#0 : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>, volatile>
|
||||
! CHECK: hlfir.destroy %[[VAL_39]] : !hlfir.expr<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_40:.*]] = fir.zero_bits !fir.heap<!fir.char<1,?>>
|
||||
! CHECK: %[[VAL_41:.*]] = fir.embox %[[VAL_40]] typeparams %[[VAL_1]] : (!fir.heap<!fir.char<1,?>>, index) -> !fir.box<!fir.heap<!fir.char<1,?>>>
|
||||
! CHECK: fir.store %[[VAL_41]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
|
||||
! CHECK: %[[VAL_42:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>>
|
||||
! CHECK: fir.call @_FortranATrim(%[[VAL_42]], %[[VAL_33]], %[[VAL_34]], %[[VAL_0]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
|
||||
! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_8]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
|
||||
! CHECK: %[[VAL_44:.*]] = fir.box_elesize %[[VAL_43]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index
|
||||
! CHECK: %[[VAL_45:.*]] = fir.box_addr %[[VAL_43]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
|
||||
! CHECK: %[[VAL_46:.*]]:2 = hlfir.declare %[[VAL_45]] typeparams %[[VAL_44]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>)
|
||||
! CHECK: %[[VAL_47:.*]] = hlfir.as_expr %[[VAL_46]]#0 move %[[VAL_2]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
|
||||
! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_13]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: hlfir.destroy %[[VAL_47]] : !hlfir.expr<!fir.char<1,?>>
|
||||
! CHECK: hlfir.assign %[[VAL_16]]#0 to %[[VAL_13]]#0 : !fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPassign_same_length(
|
||||
! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index
|
||||
! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_5:.*]] = fir.volatile_cast %[[VAL_4]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile>
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_1]] dummy_scope %[[VAL_2]] {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_same_lengthEx"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.address_of(@_QQclX626172) : !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] typeparams %[[VAL_1]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX626172"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
|
||||
! CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_6]]#0 : !fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPassign_different_length(
|
||||
! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.boxchar<1> {fir.bindc_name = "string"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 2 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 3 : index
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,3>>
|
||||
! CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile>
|
||||
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] typeparams %[[VAL_2]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<intent_inout, volatile>, uniq_name = "_QFFassign_different_lengthEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>)
|
||||
! CHECK: %[[VAL_8:.*]] = fir.address_of(@_QQclX626F) : !fir.ref<!fir.char<1,2>>
|
||||
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_1]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX626F"} : (!fir.ref<!fir.char<1,2>>, index) -> (!fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,2>>)
|
||||
! CHECK: hlfir.assign %[[VAL_9]]#0 to %[[VAL_7]]#0 : !fir.ref<!fir.char<1,2>>, !fir.ref<!fir.char<1,3>, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
93
flang/test/Lower/volatile1.f90
Normal file
93
flang/test/Lower/volatile1.f90
Normal file
@ -0,0 +1,93 @@
|
||||
! RUN: bbc %s -o - | FileCheck %s
|
||||
|
||||
program p
|
||||
integer,volatile::i,arr(10)
|
||||
call not_declared_volatile_in_this_scope(i)
|
||||
call not_declared_volatile_in_this_scope(arr)
|
||||
call declared_volatile_in_this_scope(arr,10)
|
||||
print*,arr,i
|
||||
contains
|
||||
elemental subroutine not_declared_volatile_in_this_scope(v)
|
||||
integer,intent(inout)::v
|
||||
v=1
|
||||
end subroutine
|
||||
subroutine declared_volatile_in_this_scope(v,n)
|
||||
integer,intent(in)::n
|
||||
integer,volatile,intent(inout)::v(n)
|
||||
v=1
|
||||
end subroutine
|
||||
end program
|
||||
|
||||
|
||||
! CHECK-LABEL: func.func @_QQmain() attributes {{.+}} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 8 : i32
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 6 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 10 : i32
|
||||
! CHECK: %[[VAL_4:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_5:.*]] = arith.constant 10 : index
|
||||
! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.volatile_cast %[[VAL_6]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]](%[[VAL_7]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
|
||||
! CHECK: %[[VAL_11:.*]] = fir.volatile_cast %[[VAL_10]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]]#0 : (!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: cf.br ^bb1(%[[VAL_4]], %[[VAL_5]] : index, index)
|
||||
! CHECK: ^bb1(%[[VAL_14:.*]]: index, %[[VAL_15:.*]]: index):
|
||||
! CHECK: %[[VAL_16:.*]] = arith.cmpi sgt, %[[VAL_15]], %[[VAL_0]] : index
|
||||
! CHECK: cf.cond_br %[[VAL_16]], ^bb2, ^bb3
|
||||
! CHECK: ^bb2:
|
||||
! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_14]]) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_18:.*]] = fir.volatile_cast %[[VAL_17]] : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
|
||||
! CHECK: fir.call @_QFPnot_declared_volatile_in_this_scope(%[[VAL_18]]) proc_attrs<elemental, pure> fastmath<contract> : (!fir.ref<i32>) -> ()
|
||||
! CHECK: %[[VAL_19:.*]] = arith.addi %[[VAL_14]], %[[VAL_4]] overflow<nsw> : index
|
||||
! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_15]], %[[VAL_4]] : index
|
||||
! CHECK: cf.br ^bb1(%[[VAL_19]], %[[VAL_20]] : index, index)
|
||||
! CHECK: ^bb3:
|
||||
! CHECK: %[[VAL_21:.*]] = fir.volatile_cast %[[VAL_9]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_21]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<?xi32>>
|
||||
! CHECK: %[[VAL_23:.*]]:3 = hlfir.associate %[[VAL_3]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
|
||||
! CHECK: fir.call @_QFPdeclared_volatile_in_this_scope(%[[VAL_22]], %[[VAL_23]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) -> ()
|
||||
! CHECK: hlfir.end_associate %[[VAL_23]]#1, %[[VAL_23]]#2 : !fir.ref<i32>, i1
|
||||
! CHECK: %[[VAL_24:.*]] = fir.address_of
|
||||
! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
|
||||
! CHECK: %[[VAL_26:.*]] = fir.call @_FortranAioBeginExternalListOutput(%[[VAL_2]], %[[VAL_25]], %[[VAL_1]]) fastmath<contract> {{.+}} : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8>
|
||||
! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_9]]#0(%[[VAL_7]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_28:.*]] = fir.volatile_cast %[[VAL_27]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<none>
|
||||
! CHECK: %[[VAL_30:.*]] = fir.call @_FortranAioOutputDescriptor(%[[VAL_26]], %[[VAL_29]]) fastmath<contract> {llvm.nocallback, llvm.nosync} : (!fir.ref<i8>, !fir.box<none>) -> i1
|
||||
! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_32:.*]] = fir.call @_FortranAioOutputInteger32(%[[VAL_26]], %[[VAL_31]]) fastmath<contract> {{.+}} : (!fir.ref<i8>, i32) -> i1
|
||||
! CHECK: %[[VAL_33:.*]] = fir.call @_FortranAioEndIoStatement(%[[VAL_26]]) 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 {{.+}} {
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {{.+}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
|
||||
! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_3]]#0 : i32, !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 {{.+}} {
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_4]] {{.+}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
|
||||
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
|
||||
! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i32) -> index
|
||||
! CHECK: %[[VAL_8:.*]] = arith.cmpi sgt, %[[VAL_7]], %[[VAL_3]] : index
|
||||
! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_8]], %[[VAL_7]], %[[VAL_3]] : index
|
||||
! CHECK: %[[VAL_10:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_11:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>, volatile>
|
||||
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]](%[[VAL_10]]) dummy_scope %[[VAL_4]] {{.+}} : (!fir.ref<!fir.array<?xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.ref<!fir.array<?xi32>, volatile>)
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_12]]#0 : i32, !fir.box<!fir.array<?xi32>, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
63
flang/test/Lower/volatile2.f90
Normal file
63
flang/test/Lower/volatile2.f90
Normal file
@ -0,0 +1,63 @@
|
||||
! RUN: bbc %s -o - | FileCheck %s
|
||||
|
||||
program p
|
||||
print*,a(),b(),c()
|
||||
contains
|
||||
function a()
|
||||
integer,volatile::a
|
||||
a=1
|
||||
end function
|
||||
function b() result(r)
|
||||
integer,volatile::r
|
||||
r=2
|
||||
end function
|
||||
function c() result(r)
|
||||
volatile::r
|
||||
r=3
|
||||
end function
|
||||
end program
|
||||
|
||||
|
||||
! CHECK-LABEL: func.func @_QQmain() attributes {{.+}} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 4 : i32
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 6 : i32
|
||||
! CHECK: %[[VAL_2:.*]] = fir.address_of
|
||||
! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.char<1,{{.+}}>>) -> !fir.ref<i8>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.call @_QFPa() fastmath<contract> : () -> i32
|
||||
! CHECK: %[[VAL_5:.*]] = fir.call @_QFPb() fastmath<contract> : () -> i32
|
||||
! CHECK: %[[VAL_6:.*]] = fir.call @_QFPc() fastmath<contract> : () -> f32
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPa() -> i32 attributes {{.+}} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFFaEa"}
|
||||
! CHECK: %[[VAL_2:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_3]]#0 : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_3]]#0 : (!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 {{.+}} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 2 : i32
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "r", uniq_name = "_QFFbEr"}
|
||||
! CHECK: %[[VAL_2:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_3]]#0 : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_3]]#0 : (!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 {{.+}} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 3.000000e+00 : f32
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFFcEr"}
|
||||
! CHECK: %[[VAL_2:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<f32>) -> !fir.ref<f32, volatile>
|
||||
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {{.+}} : (!fir.ref<f32, volatile>) -> (!fir.ref<f32, volatile>, !fir.ref<f32, volatile>)
|
||||
! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_3]]#0 : f32, !fir.ref<f32, volatile>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_3]]#0 : (!fir.ref<f32, volatile>) -> !fir.ref<f32>
|
||||
! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref<f32>
|
||||
! CHECK: return %[[VAL_5]] : f32
|
||||
! CHECK: }
|
268
flang/test/Lower/volatile3.f90
Normal file
268
flang/test/Lower/volatile3.f90
Normal file
@ -0,0 +1,268 @@
|
||||
! RUN: bbc %s -o - | FileCheck %s
|
||||
|
||||
! Test that all combinations of volatile pointer and target are properly lowered -
|
||||
! note that a volatile pointer implies that the target is volatile, even if not specified
|
||||
|
||||
program p
|
||||
integer, volatile :: volatile_integer, volatile_array(10), &
|
||||
volatile_array_2d(10,10)
|
||||
integer, volatile, pointer :: volatile_integer_pointer
|
||||
integer :: nonvolatile_array(10)
|
||||
integer, volatile, target :: volatile_integer_target, volatile_array_target(10)
|
||||
integer, target :: nonvolatile_integer_target, nonvolatile_array_target(10)
|
||||
integer, volatile, &
|
||||
pointer, dimension(:) :: volatile_array_pointer
|
||||
integer, pointer, dimension(:) :: nonvolatile_array_pointer
|
||||
|
||||
volatile_array_pointer => volatile_array_target
|
||||
volatile_array_pointer => nonvolatile_array_target
|
||||
volatile_array_pointer => null(volatile_array_pointer)
|
||||
nonvolatile_array_pointer => volatile_array_target
|
||||
nonvolatile_array_pointer => nonvolatile_array_target
|
||||
volatile_integer_pointer => volatile_integer_target
|
||||
volatile_integer_pointer => null(volatile_integer_pointer)
|
||||
|
||||
call sub_nonvolatile_array(volatile_array)
|
||||
call sub_volatile_array_assumed_shape(volatile_array)
|
||||
call sub_volatile_array(volatile_array)
|
||||
|
||||
call sub_volatile_array_assumed_shape(nonvolatile_array)
|
||||
call sub_volatile_array(nonvolatile_array)
|
||||
|
||||
call sub_volatile_array_pointer(volatile_array_pointer)
|
||||
call sub_volatile_array_pointer(nonvolatile_array_pointer)
|
||||
|
||||
call sub_volatile_array_assumed_shape(volatile_array(1:10:1))
|
||||
call sub_volatile_array_assumed_shape_2d(volatile_array_2d(1:10:1,:))
|
||||
|
||||
call sub_select_rank(volatile_array)
|
||||
call sub_select_rank(volatile_array_2d)
|
||||
contains
|
||||
subroutine sub_nonvolatile_array(arr)
|
||||
integer :: arr(10)
|
||||
arr(1) = 5
|
||||
end subroutine
|
||||
subroutine sub_volatile_array_assumed_shape(arr)
|
||||
integer, volatile, dimension(:) :: arr
|
||||
arr(1) = 5
|
||||
end subroutine
|
||||
subroutine sub_volatile_array_assumed_shape_2d(arr)
|
||||
integer, volatile, dimension(:,:) :: arr
|
||||
arr(1,1) = 5
|
||||
end subroutine
|
||||
subroutine sub_volatile_array(arr)
|
||||
integer, volatile, dimension(10) :: arr
|
||||
arr(1) = 5
|
||||
end subroutine
|
||||
subroutine sub_volatile_array_pointer(arr)
|
||||
integer, volatile, dimension(:), pointer :: arr
|
||||
arr(1) = 5
|
||||
end subroutine
|
||||
subroutine sub_select_rank(arr)
|
||||
integer, volatile :: arr(..)
|
||||
select rank(arr)
|
||||
rank(1)
|
||||
arr(1) = 5
|
||||
rank(4)
|
||||
arr(1,1,1,1) = 5
|
||||
end select
|
||||
end subroutine
|
||||
end program
|
||||
|
||||
|
||||
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "p"} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
|
||||
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.ptr<i32>, volatile>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QFEnonvolatile_array) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_6]]) {uniq_name = "_QFEnonvolatile_array"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
|
||||
! CHECK: %[[VAL_8:.*]] = fir.address_of(@_QFEnonvolatile_array_pointer) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
|
||||
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEnonvolatile_array_pointer"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>)
|
||||
! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QFEnonvolatile_array_target) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_6]]) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEnonvolatile_array_target"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
|
||||
! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEnonvolatile_integer_target) : !fir.ref<i32>
|
||||
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFEnonvolatile_integer_target"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
||||
! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFEvolatile_array) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]](%[[VAL_6]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_array"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_17:.*]] = fir.address_of(@_QFEvolatile_array_2d) : !fir.ref<!fir.array<10x10xi32>>
|
||||
! CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_2]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
|
||||
! CHECK: %[[VAL_19:.*]] = fir.volatile_cast %[[VAL_17]] : (!fir.ref<!fir.array<10x10xi32>>) -> !fir.ref<!fir.array<10x10xi32>, volatile>
|
||||
! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]](%[[VAL_18]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_array_2d"} : (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.ref<!fir.array<10x10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_21:.*]] = fir.address_of(@_QFEvolatile_array_pointer) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
|
||||
! CHECK: %[[VAL_22:.*]] = fir.volatile_cast %[[VAL_21]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_23:.*]]:2 = hlfir.declare %[[VAL_22]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEvolatile_array_pointer"} : (!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>)
|
||||
! CHECK: %[[VAL_24:.*]] = fir.address_of(@_QFEvolatile_array_target) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_25:.*]] = fir.volatile_cast %[[VAL_24]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_25]](%[[VAL_6]]) {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEvolatile_array_target"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_27:.*]] = fir.alloca i32 {bindc_name = "volatile_integer", uniq_name = "_QFEvolatile_integer"}
|
||||
! CHECK: %[[VAL_28:.*]] = fir.volatile_cast %[[VAL_27]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_28]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEvolatile_integer"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: %[[VAL_30:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "volatile_integer_pointer", uniq_name = "_QFEvolatile_integer_pointer"}
|
||||
! CHECK: %[[VAL_31:.*]] = fir.zero_bits !fir.ptr<i32>
|
||||
! CHECK: %[[VAL_32:.*]] = fir.embox %[[VAL_31]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
|
||||
! CHECK: fir.store %[[VAL_32]] to %[[VAL_30]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
|
||||
! CHECK: %[[VAL_33:.*]] = fir.volatile_cast %[[VAL_30]] : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_34:.*]]:2 = hlfir.declare %[[VAL_33]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFEvolatile_integer_pointer"} : (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>) -> (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>, !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>)
|
||||
! CHECK: %[[VAL_35:.*]] = fir.address_of(@_QFEvolatile_integer_target) : !fir.ref<i32>
|
||||
! CHECK: %[[VAL_36:.*]] = fir.volatile_cast %[[VAL_35]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_36]] {fortran_attrs = #fir.var_attrs<target, volatile>, uniq_name = "_QFEvolatile_integer_target"} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: %[[VAL_38:.*]] = fir.embox %[[VAL_26]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: fir.store %[[VAL_38]] to %[[VAL_23]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_39:.*]] = fir.embox %[[VAL_11]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>>
|
||||
! CHECK: %[[VAL_40:.*]] = fir.volatile_cast %[[VAL_39]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: fir.store %[[VAL_40]] to %[[VAL_23]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_41:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>>
|
||||
! CHECK: %[[VAL_42:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_43:.*]] = fir.embox %[[VAL_41]](%[[VAL_42]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: fir.store %[[VAL_43]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>
|
||||
! CHECK: %[[VAL_44:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>)
|
||||
! CHECK: %[[VAL_45:.*]] = fir.load %[[VAL_44]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>>
|
||||
! CHECK: %[[VAL_46:.*]]:3 = fir.box_dims %[[VAL_45]], %[[VAL_1]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, index) -> (index, index, index)
|
||||
! CHECK: %[[VAL_47:.*]] = fir.shift %[[VAL_46]]#0 : (index) -> !fir.shift<1>
|
||||
! CHECK: %[[VAL_48:.*]] = fir.rebox %[[VAL_45]](%[[VAL_47]]) : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, !fir.shift<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: fir.store %[[VAL_48]] to %[[VAL_23]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_49:.*]] = fir.volatile_cast %[[VAL_38]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>>
|
||||
! CHECK: fir.store %[[VAL_49]] to %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
|
||||
! CHECK: fir.store %[[VAL_39]] to %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
|
||||
! CHECK: %[[VAL_50:.*]] = fir.embox %[[VAL_37]]#0 : (!fir.ref<i32, volatile>) -> !fir.box<!fir.ptr<i32>, volatile>
|
||||
! CHECK: fir.store %[[VAL_50]] to %[[VAL_34]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_51:.*]] = fir.embox %[[VAL_31]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>, volatile>
|
||||
! CHECK: fir.store %[[VAL_51]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>>
|
||||
! CHECK: %[[VAL_52:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>, volatile>>, !fir.ref<!fir.box<!fir.ptr<i32>, volatile>>)
|
||||
! CHECK: %[[VAL_53:.*]] = fir.load %[[VAL_52]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>>
|
||||
! CHECK: %[[VAL_54:.*]] = fir.box_addr %[[VAL_53]] : (!fir.box<!fir.ptr<i32>, volatile>) -> !fir.ptr<i32>
|
||||
! CHECK: %[[VAL_55:.*]] = fir.embox %[[VAL_54]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
|
||||
! CHECK: %[[VAL_56:.*]] = fir.volatile_cast %[[VAL_55]] : (!fir.box<!fir.ptr<i32>>) -> !fir.box<!fir.ptr<i32>, volatile>
|
||||
! CHECK: fir.store %[[VAL_56]] to %[[VAL_34]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_57:.*]] = fir.volatile_cast %[[VAL_16]]#0 : (!fir.ref<!fir.array<10xi32>, volatile>) -> !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: fir.call @_QFPsub_nonvolatile_array(%[[VAL_57]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
|
||||
! CHECK: %[[VAL_58:.*]] = fir.embox %[[VAL_16]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_59:.*]] = fir.volatile_cast %[[VAL_58]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_60:.*]] = fir.convert %[[VAL_59]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>>
|
||||
! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[VAL_60]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> ()
|
||||
! CHECK: fir.call @_QFPsub_volatile_array(%[[VAL_57]]) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
|
||||
! CHECK: %[[VAL_61:.*]] = fir.embox %[[VAL_7]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_62:.*]] = fir.convert %[[VAL_61]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>>
|
||||
! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[VAL_62]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> ()
|
||||
! CHECK: fir.call @_QFPsub_volatile_array(%[[VAL_7]]#0) fastmath<contract> : (!fir.ref<!fir.array<10xi32>>) -> ()
|
||||
! CHECK: %[[VAL_63:.*]] = fir.convert %[[VAL_23]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>
|
||||
! CHECK: fir.call @_QFPsub_volatile_array_pointer(%[[VAL_63]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> ()
|
||||
! CHECK: %[[VAL_64:.*]] = fir.volatile_cast %[[VAL_9]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>
|
||||
! CHECK: fir.call @_QFPsub_volatile_array_pointer(%[[VAL_64]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>, volatile>) -> ()
|
||||
! CHECK: %[[VAL_65:.*]] = hlfir.designate %[[VAL_16]]#0 (%[[VAL_0]]:%[[VAL_2]]:%[[VAL_0]]) shape %[[VAL_6]] : (!fir.ref<!fir.array<10xi32>, volatile>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_66:.*]] = fir.embox %[[VAL_65]](%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_67:.*]] = fir.volatile_cast %[[VAL_66]] : (!fir.box<!fir.array<10xi32>, volatile>) -> !fir.box<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_68:.*]] = fir.convert %[[VAL_67]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>>
|
||||
! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape(%[[VAL_68]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> ()
|
||||
! CHECK: %[[VAL_69:.*]] = hlfir.designate %[[VAL_20]]#0 (%[[VAL_0]]:%[[VAL_2]]:%[[VAL_0]], %[[VAL_0]]:%[[VAL_2]]:%[[VAL_0]]) shape %[[VAL_18]] : (!fir.ref<!fir.array<10x10xi32>, volatile>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>, volatile>
|
||||
! CHECK: %[[VAL_70:.*]] = fir.volatile_cast %[[VAL_69]] : (!fir.box<!fir.array<10x10xi32>, volatile>) -> !fir.box<!fir.array<10x10xi32>>
|
||||
! CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_70]] : (!fir.box<!fir.array<10x10xi32>>) -> !fir.box<!fir.array<?x?xi32>>
|
||||
! CHECK: fir.call @_QFPsub_volatile_array_assumed_shape_2d(%[[VAL_71]]) fastmath<contract> : (!fir.box<!fir.array<?x?xi32>>) -> ()
|
||||
! CHECK: %[[VAL_72:.*]] = fir.convert %[[VAL_59]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<*:i32>>
|
||||
! CHECK: fir.call @_QFPsub_select_rank(%[[VAL_72]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> ()
|
||||
! CHECK: %[[VAL_73:.*]] = fir.embox %[[VAL_20]]#0(%[[VAL_18]]) : (!fir.ref<!fir.array<10x10xi32>, volatile>, !fir.shape<2>) -> !fir.box<!fir.array<10x10xi32>, volatile>
|
||||
! CHECK: %[[VAL_74:.*]] = fir.volatile_cast %[[VAL_73]] : (!fir.box<!fir.array<10x10xi32>, volatile>) -> !fir.box<!fir.array<10x10xi32>>
|
||||
! CHECK: %[[VAL_75:.*]] = fir.convert %[[VAL_74]] : (!fir.box<!fir.array<10x10xi32>>) -> !fir.box<!fir.array<*:i32>>
|
||||
! CHECK: fir.call @_QFPsub_select_rank(%[[VAL_75]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> ()
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPsub_nonvolatile_array(
|
||||
! 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:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
|
||||
! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) dummy_scope %[[VAL_4]] {uniq_name = "_QFFsub_nonvolatile_arrayEarr"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
|
||||
! CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_1]]) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.ref<i32>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.ref<i32>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPsub_volatile_array_assumed_shape(
|
||||
! 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:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>, volatile>
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_array_assumed_shapeEarr"} : (!fir.box<!fir.array<?xi32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.box<!fir.array<?xi32>, volatile>)
|
||||
! CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_1]]) : (!fir.box<!fir.array<?xi32>, volatile>, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_6]] : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPsub_volatile_array_assumed_shape_2d(
|
||||
! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<!fir.array<?x?xi32>, volatile>
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_array_assumed_shape_2dEarr"} : (!fir.box<!fir.array<?x?xi32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<?x?xi32>, volatile>, !fir.box<!fir.array<?x?xi32>, volatile>)
|
||||
! CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_1]], %[[VAL_1]]) : (!fir.box<!fir.array<?x?xi32>, volatile>, index, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_6]] : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPsub_volatile_array(
|
||||
! 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:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
|
||||
! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_5]]) dummy_scope %[[VAL_4]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_volatile_arrayEarr"} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_1]]) : (!fir.ref<!fir.array<10xi32>, volatile>, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_8]] : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPsub_volatile_array_pointer(
|
||||
! 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:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]] = 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_5:.*]]:2 = hlfir.declare %[[VAL_4]] dummy_scope %[[VAL_3]] {fortran_attrs = #fir.var_attrs<pointer, volatile>, uniq_name = "_QFFsub_volatile_array_pointerEarr"} : (!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>)
|
||||
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_6]] (%[[VAL_1]]) : (!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: return
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: func.func private @_QFPsub_select_rank(
|
||||
! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<*:i32>> {fir.bindc_name = "arr"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 4 : i8
|
||||
! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i8
|
||||
! CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_6:.*]] = fir.volatile_cast %[[VAL_0]] : (!fir.box<!fir.array<*:i32>>) -> !fir.box<!fir.array<*:i32>, volatile>
|
||||
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %[[VAL_5]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<*:i32>, volatile>, !fir.dscope) -> (!fir.box<!fir.array<*:i32>, volatile>, !fir.box<!fir.array<*:i32>, volatile>)
|
||||
! CHECK: %[[VAL_8:.*]] = fir.volatile_cast %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<*:i32>>
|
||||
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.array<*:i32>>) -> !fir.box<none>
|
||||
! CHECK: %[[VAL_10:.*]] = fir.call @_FortranAIsAssumedSize(%[[VAL_9]]) : (!fir.box<none>) -> i1
|
||||
! CHECK: cf.cond_br %[[VAL_10]], ^bb4, ^bb1
|
||||
! CHECK: ^bb1:
|
||||
! CHECK: %[[VAL_11:.*]] = fir.box_rank %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> i8
|
||||
! CHECK: fir.select_case %[[VAL_11]] : i8 [#fir.point, %[[VAL_4]], ^bb2, #fir.point, %[[VAL_3]], ^bb3, unit, ^bb4]
|
||||
! CHECK: ^bb2:
|
||||
! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<?xi32>, volatile>
|
||||
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<?xi32>, volatile>) -> (!fir.box<!fir.array<?xi32>, volatile>, !fir.box<!fir.array<?xi32>, volatile>)
|
||||
! CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_13]]#0 (%[[VAL_1]]) : (!fir.box<!fir.array<?xi32>, volatile>, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_14]] : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: cf.br ^bb4
|
||||
! CHECK: ^bb3:
|
||||
! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.box<!fir.array<*:i32>, volatile>) -> !fir.box<!fir.array<?x?x?x?xi32>, volatile>
|
||||
! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFFsub_select_rankEarr"} : (!fir.box<!fir.array<?x?x?x?xi32>, volatile>) -> (!fir.box<!fir.array<?x?x?x?xi32>, volatile>, !fir.box<!fir.array<?x?x?x?xi32>, volatile>)
|
||||
! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_16]]#0 (%[[VAL_1]], %[[VAL_1]], %[[VAL_1]], %[[VAL_1]]) : (!fir.box<!fir.array<?x?x?x?xi32>, volatile>, index, index, index, index) -> !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_17]] : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: cf.br ^bb4
|
||||
! CHECK: ^bb4:
|
||||
! CHECK: return
|
||||
! CHECK: }
|
92
flang/test/Lower/volatile4.f90
Normal file
92
flang/test/Lower/volatile4.f90
Normal file
@ -0,0 +1,92 @@
|
||||
! RUN: bbc %s -o - | FileCheck %s
|
||||
|
||||
program p
|
||||
integer,volatile::i,arr(10)
|
||||
integer,volatile,target::tgt(10)
|
||||
integer,volatile,pointer,dimension(:)::ptr
|
||||
i = loc(i)
|
||||
ptr => tgt
|
||||
i=0
|
||||
arr=1
|
||||
call host_assoc
|
||||
contains
|
||||
subroutine host_assoc
|
||||
ptr => tgt
|
||||
i=0
|
||||
arr=1
|
||||
end subroutine
|
||||
end program
|
||||
|
||||
! CHECK-LABEL: func.func @_QQmain() attributes {{.+}} {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
|
||||
! CHECK: %[[VAL_3:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_5:.*]] = fir.volatile_cast %[[VAL_3]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_4]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
|
||||
! CHECK: %[[VAL_8:.*]] = fir.volatile_cast %[[VAL_7]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QFEptr) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
|
||||
! CHECK: %[[VAL_11:.*]] = fir.volatile_cast %[[VAL_10]] : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {{.+}} : (!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>)
|
||||
! CHECK: %[[VAL_13:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_14:.*]] = fir.volatile_cast %[[VAL_13]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]](%[[VAL_4]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_16:.*]] = fir.alloca tuple<!fir.ref<i32>>
|
||||
! CHECK: %[[VAL_17:.*]] = fir.coordinate_of %[[VAL_16]], %[[VAL_1]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>>
|
||||
! CHECK: %[[VAL_18:.*]] = fir.volatile_cast %[[VAL_9]]#0 : (!fir.ref<i32, volatile>) -> !fir.ref<i32>
|
||||
! CHECK: fir.store %[[VAL_18]] to %[[VAL_17]] : !fir.llvm_ptr<!fir.ref<i32>>
|
||||
! CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_15]]#0(%[[VAL_4]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_9]]#0 : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_6]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: fir.call @_QFPhost_assoc(%[[VAL_16]]) 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 {{.+}} {
|
||||
! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32
|
||||
! CHECK: %[[VAL_3:.*]] = arith.constant 10 : index
|
||||
! CHECK: %[[VAL_4:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QFEarr) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_7:.*]] = fir.volatile_cast %[[VAL_5]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_6]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, 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:.*]]:2 = hlfir.declare %[[VAL_10]] {{.+}} : (!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>)
|
||||
! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEtgt) : !fir.ref<!fir.array<10xi32>>
|
||||
! CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_13]](%[[VAL_6]]) {{.+}} : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>, volatile>, !fir.ref<!fir.array<10xi32>, volatile>)
|
||||
! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_2]] : (!fir.ref<tuple<!fir.ref<i32>>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>>
|
||||
! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.llvm_ptr<!fir.ref<i32>>
|
||||
! CHECK: %[[VAL_17:.*]] = fir.volatile_cast %[[VAL_16]] : (!fir.ref<i32>) -> !fir.ref<i32, volatile>
|
||||
! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {{.+}} : (!fir.ref<i32, volatile>) -> (!fir.ref<i32, volatile>, !fir.ref<i32, volatile>)
|
||||
! CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_14]]#0(%[[VAL_6]]) : (!fir.ref<!fir.array<10xi32>, volatile>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>
|
||||
! CHECK: fir.store %[[VAL_19]] to %[[VAL_11]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>, volatile>, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_18]]#0 : i32, !fir.ref<i32, volatile>
|
||||
! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_8]]#0 : i32, !fir.ref<!fir.array<10xi32>, volatile>
|
||||
! 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-LABEL: fir.global internal @_QFEptr : !fir.box<!fir.ptr<!fir.array<?xi32>>> {
|
||||
! CHECK: %[[VAL_0:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_1:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>>
|
||||
! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_0]] : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1]](%[[VAL_2]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>>
|
||||
! CHECK: fir.has_value %[[VAL_3]] : !fir.box<!fir.ptr<!fir.array<?xi32>>>
|
||||
! CHECK: }
|
||||
|
||||
! CHECK-LABEL: fir.global internal @_QFEtgt target : !fir.array<10xi32> {
|
||||
! CHECK: %[[VAL_0:.*]] = fir.zero_bits !fir.array<10xi32>
|
||||
! CHECK: fir.has_value %[[VAL_0]] : !fir.array<10xi32>
|
||||
! CHECK: }
|
Loading…
x
Reference in New Issue
Block a user