CIRCT 20.0.0git
Loading...
Searching...
No Matches
RuntimeCostEstimateInterfaceImpl.cpp
Go to the documentation of this file.
1//===- RuntimeCostEstimateInterfaceImpl.cpp -------------------------------===//
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// Implements the RuntimeCostEstimateDialectInterface for various dialects and
10// exposes them using registration functions.
11//
12//===----------------------------------------------------------------------===//
13
17#include "mlir/Dialect/SCF/IR/SCF.h"
18#include "mlir/Support/LLVM.h"
19#include "llvm/ADT/TypeSwitch.h"
20
21using namespace mlir;
22using namespace circt;
23using namespace arc;
24using namespace comb;
25using namespace hw;
26
27//===----------------------------------------------------------------------===//
28// Helpers
29//===----------------------------------------------------------------------===//
30
31static uint32_t sumNonConstantOperands(Operation *op, uint32_t perOperand) {
32 uint32_t count = 0;
33 for (auto operand : op->getOperands())
34 if (!operand.template getDefiningOp<ConstantOp>())
35 count += perOperand;
36 return count;
37}
38
39//===----------------------------------------------------------------------===//
40// Dialect interface implementations
41//===----------------------------------------------------------------------===//
42
43namespace {
44
45class CombRuntimeCostEstimateDialectInterface
48 RuntimeCostEstimateDialectInterface;
49
50 uint32_t getCostEstimate(mlir::Operation *op) const final {
51 assert(isa<CombDialect>(op->getDialect()));
52
53 return TypeSwitch<Operation *, uint32_t>(op)
54 // ExtractOp is either lowered to shift+AND or only an AND operation.
55 // Due to the high throughput of these simple ops, the real cost is
56 // likely lower than the 1 or 2 cycles.
57 .Case<ExtractOp>([](auto op) { return (op.getLowBit() > 0) * 4 + 4; })
58 // TODO: improve this measure as it might lower to a sext or a mul
59 .Case<ReplicateOp>([](auto op) { return 20; })
60 .Case<MuxOp, ShlOp, ShrUOp, ShrSOp, SubOp, ICmpOp>(
61 [](auto op) { return 10; })
62 // NOTE: provided that the ISA has a popcount operation that takes 1
63 // cycle
64 .Case<ParityOp>([](auto op) { return 20; })
65 // NOTE: processor performance varies a lot for these operations
66 .Case<DivUOp, DivSOp, ModUOp, ModSOp>([](auto op) { return 100; })
67 .Case<MulOp>([](auto op) { return (op->getNumOperands() - 1) * 30; })
68 .Case<AddOp, AndOp, OrOp, XorOp>(
69 [](auto op) { return (op->getNumOperands() - 1) * 10; })
70 .Case<ConcatOp>(
71 std::bind(&sumNonConstantOperands, std::placeholders::_1, 20));
72 }
73};
74
75class HWRuntimeCostEstimateDialectInterface
78 RuntimeCostEstimateDialectInterface;
79
80 uint32_t getCostEstimate(mlir::Operation *op) const final {
81 assert(circt::isa<HWDialect>(op->getDialect()));
82
83 return llvm::TypeSwitch<mlir::Operation *, uint32_t>(op)
84 .Case<ConstantOp, EnumConstantOp, BitcastOp, AggregateConstantOp>(
85 [](auto op) { return 0; })
86 .Case<ArrayGetOp, StructExtractOp, StructInjectOp, UnionExtractOp>(
87 [](auto op) { return 10; })
88 .Case<ArrayCreateOp, StructCreateOp, StructExplodeOp, UnionCreateOp>(
89 std::bind(&sumNonConstantOperands, std::placeholders::_1, 10));
90 // TODO: ArraySliceOp, ArrayConcatOp
91 }
92};
93
94class SCFRuntimeCostEstimateDialectInterface
97 RuntimeCostEstimateDialectInterface;
98
99 uint32_t getCostEstimate(mlir::Operation *op) const final {
100 assert(isa<scf::SCFDialect>(op->getDialect()));
101
102 return llvm::TypeSwitch<mlir::Operation *, uint32_t>(op)
103 .Case<scf::YieldOp>([](auto op) { return 0; })
104 // TODO: this is chosen quite arbitrarily right now
105 .Case<scf::IfOp>([](auto op) { return 20; });
106 }
107};
108
109} // namespace
110
111//===----------------------------------------------------------------------===//
112// Registration functions
113//===----------------------------------------------------------------------===//
114
116 mlir::DialectRegistry &registry) {
117 registry.addExtension(+[](MLIRContext *ctx, comb::CombDialect *dialect) {
118 dialect->addInterfaces<CombRuntimeCostEstimateDialectInterface>();
119 });
120}
121
123 mlir::DialectRegistry &registry) {
124 registry.addExtension(+[](MLIRContext *ctx, hw::HWDialect *dialect) {
125 dialect->addInterfaces<HWRuntimeCostEstimateDialectInterface>();
126 });
127}
128
130 mlir::DialectRegistry &registry) {
131 registry.addExtension(+[](MLIRContext *ctx, scf::SCFDialect *dialect) {
132 dialect->addInterfaces<SCFRuntimeCostEstimateDialectInterface>();
133 });
134}
assert(baseType &&"element must be base type")
static uint32_t sumNonConstantOperands(Operation *op, uint32_t perOperand)
A dialect interface to get runtime cost estimates of MLIR operations.
virtual uint32_t getCostEstimate(mlir::Operation *op) const =0
Returns a number indicating the expected number of cycles the given operation will take to execute on...
void registerCombRuntimeCostEstimateInterface(mlir::DialectRegistry &registry)
void registerSCFRuntimeCostEstimateInterface(mlir::DialectRegistry &registry)
void registerHWRuntimeCostEstimateInterface(mlir::DialectRegistry &registry)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition comb.py:1
Definition hw.py:1