brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 2ef09b7 Raw
165 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements pass that canonicalizes CIR operations, eliminating10// redundant branches, empty scopes, and other unnecessary operations.11//12//===----------------------------------------------------------------------===//13 14#include "PassDetail.h"15#include "mlir/Dialect/Func/IR/FuncOps.h"16#include "mlir/IR/Block.h"17#include "mlir/IR/Operation.h"18#include "mlir/IR/PatternMatch.h"19#include "mlir/IR/Region.h"20#include "mlir/Support/LogicalResult.h"21#include "mlir/Transforms/GreedyPatternRewriteDriver.h"22#include "clang/CIR/Dialect/IR/CIRDialect.h"23#include "clang/CIR/Dialect/Passes.h"24#include "clang/CIR/MissingFeatures.h"25 26using namespace mlir;27using namespace cir;28 29namespace mlir {30#define GEN_PASS_DEF_CIRCANONICALIZE31#include "clang/CIR/Dialect/Passes.h.inc"32} // namespace mlir33 34namespace {35 36/// Removes branches between two blocks if it is the only branch.37///38/// From:39///   ^bb0:40///     cir.br ^bb141///   ^bb1:  // pred: ^bb042///     cir.return43///44/// To:45///   ^bb0:46///     cir.return47struct RemoveRedundantBranches : public OpRewritePattern<BrOp> {48  using OpRewritePattern<BrOp>::OpRewritePattern;49 50  LogicalResult matchAndRewrite(BrOp op,51                                PatternRewriter &rewriter) const final {52    Block *block = op.getOperation()->getBlock();53    Block *dest = op.getDest();54 55    if (isa<cir::LabelOp>(dest->front()))56      return failure();57    // Single edge between blocks: merge it.58    if (block->getNumSuccessors() == 1 &&59        dest->getSinglePredecessor() == block) {60      rewriter.eraseOp(op);61      rewriter.mergeBlocks(dest, block);62      return success();63    }64 65    return failure();66  }67};68 69struct RemoveEmptyScope : public OpRewritePattern<ScopeOp> {70  using OpRewritePattern<ScopeOp>::OpRewritePattern;71 72  LogicalResult matchAndRewrite(ScopeOp op,73                                PatternRewriter &rewriter) const final {74    // TODO: Remove this logic once CIR uses MLIR infrastructure to remove75    // trivially dead operations76    if (op.isEmpty()) {77      rewriter.eraseOp(op);78      return success();79    }80 81    Region &region = op.getScopeRegion();82    if (region.getBlocks().front().getOperations().size() == 1 &&83        isa<YieldOp>(region.getBlocks().front().front())) {84      rewriter.eraseOp(op);85      return success();86    }87 88    return failure();89  }90};91 92struct RemoveEmptySwitch : public OpRewritePattern<SwitchOp> {93  using OpRewritePattern<SwitchOp>::OpRewritePattern;94 95  LogicalResult matchAndRewrite(SwitchOp op,96                                PatternRewriter &rewriter) const final {97    if (!(op.getBody().empty() || isa<YieldOp>(op.getBody().front().front())))98      return failure();99 100    rewriter.eraseOp(op);101    return success();102  }103};104 105//===----------------------------------------------------------------------===//106// CIRCanonicalizePass107//===----------------------------------------------------------------------===//108 109struct CIRCanonicalizePass110    : public impl::CIRCanonicalizeBase<CIRCanonicalizePass> {111  using CIRCanonicalizeBase::CIRCanonicalizeBase;112 113  // The same operation rewriting done here could have been performed114  // by CanonicalizerPass (adding hasCanonicalizer for target Ops and115  // implementing the same from above in CIRDialects.cpp). However, it's116  // currently too aggressive for static analysis purposes, since it might117  // remove things where a diagnostic can be generated.118  //119  // FIXME: perhaps we can add one more mode to GreedyRewriteConfig to120  // disable this behavior.121  void runOnOperation() override;122};123 124void populateCIRCanonicalizePatterns(RewritePatternSet &patterns) {125  // clang-format off126  patterns.add<127    RemoveRedundantBranches,128    RemoveEmptyScope129  >(patterns.getContext());130  // clang-format on131}132 133void CIRCanonicalizePass::runOnOperation() {134  // Collect rewrite patterns.135  RewritePatternSet patterns(&getContext());136  populateCIRCanonicalizePatterns(patterns);137 138  // Collect operations to apply patterns.139  llvm::SmallVector<Operation *, 16> ops;140  getOperation()->walk([&](Operation *op) {141    assert(!cir::MissingFeatures::switchOp());142    assert(!cir::MissingFeatures::tryOp());143    assert(!cir::MissingFeatures::callOp());144 145    // Many operations are here to perform a manual `fold` in146    // applyOpPatternsGreedily.147    if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp,148            ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,149            VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,150            VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitFfsOp, BitParityOp,151            BitPopcountOp, BitReverseOp, ByteSwapOp, RotateOp>(op))152      ops.push_back(op);153  });154 155  // Apply patterns.156  if (applyOpPatternsGreedily(ops, std::move(patterns)).failed())157    signalPassFailure();158}159 160} // namespace161 162std::unique_ptr<Pass> mlir::createCIRCanonicalizePass() {163  return std::make_unique<CIRCanonicalizePass>();164}165