From ebb53b6571580375bb8abacbb56ad2dbeee4a199 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Mon, 21 Jul 2025 20:58:00 +0800 Subject: [PATCH] [mlir][NFC] Use `hasOneBlock` instead of `llvm::hasSingleElement(region)` --- mlir/include/mlir/IR/OpDefinition.h | 2 +- mlir/include/mlir/Parser/Parser.h | 3 +-- mlir/lib/Analysis/SliceAnalysis.cpp | 2 +- mlir/lib/Dialect/Affine/IR/AffineOps.cpp | 2 +- mlir/lib/Dialect/GPU/Transforms/EliminateBarriers.cpp | 4 ++-- mlir/lib/Dialect/GPU/Transforms/MemoryPromotion.cpp | 3 +-- mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp | 3 +-- mlir/lib/Dialect/Linalg/Utils/Utils.cpp | 4 ++-- mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 2 +- mlir/lib/Dialect/SCF/IR/SCF.cpp | 4 ++-- mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp | 4 ++-- .../Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp | 3 +-- .../Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp | 5 ++--- mlir/lib/IR/SymbolTable.cpp | 4 ++-- .../LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp | 2 +- mlir/lib/Transforms/CSE.cpp | 5 ++--- mlir/lib/Transforms/Utils/RegionUtils.cpp | 4 ++-- mlir/test/lib/Analysis/TestCFGLoopInfo.cpp | 2 +- mlir/test/lib/Dialect/Test/TestPatterns.cpp | 2 +- 19 files changed, 27 insertions(+), 33 deletions(-) diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h index 883ece32967e4..be92fe0a6c7e3 100644 --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -889,7 +889,7 @@ struct SingleBlock : public TraitBase { continue; // Non-empty regions must contain a single basic block. - if (!llvm::hasSingleElement(region)) + if (!region.hasOneBlock()) return op->emitOpError("expects region #") << i << " to have 0 or 1 blocks"; diff --git a/mlir/include/mlir/Parser/Parser.h b/mlir/include/mlir/Parser/Parser.h index 828760fcbefa9..6683c2b4401d5 100644 --- a/mlir/include/mlir/Parser/Parser.h +++ b/mlir/include/mlir/Parser/Parser.h @@ -66,8 +66,7 @@ inline OwningOpRef constructContainerOpForParserIfNecessary( OpBuilder builder(context); ContainerOpT op = builder.create(sourceFileLoc); OwningOpRef opRef(op); - assert(op->getNumRegions() == 1 && - llvm::hasSingleElement(op->getRegion(0)) && + assert(op->getNumRegions() == 1 && op->getRegion(0).hasOneBlock() && "expected generated operation to have a single region with a single " "block"); Block *opBlock = &op->getRegion(0).front(); diff --git a/mlir/lib/Analysis/SliceAnalysis.cpp b/mlir/lib/Analysis/SliceAnalysis.cpp index 991c71e3f689a..7037fa644c7be 100644 --- a/mlir/lib/Analysis/SliceAnalysis.cpp +++ b/mlir/lib/Analysis/SliceAnalysis.cpp @@ -137,7 +137,7 @@ static LogicalResult getBackwardSliceImpl(Operation *op, // into us. For now, just bail. if (parentOp && backwardSlice->count(parentOp) == 0) { if (parentOp->getNumRegions() == 1 && - llvm::hasSingleElement(parentOp->getRegion(0).getBlocks())) { + parentOp->getRegion(0).hasOneBlock()) { return getBackwardSliceImpl(parentOp, visited, backwardSlice, options); } diff --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp index ee5db073ffc4e..8d7053c02fd84 100644 --- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp +++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp @@ -169,7 +169,7 @@ struct AffineInlinerInterface : public DialectInlinerInterface { // Multi-block regions cannot be inlined into affine constructs, all of // which require single-block regions. - if (!llvm::hasSingleElement(*src)) + if (!src->hasOneBlock()) return false; // Side-effecting operations that the affine dialect cannot understand diff --git a/mlir/lib/Dialect/GPU/Transforms/EliminateBarriers.cpp b/mlir/lib/Dialect/GPU/Transforms/EliminateBarriers.cpp index 57b529daa3c1e..9bf11c7905aa1 100644 --- a/mlir/lib/Dialect/GPU/Transforms/EliminateBarriers.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/EliminateBarriers.cpp @@ -158,7 +158,7 @@ getEffectsBefore(Operation *op, // If there is a non-structured control flow, bail. Region *region = op->getBlock()->getParent(); - if (region && !llvm::hasSingleElement(region->getBlocks())) { + if (region && !region->hasOneBlock()) { addAllValuelessEffects(effects); return false; } @@ -250,7 +250,7 @@ getEffectsAfter(Operation *op, // If there is a non-structured control flow, bail. Region *region = op->getBlock()->getParent(); - if (region && !llvm::hasSingleElement(region->getBlocks())) { + if (region && !region->hasOneBlock()) { addAllValuelessEffects(effects); return false; } diff --git a/mlir/lib/Dialect/GPU/Transforms/MemoryPromotion.cpp b/mlir/lib/Dialect/GPU/Transforms/MemoryPromotion.cpp index 14c44f27a6249..a93f658051276 100644 --- a/mlir/lib/Dialect/GPU/Transforms/MemoryPromotion.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/MemoryPromotion.cpp @@ -126,8 +126,7 @@ static void insertCopies(Region ®ion, Location loc, Value from, Value to) { (void)toType; assert(fromType.getShape() == toType.getShape()); assert(fromType.getRank() != 0); - assert(llvm::hasSingleElement(region) && - "unstructured control flow not supported"); + assert(region.hasOneBlock() && "unstructured control flow not supported"); auto b = ImplicitLocOpBuilder::atBlockBegin(loc, ®ion.front()); insertCopyLoops(b, from, to); diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp index 085ae4c93b829..f49d9a1eb96b5 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp @@ -1277,8 +1277,7 @@ LogicalResult mlir::linalg::detail::verifyStructuredOpInterface(Operation *op) { return op->emitOpError("expected the shape-to-loops map to be non-null"); // Check the region has exactly one block. - if (linalgOp->getNumRegions() != 1 || - !llvm::hasSingleElement(linalgOp->getRegion(0))) + if (linalgOp->getNumRegions() != 1 || !linalgOp->getRegion(0).hasOneBlock()) return op->emitOpError("expects to have 1 region with 1 block"); // Simplifying assumption: bbargs match 1-1 with shape operands elemental diff --git a/mlir/lib/Dialect/Linalg/Utils/Utils.cpp b/mlir/lib/Dialect/Linalg/Utils/Utils.cpp index e89e80b07d20d..14d62005e2a07 100644 --- a/mlir/lib/Dialect/Linalg/Utils/Utils.cpp +++ b/mlir/lib/Dialect/Linalg/Utils/Utils.cpp @@ -92,7 +92,7 @@ static bool isTiled(AffineMap map, ArrayRef tileSizes) { std::optional RegionMatcher::matchAsScalarBinaryOp(GenericOp op) { auto ®ion = op.getRegion(); - if (!llvm::hasSingleElement(region)) + if (!region.hasOneBlock()) return std::nullopt; Block &block = region.front(); @@ -204,7 +204,7 @@ bool allIndexingsAreProjectedPermutation(LinalgOp op) { } bool hasOnlyScalarElementwiseOp(Region &r) { - if (!llvm::hasSingleElement(r)) + if (!r.hasOneBlock()) return false; for (Operation &op : r.front()) { if (!(isa { /// using the operands of the block terminator to replace operation results. static void replaceOpWithRegion(PatternRewriter &rewriter, Operation *op, Region ®ion, ValueRange blockArgs = {}) { - assert(llvm::hasSingleElement(region) && "expected single-region block"); + assert(region.hasOneBlock() && "expected single-block region"); Block *block = ®ion.front(); Operation *terminator = block->getTerminator(); ValueRange results = terminator->getOperands(); diff --git a/mlir/lib/Dialect/SCF/IR/SCF.cpp b/mlir/lib/Dialect/SCF/IR/SCF.cpp index df41eba4ef533..d769f83ca1520 100644 --- a/mlir/lib/Dialect/SCF/IR/SCF.cpp +++ b/mlir/lib/Dialect/SCF/IR/SCF.cpp @@ -112,7 +112,7 @@ static TerminatorTy verifyAndGetTerminator(Operation *op, Region ®ion, /// using the operands of the block terminator to replace operation results. static void replaceOpWithRegion(PatternRewriter &rewriter, Operation *op, Region ®ion, ValueRange blockArgs = {}) { - assert(llvm::hasSingleElement(region) && "expected single-region block"); + assert(region.hasOneBlock() && "expected single-block region"); Block *block = ®ion.front(); Operation *terminator = block->getTerminator(); ValueRange results = terminator->getOperands(); @@ -184,7 +184,7 @@ struct SingleBlockExecuteInliner : public OpRewritePattern { LogicalResult matchAndRewrite(ExecuteRegionOp op, PatternRewriter &rewriter) const override { - if (!llvm::hasSingleElement(op.getRegion())) + if (!op.getRegion().hasOneBlock()) return failure(); replaceOpWithRegion(rewriter, op, op.getRegion()); return success(); diff --git a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp index 181a29ef70e82..9a68565450774 100644 --- a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp +++ b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp @@ -418,7 +418,7 @@ transform::LoopCoalesceOp::applyToOne(transform::TransformRewriter &rewriter, /// using the operands of the block terminator to replace operation results. static void replaceOpWithRegion(RewriterBase &rewriter, Operation *op, Region ®ion) { - assert(llvm::hasSingleElement(region) && "expected single-region block"); + assert(region.hasOneBlock() && "expected single-block region"); Block *block = ®ion.front(); Operation *terminator = block->getTerminator(); ValueRange results = terminator->getOperands(); @@ -434,7 +434,7 @@ DiagnosedSilenceableFailure transform::TakeAssumedBranchOp::applyToOne( rewriter.setInsertionPoint(ifOp); Region ®ion = getTakeElseBranch() ? ifOp.getElseRegion() : ifOp.getThenRegion(); - if (!llvm::hasSingleElement(region)) { + if (!region.hasOneBlock()) { return emitDefiniteFailure() << "requires an scf.if op with a single-block " << ((getTakeElseBranch()) ? "`else`" : "`then`") << " region"; diff --git a/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp index 99d021081f866..85093828efa96 100644 --- a/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp @@ -51,8 +51,7 @@ static Value castBuffer(OpBuilder &b, Value buffer, Type type) { static bool doesNotAliasExternalValue(Value value, Region *region, ValueRange exceptions, const OneShotAnalysisState &state) { - assert(llvm::hasSingleElement(region->getBlocks()) && - "expected region with single block"); + assert(region->hasOneBlock() && "expected region with single block"); bool result = true; state.applyOnAliases(value, [&](Value alias) { if (llvm::is_contained(exceptions, alias)) diff --git a/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp index 23a4266d6b780..e4054750b9fe5 100644 --- a/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp @@ -37,7 +37,7 @@ struct AssumingOpInterface size_t resultNum = std::distance(op->getOpResults().begin(), llvm::find(op->getOpResults(), value)); // TODO: Support multiple blocks. - assert(llvm::hasSingleElement(assumingOp.getDoRegion().getBlocks()) && + assert(assumingOp.getDoRegion().hasOneBlock() && "expected exactly 1 block"); auto yieldOp = dyn_cast( assumingOp.getDoRegion().front().getTerminator()); @@ -49,8 +49,7 @@ struct AssumingOpInterface const BufferizationOptions &options, BufferizationState &state) const { auto assumingOp = cast(op); - assert(llvm::hasSingleElement(assumingOp.getDoRegion().getBlocks()) && - "only 1 block supported"); + assert(assumingOp.getDoRegion().hasOneBlock() && "only 1 block supported"); auto yieldOp = cast( assumingOp.getDoRegion().front().getTerminator()); diff --git a/mlir/lib/IR/SymbolTable.cpp b/mlir/lib/IR/SymbolTable.cpp index aaa4d5617eb4f..07c311b64aa20 100644 --- a/mlir/lib/IR/SymbolTable.cpp +++ b/mlir/lib/IR/SymbolTable.cpp @@ -121,7 +121,7 @@ SymbolTable::SymbolTable(Operation *symbolTableOp) "expected operation to have SymbolTable trait"); assert(symbolTableOp->getNumRegions() == 1 && "expected operation to have a single region"); - assert(llvm::hasSingleElement(symbolTableOp->getRegion(0)) && + assert(symbolTableOp->getRegion(0).hasOneBlock() && "expected operation to have a single block"); StringAttr symbolNameId = StringAttr::get(symbolTableOp->getContext(), @@ -484,7 +484,7 @@ LogicalResult detail::verifySymbolTable(Operation *op) { if (op->getNumRegions() != 1) return op->emitOpError() << "Operations with a 'SymbolTable' must have exactly one region"; - if (!llvm::hasSingleElement(op->getRegion(0))) + if (!op->getRegion(0).hasOneBlock()) return op->emitOpError() << "Operations with a 'SymbolTable' must have exactly one block"; diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 3185f28fe6681..da39b19388627 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -898,7 +898,7 @@ static LogicalResult inlineConvertOmpRegions( // Special case for single-block regions that don't create additional blocks: // insert operations without creating additional blocks. - if (llvm::hasSingleElement(region)) { + if (region.hasOneBlock()) { llvm::Instruction *potentialTerminator = builder.GetInsertBlock()->empty() ? nullptr : &builder.GetInsertBlock()->back(); diff --git a/mlir/lib/Transforms/CSE.cpp b/mlir/lib/Transforms/CSE.cpp index 8e03f62894bab..4d09c5ff8ab2c 100644 --- a/mlir/lib/Transforms/CSE.cpp +++ b/mlir/lib/Transforms/CSE.cpp @@ -239,9 +239,8 @@ LogicalResult CSEDriver::simplifyOperation(ScopedMapTy &knownValues, // Don't simplify operations with regions that have multiple blocks. // TODO: We need additional tests to verify that we handle such IR correctly. - if (!llvm::all_of(op->getRegions(), [](Region &r) { - return r.getBlocks().empty() || llvm::hasSingleElement(r.getBlocks()); - })) + if (!llvm::all_of(op->getRegions(), + [](Region &r) { return r.empty() || r.hasOneBlock(); })) return failure(); // Some simple use case of operation with memory side-effect are dealt with diff --git a/mlir/lib/Transforms/Utils/RegionUtils.cpp b/mlir/lib/Transforms/Utils/RegionUtils.cpp index 353f8a58b3ace..a1d975dfb1476 100644 --- a/mlir/lib/Transforms/Utils/RegionUtils.cpp +++ b/mlir/lib/Transforms/Utils/RegionUtils.cpp @@ -417,7 +417,7 @@ static LogicalResult deleteDeadness(RewriterBase &rewriter, for (Region ®ion : regions) { if (region.empty()) continue; - bool hasSingleBlock = llvm::hasSingleElement(region); + bool hasSingleBlock = region.hasOneBlock(); // Delete every operation that is not live. Graph regions may have cycles // in the use-def graph, so we must explicitly dropAllUses() from each @@ -850,7 +850,7 @@ LogicalResult BlockMergeCluster::merge(RewriterBase &rewriter) { /// failure otherwise. static LogicalResult mergeIdenticalBlocks(RewriterBase &rewriter, Region ®ion) { - if (region.empty() || llvm::hasSingleElement(region)) + if (region.empty() || region.hasOneBlock()) return failure(); // Identify sets of blocks, other than the entry block, that branch to the diff --git a/mlir/test/lib/Analysis/TestCFGLoopInfo.cpp b/mlir/test/lib/Analysis/TestCFGLoopInfo.cpp index 7535994955f57..a4a8bfbb2178f 100644 --- a/mlir/test/lib/Analysis/TestCFGLoopInfo.cpp +++ b/mlir/test/lib/Analysis/TestCFGLoopInfo.cpp @@ -53,7 +53,7 @@ void TestCFGLoopInfo::runOnOperation() { } llvm::errs() << "\n"; - if (llvm::hasSingleElement(region.getBlocks())) { + if (region.hasOneBlock()) { llvm::errs() << "no loops\n"; return; } diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp b/mlir/test/lib/Dialect/Test/TestPatterns.cpp index 6b22b171822ae..b4aeccf2a46af 100644 --- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp +++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp @@ -2114,7 +2114,7 @@ struct TestMergeBlocksPatternDriver /// Expect the op to have a single block after legalization. target.addDynamicallyLegalOp( [&](TestMergeBlocksOp op) -> bool { - return llvm::hasSingleElement(op.getBody()); + return op.getBody().hasOneBlock(); }); /// Only allow `test.br` within test.merge_blocks op.