clang 22.0.0git
CIRCanonicalize.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements pass that canonicalizes CIR operations, eliminating
10// 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"
25
26using namespace mlir;
27using namespace cir;
28
29namespace mlir {
30#define GEN_PASS_DEF_CIRCANONICALIZE
31#include "clang/CIR/Dialect/Passes.h.inc"
32} // namespace mlir
33
34namespace {
35
36/// Removes branches between two blocks if it is the only branch.
37///
38/// From:
39/// ^bb0:
40/// cir.br ^bb1
41/// ^bb1: // pred: ^bb0
42/// cir.return
43///
44/// To:
45/// ^bb0:
46/// cir.return
47struct 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, cir::IndirectBrOp>(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
69//===----------------------------------------------------------------------===//
70// CIRCanonicalizePass
71//===----------------------------------------------------------------------===//
72
73struct CIRCanonicalizePass
74 : public impl::CIRCanonicalizeBase<CIRCanonicalizePass> {
75 using CIRCanonicalizeBase::CIRCanonicalizeBase;
76
77 // The same operation rewriting done here could have been performed
78 // by CanonicalizerPass (adding hasCanonicalizer for target Ops and
79 // implementing the same from above in CIRDialects.cpp). However, it's
80 // currently too aggressive for static analysis purposes, since it might
81 // remove things where a diagnostic can be generated.
82 //
83 // FIXME: perhaps we can add one more mode to GreedyRewriteConfig to
84 // disable this behavior.
85 void runOnOperation() override;
86};
87
88void populateCIRCanonicalizePatterns(RewritePatternSet &patterns) {
89 // clang-format off
90 patterns.add<
91 RemoveRedundantBranches
92 >(patterns.getContext());
93 // clang-format on
94}
95
96void CIRCanonicalizePass::runOnOperation() {
97 // Collect rewrite patterns.
98 RewritePatternSet patterns(&getContext());
99 populateCIRCanonicalizePatterns(patterns);
100
101 // Collect operations to apply patterns.
102 llvm::SmallVector<Operation *, 16> ops;
103 getOperation()->walk([&](Operation *op) {
106
107 // Many operations are here to perform a manual `fold` in
108 // applyOpPatternsGreedily.
109 if (isa<BrOp, BrCondOp, CastOp, ScopeOp, SwitchOp, SelectOp, UnaryOp,
110 ComplexCreateOp, ComplexImagOp, ComplexRealOp, VecCmpOp,
111 VecCreateOp, VecExtractOp, VecShuffleOp, VecShuffleDynamicOp,
112 VecTernaryOp, BitClrsbOp, BitClzOp, BitCtzOp, BitFfsOp, BitParityOp,
113 BitPopcountOp, BitReverseOp, ByteSwapOp, RotateOp>(op))
114 ops.push_back(op);
115 });
116
117 // Apply patterns.
118 if (applyOpPatternsGreedily(ops, std::move(patterns)).failed())
119 signalPassFailure();
120}
121
122} // namespace
123
124std::unique_ptr<Pass> mlir::createCIRCanonicalizePass() {
125 return std::make_unique<CIRCanonicalizePass>();
126}
std::unique_ptr< Pass > createCIRCanonicalizePass()