CIRCT  20.0.0git
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 
16 #include "circt/Dialect/HW/HWOps.h"
17 #include "mlir/Dialect/SCF/IR/SCF.h"
18 #include "mlir/Support/LLVM.h"
19 #include "llvm/ADT/TypeSwitch.h"
20 
21 using namespace mlir;
22 using namespace circt;
23 using namespace arc;
24 using namespace comb;
25 using namespace hw;
26 
27 //===----------------------------------------------------------------------===//
28 // Helpers
29 //===----------------------------------------------------------------------===//
30 
31 static 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 
43 namespace {
44 
45 class CombRuntimeCostEstimateDialectInterface
47  using RuntimeCostEstimateDialectInterface::
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 
75 class HWRuntimeCostEstimateDialectInterface
77  using RuntimeCostEstimateDialectInterface::
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 
94 class SCFRuntimeCostEstimateDialectInterface
96  using RuntimeCostEstimateDialectInterface::
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 getCostEstimate(const SmallPtrSetImpl< Operation * > &ops)
Simple helper to invoke the runtime cost interface for every operation in a set and sum up the costs.
static uint32_t sumNonConstantOperands(Operation *op, uint32_t perOperand)
A dialect interface to get runtime cost estimates of MLIR operations.
Definition: ArcInterfaces.h:39
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: DebugAnalysis.h:21
Definition: comb.py:1
Definition: hw.py:1