[flang-commits] [flang] [flang] Stop using Operation::getAttrs (NFC) (PR #223049)
Mehdi Amini via flang-commits
flang-commits at lists.llvm.org
Fri Sep 11 14:46:57 PDT 2026
https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/223049
>From 65f30d145e38203bef6376f1ad65afc7a0bcbe5b Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 10 Sep 2026 10:52:41 -0700
Subject: [PATCH] [flang] Stop using Operation::getAttrs
Migrate FIR attribute copying and printing to the explicit inherent and
discardable attribute APIs.
This is part of a general migration to use the "new" properties-based APIs
and stop mixing discardable/inherent attributes, see #155475
Assisted-by: Codex
---
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 38 +++--
flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp | 154 +++++++++---------
flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp | 9 +-
flang/lib/Optimizer/Dialect/FIROps.cpp | 118 +++++++++-----
.../HLFIR/Transforms/ConvertToFIR.cpp | 10 +-
.../ConstantArgumentGlobalisation.cpp | 3 +-
flang/lib/Optimizer/Transforms/FIRToSCF.cpp | 12 +-
flang/test/Fir/FirToSCF/iter-while.fir | 10 +-
.../test/Fir/convert-to-llvm-access-group.fir | 8 +-
9 files changed, 208 insertions(+), 154 deletions(-)
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 1fafee2e90714..e072416e89089 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1504,6 +1504,15 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
size = integerCast(loc, rewriter, mallocTy, size);
std::optional<uint64_t> alignment = heap.getAlignment();
+ auto getRuntimeCallBuilderAttributes = [&](int32_t numCallOperands) {
+ llvm::SmallVector<mlir::NamedAttribute> runtimeCallAttrs(
+ heap->getDiscardableAttrDictionary().getValue());
+ if (mlir::IntegerAttr alignmentAttr = heap.getAlignmentAttr())
+ runtimeCallAttrs.emplace_back(heap.getAlignmentAttrName(),
+ alignmentAttr);
+ return getLLVMCallBuilderAttributes(rewriter, runtimeCallAttrs,
+ numCallOperands);
+ };
if (alignment && *alignment > 16) {
auto mod = heap->getParentOfType<mlir::ModuleOp>();
llvm::Triple triple = mod ? fir::getTargetTriple(mod) : llvm::Triple{};
@@ -1536,8 +1545,7 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
mlir::LLVM::StoreOp::create(rewriter, loc, nullPtr, memptr);
heap->setAttr("callee", getPosixMemalign(heap, rewriter, mallocTy,
this->options));
- auto builderAttrs =
- getLLVMCallBuilderAttributes(rewriter, heap->getAttrs(), 3);
+ auto builderAttrs = getRuntimeCallBuilderAttributes(3);
mlir::LLVM::CallOp::create(rewriter, loc,
mlir::TypeRange{mlir::IntegerType::get(
rewriter.getContext(), 32)},
@@ -1561,8 +1569,7 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
rewriter, loc, mallocTy, sizePlus, notAlignMinusOne);
heap->setAttr("callee",
getAlignedAlloc(heap, rewriter, mallocTy, this->options));
- auto builderAttrs =
- getLLVMCallBuilderAttributes(rewriter, heap->getAttrs(), 2);
+ auto builderAttrs = getRuntimeCallBuilderAttributes(2);
rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
heap, mlir::TypeRange{::getLlvmPtrType(heap.getContext())},
mlir::ValueRange{alignVal, roundedSize}, builderAttrs.properties,
@@ -1572,8 +1579,7 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
}
heap->setAttr("callee", getMalloc(heap, rewriter, mallocTy, this->options));
- auto builderAttrs =
- getLLVMCallBuilderAttributes(rewriter, heap->getAttrs(), 1);
+ auto builderAttrs = getRuntimeCallBuilderAttributes(1);
rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
heap, mlir::TypeRange{::getLlvmPtrType(heap.getContext())},
mlir::ValueRange{size}, builderAttrs.properties,
@@ -1647,8 +1653,8 @@ struct FreeMemOpConversion : public fir::FIROpConversion<fir::FreeMemOp> {
mlir::ConversionPatternRewriter &rewriter) const override {
mlir::Location loc = freemem.getLoc();
freemem->setAttr("callee", getFree(freemem, rewriter, this->options));
- auto builderAttrs =
- getLLVMCallBuilderAttributes(rewriter, freemem->getAttrs(), 1);
+ auto builderAttrs = getLLVMCallBuilderAttributes(
+ rewriter, freemem->getDiscardableAttrDictionary().getValue(), 1);
mlir::LLVM::CallOp::create(rewriter, loc, mlir::TypeRange{},
mlir::ValueRange{adaptor.getHeapref()},
builderAttrs.properties,
@@ -3849,11 +3855,9 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
// Apply all non-Fir::GlobalOp attributes to the LLVM::GlobalOp, preserving
// them; whilst taking care not to apply attributes that are lowered in
// other ways.
- llvm::SmallDenseSet<llvm::StringRef> elidedAttrsSet(
- global.getAttributeNames().begin(), global.getAttributeNames().end());
- for (auto &attr : global->getAttrs())
- if (!elidedAttrsSet.contains(attr.getName().strref()))
- g->setAttr(attr.getName(), attr.getValue());
+ for (mlir::NamedAttribute attr :
+ global->getDiscardableAttrDictionary().getValue())
+ g->setDiscardableAttr(attr.getName(), attr.getValue());
auto &gr = g.getInitializerRegion();
rewriter.inlineRegionBefore(global.getRegion(), gr, gr.end());
@@ -4050,13 +4054,11 @@ struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> {
rewriter.replaceOp(load, newBoxStorage);
} else {
- auto builderAttrs = splitBuilderAttributes<mlir::LLVM::LoadOp>(
- rewriter, load->getAttrs());
mlir::LLVM::LoadOp loadOp = mlir::LLVM::LoadOp::create(
- rewriter, load.getLoc(), mlir::TypeRange{llvmLoadTy},
- adaptor.getOperands(), builderAttrs.properties,
- builderAttrs.discardableAttributes);
+ rewriter, load.getLoc(), llvmLoadTy, adaptor.getOperands().front());
+ loadOp->setDiscardableAttrs(load->getDiscardableAttrDictionary());
loadOp.setVolatile_(isVolatile);
+ loadOp.setNontemporal(load.getNontemporal());
if (std::optional<mlir::ArrayAttr> optionalTag = load.getTbaa())
loadOp.setTBAATags(*optionalTag);
else
diff --git a/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp b/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp
index 9c6ebd61f1072..35819444387e0 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGenOpenMP.cpp
@@ -78,91 +78,91 @@ struct MapInfoOpConversion
if (failed(converter->convertTypes(curOp->getResultTypes(), resTypes)))
return mlir::failure();
- llvm::SmallVector<mlir::NamedAttribute> newAttrs;
+ auto newProperties = curOp.getProperties();
mlir::omp::MapBoundsOp mapBoundsOp;
- for (mlir::NamedAttribute attr : curOp->getAttrs()) {
- if (auto typeAttr = mlir::dyn_cast<mlir::TypeAttr>(attr.getValue())) {
- mlir::Type newAttr;
- if (fir::isTypeWithDescriptor(typeAttr.getValue())) {
- newAttr = lowerTy().convertBoxTypeAsStruct(
- mlir::cast<fir::BaseBoxType>(typeAttr.getValue()));
- } else if (fir::isa_char_string(fir::unwrapSequenceType(
- fir::unwrapPassByRefType(typeAttr.getValue()))) &&
- !characterWithDynamicLen(
- fir::unwrapPassByRefType(typeAttr.getValue()))) {
- // Characters with a LEN param are represented as strings
- // (array of characters), the lowering to LLVM dialect
- // doesn't generate bounds for these (and this is not
- // done at the initial lowering either) and there is
- // minor inconsistencies in the variable types we
- // create for the map without this step when converting
- // to the LLVM dialect.
- //
- // For example, given the types:
- //
- // 1) CHARACTER(LEN=16), dimension(:,:), allocatable :: char_arr
- // 2) CHARACTER(LEN=16), dimension(10,10) :: char_arr
- //
- // We get the FIR types (note for 1: we already peeled off the
- // dynamic extents from the type at this stage, but the conversion
- // to llvm dialect does that in any case, so the final result
- // is the same):
- //
- // 1) !fir.char<1,16>
- // 2) !fir.array<10x10x!fir.char<1,16>>
- //
- // Which are converted to the LLVM dialect types:
- //
- // 1) !llvm.array<16 x i8>
- // 2) llvm.array<10 x array<10 x array<16 x i8>>
- //
- // And in both cases, we are missing the innermost bounds for
- // the !fir.char<1,16> which is expanded into a 16 x i8 array
- // in the conversion to LLVM dialect.
- //
- // The problem with this is that we would like to treat these
- // cases identically and not have to create specialised
- // lowerings for either of these in the lowering to LLVM-IR
- // and treat them like any other array that passes through.
- //
- // To do so below, we generate an extra bound for the
- // innermost array (the char type/string) using the LEN
- // parameter of the character type. And we "canonicalize"
- // the type, stripping it down to the base element type,
- // which in this case is an i8. This effectively allows
- // the lowering to treat this as a 1-D array with multiple
- // bounds which it is capable of handling without any special
- // casing.
- // TODO: Handle dynamic LEN characters.
- if (auto ct = mlir::dyn_cast_or_null<fir::CharacterType>(
- fir::unwrapSequenceType(typeAttr.getValue()))) {
- newAttr = converter->convertType(
- fir::unwrapSequenceType(typeAttr.getValue()));
- if (auto type = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(newAttr))
- newAttr = type.getElementType();
- // We do not generate MapBoundsOps for the device pass, as
- // MapBoundsOps are not generated for the device pass, as
- // they're unused in the device lowering.
- auto offloadMod =
- llvm::dyn_cast_or_null<mlir::omp::OffloadModuleInterface>(
- *curOp->getParentOfType<mlir::ModuleOp>());
- if (!offloadMod.getIsTargetDevice())
- mapBoundsOp = createBoundsForCharString(rewriter, ct.getLen(),
- curOp.getLoc());
- } else {
- newAttr = converter->convertType(typeAttr.getValue());
- }
+ auto convertTypeAttr = [&](mlir::TypeAttr typeAttr) {
+ mlir::Type newAttr;
+ if (fir::isTypeWithDescriptor(typeAttr.getValue())) {
+ newAttr = lowerTy().convertBoxTypeAsStruct(
+ mlir::cast<fir::BaseBoxType>(typeAttr.getValue()));
+ } else if (fir::isa_char_string(fir::unwrapSequenceType(
+ fir::unwrapPassByRefType(typeAttr.getValue()))) &&
+ !characterWithDynamicLen(
+ fir::unwrapPassByRefType(typeAttr.getValue()))) {
+ // Characters with a LEN param are represented as strings
+ // (array of characters), the lowering to LLVM dialect
+ // doesn't generate bounds for these (and this is not
+ // done at the initial lowering either) and there is
+ // minor inconsistencies in the variable types we
+ // create for the map without this step when converting
+ // to the LLVM dialect.
+ //
+ // For example, given the types:
+ //
+ // 1) CHARACTER(LEN=16), dimension(:,:), allocatable :: char_arr
+ // 2) CHARACTER(LEN=16), dimension(10,10) :: char_arr
+ //
+ // We get the FIR types (note for 1: we already peeled off the
+ // dynamic extents from the type at this stage, but the conversion
+ // to llvm dialect does that in any case, so the final result
+ // is the same):
+ //
+ // 1) !fir.char<1,16>
+ // 2) !fir.array<10x10x!fir.char<1,16>>
+ //
+ // Which are converted to the LLVM dialect types:
+ //
+ // 1) !llvm.array<16 x i8>
+ // 2) llvm.array<10 x array<10 x array<16 x i8>>
+ //
+ // And in both cases, we are missing the innermost bounds for
+ // the !fir.char<1,16> which is expanded into a 16 x i8 array
+ // in the conversion to LLVM dialect.
+ //
+ // The problem with this is that we would like to treat these
+ // cases identically and not have to create specialised
+ // lowerings for either of these in the lowering to LLVM-IR
+ // and treat them like any other array that passes through.
+ //
+ // To do so below, we generate an extra bound for the
+ // innermost array (the char type/string) using the LEN
+ // parameter of the character type. And we "canonicalize"
+ // the type, stripping it down to the base element type,
+ // which in this case is an i8. This effectively allows
+ // the lowering to treat this as a 1-D array with multiple
+ // bounds which it is capable of handling without any special
+ // casing.
+ // TODO: Handle dynamic LEN characters.
+ if (auto ct = mlir::dyn_cast_or_null<fir::CharacterType>(
+ fir::unwrapSequenceType(typeAttr.getValue()))) {
+ newAttr = converter->convertType(
+ fir::unwrapSequenceType(typeAttr.getValue()));
+ if (auto type = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(newAttr))
+ newAttr = type.getElementType();
+ // We do not generate MapBoundsOps for the device pass, as
+ // MapBoundsOps are not generated for the device pass, as
+ // they're unused in the device lowering.
+ auto offloadMod =
+ llvm::dyn_cast_or_null<mlir::omp::OffloadModuleInterface>(
+ *curOp->getParentOfType<mlir::ModuleOp>());
+ if (!offloadMod.getIsTargetDevice())
+ mapBoundsOp = createBoundsForCharString(rewriter, ct.getLen(),
+ curOp.getLoc());
} else {
newAttr = converter->convertType(typeAttr.getValue());
}
- newAttrs.emplace_back(attr.getName(), mlir::TypeAttr::get(newAttr));
} else {
- newAttrs.push_back(attr);
+ newAttr = converter->convertType(typeAttr.getValue());
}
- }
+ return mlir::TypeAttr::get(newAttr);
+ };
+ newProperties.setVarPtrType(convertTypeAttr(curOp.getVarPtrTypeAttr()));
+ if (mlir::TypeAttr varPtrPtrType = curOp.getVarPtrPtrTypeAttr())
+ newProperties.setVarPtrPtrType(convertTypeAttr(varPtrPtrType));
auto newOp = rewriter.replaceOpWithNewOp<mlir::omp::MapInfoOp>(
- curOp, resTypes, adaptor.getOperands(), newAttrs);
+ curOp, resTypes, adaptor.getOperands(), newProperties,
+ curOp->getDiscardableAttrDictionary().getValue());
if (mapBoundsOp) {
rewriter.startOpModification(newOp);
newOp.getBoundsMutable().append(mlir::ValueRange{mapBoundsOp});
diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp
index 3af5e990972f1..9782ce22f6015 100644
--- a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp
+++ b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp
@@ -287,6 +287,11 @@ bool cuf::KernelOp::canMoveOutOf(mlir::Operation *candidate) {
// Operations that have !fir.ref operands cannot be moved
// out of cuf.kernel, because this may break implicit data mapping
// passes that may run after LICM.
+ bool hasSymbolRefAttr = false;
+ candidate->getName().walkInherentAttrs(
+ candidate, [&](llvm::StringRef, mlir::Attribute &attr) {
+ hasSymbolRefAttr |= mlir::isa_and_present<mlir::SymbolRefAttr>(attr);
+ });
return !llvm::any_of(candidate->getOperands(),
[&](mlir::Value candidateOperand) {
return fir::isa_ref_type(candidateOperand.getType());
@@ -294,9 +299,7 @@ bool cuf::KernelOp::canMoveOutOf(mlir::Operation *candidate) {
// Same is true for symbol operands (this has to be revisited,
// because this may indicate an issue in ordering between
// CUFDeviceGlobal and OffloadLiveInValueCanonicalization passes).
- !llvm::any_of(candidate->getAttrs(), [&](mlir::NamedAttribute attr) {
- return mlir::isa_and_present<mlir::SymbolRefAttr>(attr.getValue());
- });
+ !hasSymbolRefAttr;
}
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index ede7195041076..33f8d86d5283c 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -38,6 +38,8 @@
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
+#include <type_traits>
+
namespace {
#include "flang/Optimizer/Dialect/CanonicalizationPatterns.inc"
} // namespace
@@ -56,11 +58,27 @@ static void propagateAttributes(mlir::Operation *fromOp,
if (!fromOp || !toOp)
return;
- for (mlir::NamedAttribute attr : fromOp->getAttrs()) {
+ for (mlir::NamedAttribute attr :
+ fromOp->getDiscardableAttrDictionary().getValue()) {
if (attr.getName().getValue().starts_with(
mlir::acc::OpenACCDialect::getDialectNamespace()))
- toOp->setAttr(attr.getName(), attr.getValue());
- }
+ toOp->setDiscardableAttr(attr.getName(), attr.getValue());
+ }
+}
+
+static llvm::SmallVector<mlir::NamedAttribute>
+collectAttrsForPrinting(mlir::Operation *op,
+ llvm::ArrayRef<mlir::StringAttr> inherentAttrNames) {
+ llvm::SmallVector<mlir::NamedAttribute> attrs(
+ op->getDiscardableAttrDictionary().getValue());
+ for (mlir::StringAttr name : inherentAttrNames)
+ if (std::optional<mlir::Attribute> value = op->getInherentAttr(name);
+ value && *value)
+ attrs.emplace_back(name, *value);
+ llvm::sort(attrs, [](mlir::NamedAttribute lhs, mlir::NamedAttribute rhs) {
+ return lhs.getName().strref() < rhs.getName().strref();
+ });
+ return attrs;
}
/// Return true if a sequence type is of some incomplete size or a record type
@@ -174,7 +192,14 @@ static void printAllocatableOp(mlir::OpAsmPrinter &p, OP &op) {
p << ", ";
p.printOperand(sh);
}
- p.printOptionalAttrDict(op->getAttrs(), {"in_type", "operandSegmentSizes"});
+ llvm::SmallVector<mlir::StringAttr> inherentAttrNames = {
+ op.getUniqNameAttrName(), op.getBindcNameAttrName()};
+ if constexpr (std::is_same_v<OP, fir::AllocMemOp>)
+ inherentAttrNames.push_back(op.getAlignmentAttrName());
+ else
+ inherentAttrNames.push_back(op.getPinnedAttrName());
+ p.printOptionalAttrDict(collectAttrsForPrinting(op, inherentAttrNames),
+ {"in_type", "operandSegmentSizes"});
}
bool fir::mayBeAbsentBox(mlir::Value val) {
@@ -1507,10 +1532,12 @@ void fir::CallOp::print(mlir::OpAsmPrinter &p) {
p.printStrippedAttrOrType(fmfAttr);
}
- p.printOptionalAttrDict((*this)->getAttrs(),
- {fir::CallOp::getCalleeAttrNameStr(),
- getFastmathAttrName(), getProcedureAttrsAttrName(),
- getArgAttrsAttrName(), getResAttrsAttrName()});
+ p.printOptionalAttrDict(
+ collectAttrsForPrinting(
+ *this, {getInlineAttrAttrName(), getAccessGroupsAttrName()}),
+ {fir::CallOp::getCalleeAttrNameStr(), getFastmathAttrName(),
+ getProcedureAttrsAttrName(), getArgAttrsAttrName(),
+ getResAttrsAttrName()});
p << " : ";
mlir::call_interface_impl::printFunctionSignature(
p, getArgs().drop_front(isDirect ? 0 : 1).getTypes(), getArgAttrsAttr(),
@@ -1685,8 +1712,9 @@ static void printCmpOp(mlir::OpAsmPrinter &p, OPTY op) {
p.printOperand(op.getLhs());
p << ", ";
p.printOperand(op.getRhs());
- p.printOptionalAttrDict(op->getAttrs(),
- /*elidedAttrs=*/{OPTY::getPredicateAttrName()});
+ p.printOptionalAttrDict(
+ collectAttrsForPrinting(op, {op.getFastmathAttrName()}),
+ /*elidedAttrs=*/{OPTY::getPredicateAttrName()});
p << " : " << op.getLhs().getType();
}
@@ -2253,7 +2281,7 @@ void fir::CoordinateOp::print(mlir::OpAsmPrinter &p) {
}
}
p.printOptionalAttrDict(
- (*this)->getAttrs(),
+ (*this)->getDiscardableAttrDictionary().getValue(),
/*elideAttrs=*/{getBaseTypeAttrName(), getFieldIndicesAttrName()});
p << " : ";
p.printFunctionalType(getOperandTypes(), (*this)->getResultTypes());
@@ -2796,7 +2824,8 @@ mlir::ParseResult fir::TypeDescOp::parse(mlir::OpAsmParser &parser,
void fir::TypeDescOp::print(mlir::OpAsmPrinter &p) {
p << ' ' << getOperation()->getAttr("in_type");
- p.printOptionalAttrDict(getOperation()->getAttrs(), {"in_type"});
+ p.printOptionalAttrDict(
+ getOperation()->getDiscardableAttrDictionary().getValue());
}
llvm::LogicalResult fir::TypeDescOp::verify() {
@@ -2895,10 +2924,12 @@ void fir::GlobalOp::print(mlir::OpAsmPrinter &p) {
p << '(' << val << ')';
// Print all other attributes that are not pretty printed here.
p.printOptionalAttrDict(
- (*this)->getAttrs(), /*elideAttrs=*/{
- getSymNameAttrName(), getSymrefAttrName(), getTypeAttrName(),
- getConstantAttrName(), getTargetAttrName(), getLinkageAttrName(),
- getInitValAttrName(), getSymVisibilityAttrName()});
+ collectAttrsForPrinting(*this,
+ {getDataAttrAttrName(), getAlignmentAttrName()}),
+ /*elideAttrs=*/{getSymNameAttrName(), getSymrefAttrName(),
+ getTypeAttrName(), getConstantAttrName(),
+ getTargetAttrName(), getLinkageAttrName(),
+ getInitValAttrName(), getSymVisibilityAttrName()});
if (getOperation()->getAttr(getConstantAttrName()))
p << " " << getConstantAttrName().strref();
if (getOperation()->getAttr(getTargetAttrName()))
@@ -3447,8 +3478,8 @@ void fir::IterWhileOp::print(mlir::OpAsmPrinter &p) {
} else if (getFinalValue()) {
p << " -> (" << getResultTypes() << ')';
}
- p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
- {getFinalValueAttrNameStr()});
+ p.printOptionalAttrDictWithKeyword(
+ (*this)->getDiscardableAttrDictionary().getValue());
p << ' ';
p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/true);
@@ -3611,7 +3642,9 @@ mlir::ParseResult fir::LoadOp::parse(mlir::OpAsmParser &parser,
void fir::LoadOp::print(mlir::OpAsmPrinter &p) {
p << ' ';
p.printOperand(getMemref());
- p.printOptionalAttrDict(getOperation()->getAttrs(), {});
+ p.printOptionalAttrDict(collectAttrsForPrinting(
+ getOperation(), {getTbaaAttrName(), getNontemporalAttrName(),
+ getInvariantAttrName(), getAccessGroupsAttrName()}));
p << " : " << getMemref().getType();
}
@@ -3878,7 +3911,7 @@ void fir::DoLoopOp::print(mlir::OpAsmPrinter &p) {
if (!getInductionVar().getType().isIndex())
p << " : " << getInductionVar().getType();
p.printOptionalAttrDictWithKeyword(
- (*this)->getAttrs(),
+ collectAttrsForPrinting(*this, {getLoopAnnotationAttrName()}),
{"unordered", "finalValue", "reduceAttrs", "operandSegmentSizes"});
p << ' ';
p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
@@ -4358,9 +4391,10 @@ static void printIntegralSwitchTerminator(OpT op, mlir::OpAsmPrinter &p) {
op.printSuccessorAtIndex(p, i);
}
p << ']';
- p.printOptionalAttrDict(
- op->getAttrs(), {op.getCasesAttr(), getCompareOffsetAttr(),
- getTargetOffsetAttr(), op.getOperandSegmentSizeAttr()});
+ p.printOptionalAttrDict(op->getDiscardableAttrDictionary().getValue(),
+ {op.getCasesAttr(), getCompareOffsetAttr(),
+ getTargetOffsetAttr(),
+ op.getOperandSegmentSizeAttr()});
}
//===----------------------------------------------------------------------===//
@@ -4597,9 +4631,10 @@ void fir::SelectCaseOp::print(mlir::OpAsmPrinter &p) {
printSuccessorAtIndex(p, i);
}
p << ']';
- p.printOptionalAttrDict(getOperation()->getAttrs(),
- {getCasesAttr(), getCompareOffsetAttr(),
- getTargetOffsetAttr(), getOperandSegmentSizeAttr()});
+ p.printOptionalAttrDict(
+ getOperation()->getDiscardableAttrDictionary().getValue(),
+ {getCasesAttr(), getCompareOffsetAttr(), getTargetOffsetAttr(),
+ getOperandSegmentSizeAttr()});
}
unsigned fir::SelectCaseOp::compareOffsetSize() {
@@ -4883,10 +4918,10 @@ void fir::SelectTypeOp::print(mlir::OpAsmPrinter &p) {
printSuccessorAtIndex(p, i);
}
p << ']';
- p.printOptionalAttrDict(getOperation()->getAttrs(),
- {getCasesAttr(), getCompareOffsetAttr(),
- getTargetOffsetAttr(),
- fir::SelectTypeOp::getOperandSegmentSizeAttr()});
+ p.printOptionalAttrDict(
+ getOperation()->getDiscardableAttrDictionary().getValue(),
+ {getCasesAttr(), getCompareOffsetAttr(), getTargetOffsetAttr(),
+ fir::SelectTypeOp::getOperandSegmentSizeAttr()});
}
llvm::LogicalResult fir::SelectTypeOp::verify() {
@@ -5169,7 +5204,9 @@ void fir::StoreOp::print(mlir::OpAsmPrinter &p) {
p.printOperand(getValue());
p << " to ";
p.printOperand(getMemref());
- p.printOptionalAttrDict(getOperation()->getAttrs(), {});
+ p.printOptionalAttrDict(collectAttrsForPrinting(
+ getOperation(), {getTbaaAttrName(), getNontemporalAttrName(),
+ getAccessGroupsAttrName()}));
p << " : " << getMemref().getType();
}
@@ -5622,8 +5659,7 @@ void fir::IfOp::print(mlir::OpAsmPrinter &p) {
p.printRegion(otherReg, /*printEntryBlockArgs=*/false,
printBlockTerminators);
}
- p.printOptionalAttrDict((*this)->getAttrs(),
- /*elideAttrs=*/{getRegionWeightsAttrName()});
+ p.printOptionalAttrDict((*this)->getDiscardableAttrDictionary().getValue());
}
void fir::IfOp::resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
@@ -5868,6 +5904,14 @@ valueCheckFirAttributes(mlir::Value value,
return true;
};
+ auto testOperationAttributes = [&](mlir::Operation *op) {
+ auto hasAttribute = [&](llvm::StringRef name) {
+ return op->hasDiscardableAttr(name);
+ };
+ if (checkAny)
+ return llvm::any_of(attributeNames, hasAttribute);
+ return llvm::all_of(attributeNames, hasAttribute);
+ };
// If this is a fir.box that was loaded, the fir attributes will be on the
// related fir.ref<fir.box> creation.
if (mlir::isa<fir::BoxType>(value.getType()))
@@ -5892,18 +5936,18 @@ valueCheckFirAttributes(mlir::Value value,
// If this is an allocated value, look at the allocation attributes.
if (mlir::isa<fir::AllocMemOp>(definingOp) ||
mlir::isa<fir::AllocaOp>(definingOp))
- return testAttributeSets(definingOp->getAttrs(), attributeNames);
+ return testOperationAttributes(definingOp);
// If this is an imported global, look at AddrOfOp and GlobalOp attributes.
// Both operations are looked at because use/host associated variable (the
// AddrOfOp) can have ASYNCHRONOUS/VOLATILE attributes even if the ultimate
// entity (the globalOp) does not have them.
if (auto addressOfOp = mlir::dyn_cast<fir::AddrOfOp>(definingOp)) {
- if (testAttributeSets(addressOfOp->getAttrs(), attributeNames))
+ if (testOperationAttributes(addressOfOp))
return true;
if (auto module = definingOp->getParentOfType<mlir::ModuleOp>())
if (auto globalOp =
module.lookupSymbol<fir::GlobalOp>(addressOfOp.getSymbol()))
- return testAttributeSets(globalOp->getAttrs(), attributeNames);
+ return testOperationAttributes(globalOp);
}
}
// TODO: Construct associated entities attributes. Decide where the fir
@@ -6711,7 +6755,7 @@ void fir::DoConcurrentLoopOp::print(mlir::OpAsmPrinter &p) {
p << ' ';
p.printRegion(getRegion(), /*printEntryBlockArgs=*/false);
p.printOptionalAttrDict(
- (*this)->getAttrs(),
+ collectAttrsForPrinting(*this, {getLoopAnnotationAttrName()}),
/*elidedAttrs=*/{DoConcurrentLoopOp::getOperandSegmentSizeAttr(),
DoConcurrentLoopOp::getLocalSymsAttrName(),
DoConcurrentLoopOp::getReduceSymsAttrName(),
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index 2be94d40ebd50..985e57ff70f49 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -378,13 +378,9 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
// Propagate other attributes from hlfir.declare to fir.declare.
// OpenACC's acc.declare is one example. Right now, the propagation
// is verbatim.
- llvm::SmallSet<llvm::StringRef, 8> elidedAttrs;
- for (const mlir::NamedAttribute &firAttr : firDeclareOp->getAttrs())
- elidedAttrs.insert(firAttr.getName());
- elidedAttrs.insert(declareOp.getSkipReboxAttrName());
- for (const mlir::NamedAttribute &attr : declareOp->getAttrs())
- if (!elidedAttrs.contains(attr.getName()))
- firDeclareOp->setAttr(attr.getName(), attr.getValue());
+ for (mlir::NamedAttribute attr :
+ declareOp->getDiscardableAttrDictionary().getValue())
+ firDeclareOp->setDiscardableAttr(attr.getName(), attr.getValue());
auto firBase = firDeclareOp.getResult();
mlir::Value hlfirBase;
diff --git a/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp b/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp
index afafbd8179aff..fc2962b39cd88 100644
--- a/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp
+++ b/flang/lib/Optimizer/Transforms/ConstantArgumentGlobalisation.cpp
@@ -131,7 +131,8 @@ class CallOpRewriter : public mlir::OpRewritePattern<fir::CallOp> {
: mlir::SymbolRefAttr{},
newResultTypes, newOperands);
// Copy all the attributes from the old to new op.
- newOp->setAttrs(callOp->getAttrs());
+ newOp->copyProperties(callOp->getPropertiesStorage());
+ newOp->setDiscardableAttrs(callOp->getDiscardableAttrDictionary());
rewriter.replaceOp(callOp, newOp);
for (auto a : allocas) {
diff --git a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
index d6393ab53a647..ff1f69a7d0b0f 100644
--- a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
@@ -19,6 +19,12 @@ namespace fir {
} // namespace fir
namespace {
+static void copyDiscardableAttrs(mlir::Operation *from, mlir::Operation *to) {
+ for (mlir::NamedAttribute attr :
+ from->getDiscardableAttrDictionary().getValue())
+ to->setDiscardableAttr(attr.getName(), attr.getValue());
+}
+
class FIRToSCFPass : public fir::impl::FIRToSCFPassBase<FIRToSCFPass> {
using FIRToSCFPassBase::FIRToSCFPassBase;
@@ -298,7 +304,7 @@ struct IterWhileConversion : public mlir::OpRewritePattern<fir::IterWhileOp> {
rewriter.setInsertionPointToEnd(afterBody);
rewriter.replaceOpWithNewOp<mlir::scf::YieldOp>(resultOp, results);
- scfWhileOp->setAttrs(iterWhileOp->getAttrs());
+ copyDiscardableAttrs(iterWhileOp, scfWhileOp);
rewriter.replaceOp(iterWhileOp,
hasFinalValue ? scfWhileOp->getResults()
: scfWhileOp->getResults().drop_front());
@@ -344,7 +350,9 @@ struct IfConversion : public mlir::OpRewritePattern<fir::IfOp> {
scfIfOp.getElseRegion().front());
}
- scfIfOp->setAttrs(ifOp->getAttrs());
+ copyDiscardableAttrs(ifOp, scfIfOp);
+ if (mlir::DenseI32ArrayAttr weights = ifOp.getRegionWeightsAttr())
+ scfIfOp->setDiscardableAttr(ifOp.getRegionWeightsAttrName(), weights);
rewriter.replaceOp(ifOp, scfIfOp);
return mlir::success();
}
diff --git a/flang/test/Fir/FirToSCF/iter-while.fir b/flang/test/Fir/FirToSCF/iter-while.fir
index 1e9bd827338cc..0cf939270baea 100644
--- a/flang/test/Fir/FirToSCF/iter-while.fir
+++ b/flang/test/Fir/FirToSCF/iter-while.fir
@@ -25,7 +25,7 @@
// CHECK: %[[CONSTANT_8:.*]] = arith.constant 22 : i16
// CHECK: %[[CONSTANT_9:.*]] = arith.constant 33 : i32
// CHECK: scf.yield %[[ADDI_0]], %[[CONSTANT_7]], %[[CONSTANT_8]], %[[CONSTANT_9]] : index, i1, i16, i32
-// CHECK: } attributes {finalValue}
+// CHECK: }
// CHECK: return %[[VAL_8:.*]]#0, %[[VAL_8]]#1, %[[VAL_8]]#2, %[[VAL_8]]#3 : index, i1, i16, i32
// CHECK: }
func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) {
@@ -66,7 +66,7 @@ func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) {
// CHECK: %[[CONSTANT_2:.*]] = arith.constant 123 : i32
// CHECK: %[[CONSTANT_3:.*]] = arith.constant true
// CHECK: scf.yield %[[ADDI_0]], %[[CONSTANT_3]], %[[CONSTANT_2]] : index, i1, i32
-// CHECK: } attributes {finalValue}
+// CHECK: }
// CHECK: return %[[VAL_6:.*]]#0, %[[VAL_6]]#1, %[[VAL_6]]#2 : index, i1, i32
// CHECK: }
func.func @test_simple_iterate_while_2(%start: index, %stop: index, %cond: i1, %val: i32) -> (index, i1, i32) {
@@ -102,7 +102,7 @@ func.func @test_simple_iterate_while_2(%start: index, %stop: index, %cond: i1, %
// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] overflow<nsw> : index
// CHECK: %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1
// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1
-// CHECK: } attributes {finalValue}
+// CHECK: }
// CHECK: return %[[VAL_5:.*]]#1 : i1
// CHECK: }
func.func @loop_with_negtive_step(%lo : index, %up : index) -> i1 {
@@ -136,7 +136,7 @@ func.func @loop_with_negtive_step(%lo : index, %up : index) -> i1 {
// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] overflow<nsw> : index
// CHECK: %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1
// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1
-// CHECK: } attributes {finalValue}
+// CHECK: }
// CHECK: return %[[VAL_5:.*]]#1 : i1
// CHECK: }
func.func @loop_with_zero_step(%lo : index, %up : index) -> i1 {
@@ -170,7 +170,7 @@ func.func @loop_with_zero_step(%lo : index, %up : index) -> i1 {
// CHECK: ^bb0(%[[VAL_3:.*]]: index, %[[VAL_4:.*]]: i1, %[[VAL_5:.*]]: i8):
// CHECK: %[[ADDI_0:.*]] = arith.addi %[[VAL_3]], %[[CONSTANT_2]] overflow<nsw> : index
// CHECK: scf.yield %[[ADDI_0]], %[[VAL_4]], %[[VAL_5]] : index, i1, i8
-// CHECK: } attributes {finalValue}
+// CHECK: }
// CHECK: return %[[VAL_6:.*]]#0, %[[VAL_6]]#1, %[[VAL_6]]#2 : index, i1, i8
// CHECK: }
func.func @test_zero_iterations() -> (index, i1, i8) {
diff --git a/flang/test/Fir/convert-to-llvm-access-group.fir b/flang/test/Fir/convert-to-llvm-access-group.fir
index e28f36ffe64ca..883a9e8bb0193 100644
--- a/flang/test/Fir/convert-to-llvm-access-group.fir
+++ b/flang/test/Fir/convert-to-llvm-access-group.fir
@@ -23,13 +23,13 @@
// CHECK: llvm.cond_br %[[ICMP_0]], ^bb2, ^bb3
// CHECK: ^bb2:
// CHECK: llvm.store %[[VAL_0]], %[[ALLOCA_1]] <access_groups = [#[[$ATTR_0]]]> : i32, !llvm.ptr
-// CHECK: %[[LOAD_1:.*]] = llvm.load %[[ALLOCA_1]] <access_groups = [#[[$ATTR_0]]]> {accessGroups = [#[[$ATTR_0]]]} : !llvm.ptr -> i32
-// CHECK: %[[LOAD_2:.*]] = llvm.load %[[ARG1]] <access_groups = [#[[$ATTR_0]]]> {accessGroups = [#[[$ATTR_0]]]} : !llvm.ptr -> i32
+// CHECK: %[[LOAD_1:.*]] = llvm.load %[[ALLOCA_1]] <access_groups = [#[[$ATTR_0]]]> : !llvm.ptr -> i32
+// CHECK: %[[LOAD_2:.*]] = llvm.load %[[ARG1]] <access_groups = [#[[$ATTR_0]]]> : !llvm.ptr -> i32
// CHECK: %[[ADD_0:.*]] = llvm.add %[[LOAD_1]], %[[LOAD_2]] : i32
// CHECK: %[[SITOFP_0:.*]] = llvm.sitofp %[[ADD_0]] : i32 to f32
// CHECK: %[[MLIR_5:.*]] = llvm.mlir.constant(72 : i32) : i32
// CHECK: "llvm.intr.memcpy"(%[[ALLOCA_0]], %[[ARG3]], %[[MLIR_5]]) <{access_groups = [#[[$ATTR_0]]], arg_attrs = [{llvm.align = 8 : i64}, {llvm.align = 8 : i64}, {}], isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()
-// CHECK: %[[LOAD_3:.*]] = llvm.load %[[ARG0]] <access_groups = [#[[$ATTR_0]]]> {accessGroups = [#[[$ATTR_0]]]} : !llvm.ptr -> i32
+// CHECK: %[[LOAD_3:.*]] = llvm.load %[[ARG0]] <access_groups = [#[[$ATTR_0]]]> : !llvm.ptr -> i32
// CHECK: %[[SEXT_1:.*]] = llvm.sext %[[LOAD_3]] : i32 to i64
// CHECK: %[[SEXT_2:.*]] = llvm.sext %[[LOAD_1]] : i32 to i64
// CHECK: %[[GETELEMENTPTR_0:.*]] = llvm.getelementptr %[[ALLOCA_0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
@@ -60,7 +60,7 @@
// CHECK: %[[MUL_5:.*]] = llvm.mul %[[MUL_2]], %[[LOAD_9]] overflow<nsw, nuw> : i64
// CHECK: %[[GETELEMENTPTR_7:.*]] = llvm.getelementptr nusw|nuw %[[LOAD_4]]{{\[}}%[[ADD_2]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
// CHECK: llvm.store %[[SITOFP_0]], %[[GETELEMENTPTR_7]] <access_groups = [#[[$ATTR_0]]]> : f32, !llvm.ptr
-// CHECK: %[[LOAD_11:.*]] = llvm.load %[[ALLOCA_1]] <access_groups = [#[[$ATTR_0]]]> {accessGroups = [#[[$ATTR_0]]]} : !llvm.ptr -> i32
+// CHECK: %[[LOAD_11:.*]] = llvm.load %[[ALLOCA_1]] <access_groups = [#[[$ATTR_0]]]> : !llvm.ptr -> i32
// CHECK: %[[ADD_3:.*]] = llvm.add %[[LOAD_11]], %[[TRUNC_0]] overflow<nsw> : i32
// CHECK: %[[SUB_2:.*]] = llvm.sub %[[VAL_1]], %[[MLIR_3]] : i64
// CHECK: llvm.br ^bb1(%[[ADD_3]], %[[SUB_2]] : i32, i64) loop_annotation = #[[$ATTR_1]]
More information about the flang-commits
mailing list