MLIR 22.0.0git
LegalizeForExport.cpp
Go to the documentation of this file.
1//===- LegalizeForExport.cpp - Prepare for translation to LLVM IR ---------===//
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
10
13#include "mlir/IR/Block.h"
14#include "mlir/IR/Builders.h"
15#include "mlir/Pass/Pass.h"
16
17namespace mlir {
18namespace LLVM {
19#define GEN_PASS_DEF_LLVMLEGALIZEFOREXPORTPASS
20#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
21} // namespace LLVM
22} // namespace mlir
23
24using namespace mlir;
25
26/// If the given block has the same successor with different arguments,
27/// introduce dummy successor blocks so that all successors of the given block
28/// are different.
30 // Early exit if the block cannot have successors.
32 return;
33
34 auto *terminator = bb.getTerminator();
35
36 // Find repeated successors with arguments.
37 llvm::SmallDenseMap<Block *, SmallVector<int, 4>> successorPositions;
38 for (int i = 0, e = terminator->getNumSuccessors(); i < e; ++i) {
39 Block *successor = terminator->getSuccessor(i);
40 // Blocks with no arguments are safe even if they appear multiple times
41 // because they don't need PHI nodes.
42 if (successor->getNumArguments() == 0)
43 continue;
44 successorPositions[successor].push_back(i);
45 }
46
47 // If a successor appears for the second or more time in the terminator,
48 // create a new dummy block that unconditionally branches to the original
49 // destination, and retarget the terminator to branch to this new block.
50 // There is no need to pass arguments to the dummy block because it will be
51 // dominated by the original block and can therefore use any values defined in
52 // the original block.
53 OpBuilder builder(terminator->getContext());
54 for (const auto &successor : successorPositions) {
55 // Start from the second occurrence of a block in the successor list.
56 for (int position : llvm::drop_begin(successor.second, 1)) {
57 Block *dummyBlock = builder.createBlock(bb.getParent());
58 terminator->setSuccessor(dummyBlock, position);
59 for (BlockArgument arg : successor.first->getArguments())
60 dummyBlock->addArgument(arg.getType(), arg.getLoc());
61 LLVM::BrOp::create(builder, terminator->getLoc(),
62 dummyBlock->getArguments(), successor.first);
63 }
64 }
65}
66
68 op->walk([](Operation *nested) {
69 for (Region &region : llvm::make_early_inc_range(nested->getRegions())) {
70 for (Block &block : llvm::make_early_inc_range(region)) {
72 }
73 }
74 });
75}
76
77namespace {
78struct LegalizeForExportPass
79 : public LLVM::impl::LLVMLegalizeForExportPassBase<LegalizeForExportPass> {
80 void runOnOperation() override {
81 LLVM::ensureDistinctSuccessors(getOperation());
83 }
84};
85} // namespace
static void ensureDistinctSuccessors(Block &bb)
If the given block has the same successor with different arguments, introduce dummy successor blocks ...
This class represents an argument of a Block.
Definition Value.h:309
Block represents an ordered list of Operations.
Definition Block.h:33
bool empty()
Definition Block.h:148
unsigned getNumArguments()
Definition Block.h:128
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition Block.cpp:27
Operation & back()
Definition Block.h:152
Operation * getTerminator()
Get the terminator operation of this block.
Definition Block.cpp:244
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:153
BlockArgListType getArguments()
Definition Block.h:87
Block * getSuccessor(unsigned i)
Definition Block.cpp:269
This class helps build Operations.
Definition Builders.h:207
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition Builders.cpp:430
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Definition Operation.h:757
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition Operation.h:677
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition Operation.h:797
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
void legalizeDIExpressionsRecursively(Operation *op)
Register all known legalization patterns declared here and apply them to all ops in op.
void ensureDistinctSuccessors(Operation *op)
Make argument-taking successors of each block distinct.
Include the generated interface declarations.