Path: blob/main/contrib/llvm-project/clang/lib/CIR/Dialect/Transforms/CIRCanonicalize.cpp
213845 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements pass that canonicalizes CIR operations, eliminating9// redundant branches, empty scopes, and other unnecessary operations.10//11//===----------------------------------------------------------------------===//1213#include "PassDetail.h"14#include "mlir/Dialect/Func/IR/FuncOps.h"15#include "mlir/IR/Block.h"16#include "mlir/IR/Operation.h"17#include "mlir/IR/PatternMatch.h"18#include "mlir/IR/Region.h"19#include "mlir/Support/LogicalResult.h"20#include "mlir/Transforms/GreedyPatternRewriteDriver.h"21#include "clang/CIR/Dialect/IR/CIRDialect.h"22#include "clang/CIR/Dialect/Passes.h"23#include "clang/CIR/MissingFeatures.h"2425using namespace mlir;26using namespace cir;2728namespace {2930/// Removes branches between two blocks if it is the only branch.31///32/// From:33/// ^bb0:34/// cir.br ^bb135/// ^bb1: // pred: ^bb036/// cir.return37///38/// To:39/// ^bb0:40/// cir.return41struct RemoveRedundantBranches : public OpRewritePattern<BrOp> {42using OpRewritePattern<BrOp>::OpRewritePattern;4344LogicalResult matchAndRewrite(BrOp op,45PatternRewriter &rewriter) const final {46Block *block = op.getOperation()->getBlock();47Block *dest = op.getDest();4849assert(!cir::MissingFeatures::labelOp());5051// Single edge between blocks: merge it.52if (block->getNumSuccessors() == 1 &&53dest->getSinglePredecessor() == block) {54rewriter.eraseOp(op);55rewriter.mergeBlocks(dest, block);56return success();57}5859return failure();60}61};6263struct RemoveEmptyScope : public OpRewritePattern<ScopeOp> {64using OpRewritePattern<ScopeOp>::OpRewritePattern;6566LogicalResult matchAndRewrite(ScopeOp op,67PatternRewriter &rewriter) const final {68// TODO: Remove this logic once CIR uses MLIR infrastructure to remove69// trivially dead operations70if (op.isEmpty()) {71rewriter.eraseOp(op);72return success();73}7475Region ®ion = op.getScopeRegion();76if (region.getBlocks().front().getOperations().size() == 1 &&77isa<YieldOp>(region.getBlocks().front().front())) {78rewriter.eraseOp(op);79return success();80}8182return failure();83}84};8586struct RemoveEmptySwitch : public OpRewritePattern<SwitchOp> {87using OpRewritePattern<SwitchOp>::OpRewritePattern;8889LogicalResult matchAndRewrite(SwitchOp op,90PatternRewriter &rewriter) const final {91if (!(op.getBody().empty() || isa<YieldOp>(op.getBody().front().front())))92return failure();9394rewriter.eraseOp(op);95return success();96}97};9899//===----------------------------------------------------------------------===//100// CIRCanonicalizePass101//===----------------------------------------------------------------------===//102103struct CIRCanonicalizePass : public CIRCanonicalizeBase<CIRCanonicalizePass> {104using CIRCanonicalizeBase::CIRCanonicalizeBase;105106// The same operation rewriting done here could have been performed107// by CanonicalizerPass (adding hasCanonicalizer for target Ops and108// implementing the same from above in CIRDialects.cpp). However, it's109// currently too aggressive for static analysis purposes, since it might110// remove things where a diagnostic can be generated.111//112// FIXME: perhaps we can add one more mode to GreedyRewriteConfig to113// disable this behavior.114void runOnOperation() override;115};116117void populateCIRCanonicalizePatterns(RewritePatternSet &patterns) {118// clang-format off119patterns.add<120RemoveRedundantBranches,121RemoveEmptyScope122>(patterns.getContext());123// clang-format on124}125126void CIRCanonicalizePass::runOnOperation() {127// Collect rewrite patterns.128RewritePatternSet patterns(&getContext());129populateCIRCanonicalizePatterns(patterns);130131// Collect operations to apply patterns.132llvm::SmallVector<Operation *, 16> ops;133getOperation()->walk([&](Operation *op) {134assert(!cir::MissingFeatures::switchOp());135assert(!cir::MissingFeatures::tryOp());136assert(!cir::MissingFeatures::complexRealOp());137assert(!cir::MissingFeatures::complexImagOp());138assert(!cir::MissingFeatures::callOp());139140// Many operations are here to perform a manual `fold` in141// applyOpPatternsGreedily.142if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp,143ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,144VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,145VecTernaryOp>(op))146ops.push_back(op);147});148149// Apply patterns.150if (applyOpPatternsGreedily(ops, std::move(patterns)).failed())151signalPassFailure();152}153154} // namespace155156std::unique_ptr<Pass> mlir::createCIRCanonicalizePass() {157return std::make_unique<CIRCanonicalizePass>();158}159160161