MLIR  19.0.0git
Transforms.cpp
Go to the documentation of this file.
1 //===- Transforms.cpp - Patterns and transforms for the EmitC dialect -----===//
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 
11 #include "mlir/IR/IRMapping.h"
12 #include "mlir/IR/PatternMatch.h"
13 #include "llvm/Support/Debug.h"
14 
15 namespace mlir {
16 namespace emitc {
17 
18 ExpressionOp createExpression(Operation *op, OpBuilder &builder) {
19  assert(op->hasTrait<OpTrait::emitc::CExpression>() &&
20  "Expected a C expression");
21 
22  // Create an expression yielding the value returned by op.
23  assert(op->getNumResults() == 1 && "Expected exactly one result");
24  Value result = op->getResult(0);
25  Type resultType = result.getType();
26  Location loc = op->getLoc();
27 
28  builder.setInsertionPointAfter(op);
29  auto expressionOp = builder.create<emitc::ExpressionOp>(loc, resultType);
30 
31  // Replace all op's uses with the new expression's result.
32  result.replaceAllUsesWith(expressionOp.getResult());
33 
34  // Create an op to yield op's value.
35  Region &region = expressionOp.getRegion();
36  Block &block = region.emplaceBlock();
37  builder.setInsertionPointToEnd(&block);
38  auto yieldOp = builder.create<emitc::YieldOp>(loc, result);
39 
40  // Move op into the new expression.
41  op->moveBefore(yieldOp);
42 
43  return expressionOp;
44 }
45 
46 } // namespace emitc
47 } // namespace mlir
48 
49 using namespace mlir;
50 using namespace mlir::emitc;
51 
52 namespace {
53 
54 struct FoldExpressionOp : public OpRewritePattern<ExpressionOp> {
56  LogicalResult matchAndRewrite(ExpressionOp expressionOp,
57  PatternRewriter &rewriter) const override {
58  bool anythingFolded = false;
59  for (Operation &op : llvm::make_early_inc_range(
60  expressionOp.getBody()->without_terminator())) {
61  // Don't fold expressions whose result value has its address taken.
62  auto applyOp = dyn_cast<emitc::ApplyOp>(op);
63  if (applyOp && applyOp.getApplicableOperator() == "&")
64  continue;
65 
66  for (Value operand : op.getOperands()) {
67  auto usedExpression =
68  dyn_cast_if_present<ExpressionOp>(operand.getDefiningOp());
69 
70  if (!usedExpression)
71  continue;
72 
73  // Don't fold expressions with multiple users: assume any
74  // re-materialization was done separately.
75  if (!usedExpression.getResult().hasOneUse())
76  continue;
77 
78  // Don't fold expressions with side effects.
79  if (usedExpression.hasSideEffects())
80  continue;
81 
82  // Fold the used expression into this expression by cloning all
83  // instructions in the used expression just before the operation using
84  // its value.
85  rewriter.setInsertionPoint(&op);
86  IRMapping mapper;
87  for (Operation &opToClone :
88  usedExpression.getBody()->without_terminator()) {
89  Operation *clone = rewriter.clone(opToClone, mapper);
90  mapper.map(&opToClone, clone);
91  }
92 
93  Operation *expressionRoot = usedExpression.getRootOp();
94  Operation *clonedExpressionRootOp = mapper.lookup(expressionRoot);
95  assert(clonedExpressionRootOp &&
96  "Expected cloned expression root to be in mapper");
97  assert(clonedExpressionRootOp->getNumResults() == 1 &&
98  "Expected cloned root to have a single result");
99 
100  rewriter.replaceOp(usedExpression, clonedExpressionRootOp);
101  anythingFolded = true;
102  }
103  }
104  return anythingFolded ? success() : failure();
105  }
106 };
107 
108 } // namespace
109 
111  patterns.add<FoldExpressionOp>(patterns.getContext());
112 }
Block represents an ordered list of Operations.
Definition: Block.h:30
This is a utility class for mapping one set of IR entities to another.
Definition: IRMapping.h:26
auto lookup(T from) const
Lookup a mapped value within the map.
Definition: IRMapping.h:72
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
Definition: IRMapping.h:30
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
This class helps build Operations.
Definition: Builders.h:209
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
Definition: Builders.cpp:555
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:400
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:438
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:464
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Definition: Builders.h:414
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:745
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:402
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:373
void moveBefore(Operation *existingOp)
Unlink this operation from its current block and insert it right before existingOp which may be in th...
Definition: Operation.cpp:555
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:399
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:785
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
Block & emplaceBlock()
Definition: Region.h:46
MLIRContext * getContext() const
Definition: PatternMatch.h:822
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Definition: PatternMatch.h:846
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
Type getType() const
Return the type of this value.
Definition: Value.h:129
void replaceAllUsesWith(Value newValue)
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
Definition: Value.h:173
void populateExpressionPatterns(RewritePatternSet &patterns)
Populates patterns with expression-related patterns.
Definition: Transforms.cpp:110
ExpressionOp createExpression(Operation *op, OpBuilder &builder)
Definition: Transforms.cpp:18
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
Definition: PatternMatch.h:358