CIRCT 24.0.0git
Loading...
Searching...
No Matches
ArcCostModel.cpp
Go to the documentation of this file.
1//===- ArcCostModel.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
11#include "mlir/Dialect/Func/IR/FuncOps.h"
12#include <algorithm>
13
14using namespace circt;
15using namespace arc;
16using namespace std;
17
18// FIXME: May be refined and we have more accurate operation costs
30
32 return computeOperationCost(op);
33}
34
36 if (auto it = opCostCache.find(op); it != opCostCache.end())
37 return it->second;
38
39 OperationCosts costs;
40
41 if (isa<circt::comb::ConcatOp>(op))
43 else if (isa<circt::comb::ExtractOp>(op))
45 else if (auto vecOp = dyn_cast<arc::VectorizeOp>(op)) {
46 // VectorizeOpCost = packingCost + shufflingCost + bodyCost
47 OperationCosts inputVecCosts = getInputVectorsCost(vecOp);
48 costs.packingCost += inputVecCosts.packingCost;
49 costs.shufflingCost += inputVecCosts.shufflingCost;
50
51 for (auto &region : op->getRegions()) {
52 for (auto &block : region) {
53 for (auto &innerOp : block) {
54 OperationCosts innerCosts = computeOperationCost(&innerOp);
55 costs.vectorizeOpsBodyCost += innerCosts.totalCost();
56 }
57 }
58 }
59 } else if (auto callableOp = dyn_cast<CallOpInterface>(op)) {
60 // Callable Op? then resolve!
61 if (auto *calledOp = callableOp.resolveCallable())
62 return opCostCache[callableOp] = computeOperationCost(calledOp);
63 } else if (isa<func::FuncOp, arc::DefineOp, mlir::ModuleOp>(op)) {
64 // Get the body cost
65 for (auto &region : op->getRegions())
66 for (auto &block : region)
67 for (auto &innerOp : block)
68 costs += computeOperationCost(&innerOp);
69 } else
71
72 return opCostCache[op] = costs;
73}
74
76 OperationCosts costs;
77 for (auto inputVec : vecOp.getInputs()) {
78 if (auto otherVecOp = inputVec[0].getDefiningOp<VectorizeOp>();
79 llvm::all_of(inputVec, [&](auto element) {
80 return element.template getDefiningOp<VectorizeOp>() == otherVecOp;
81 })) {
82 // This means that they came from the same vector or
83 // VectorizeOp == null so they are all scalars
84
85 // Check if they all scalars we multiply by the PACKCOST (SHL/R + OR)
86 if (!otherVecOp)
87 costs.packingCost += inputVec.size() * size_t(OperationCost::PACKCOST);
88 else
89 costs.shufflingCost += inputVec == otherVecOp.getResults()
91 : getShufflingCost(inputVec, true);
92 } else
93 // inputVector consists of elements from different vectotrize ops and
94 // may have scalars as well.
95 costs.shufflingCost += getShufflingCost(inputVec);
96 }
97
98 return costs;
99}
100
101size_t ArcCostModel::getShufflingCost(const ValueRange &inputVec, bool isSame) {
102 size_t totalCost = 0;
103 if (isSame) {
104 auto vecOp = inputVec[0].getDefiningOp<VectorizeOp>();
105 for (auto [elem, orig] : llvm::zip(inputVec, vecOp.getResults()))
106 if (elem != orig)
107 ++totalCost;
108
109 return totalCost * size_t(OperationCost::SAMEVECTORSHUFFLECOST);
110 }
111
112 for (size_t i = 0; i < inputVec.size(); ++i) {
113 auto otherVecOp = inputVec[i].getDefiningOp<VectorizeOp>();
114 // If the element is not a result of a vector operation then it's a result
115 // of a scalar operation, then it just needs to be packed into the vector.
116 if (!otherVecOp)
117 totalCost += size_t(OperationCost::PACKCOST);
118 else {
119 // If it's a result of a vector operation, then we have two cases:
120 // (1) Its order in `inputVec` is the same as its order in the result of
121 // the defining op.
122 // (2) the order is different.
123 size_t idx = find(otherVecOp.getResults().begin(),
124 otherVecOp.getResults().end(), inputVec[i]) -
125 otherVecOp.getResults().begin();
126 totalCost += i == idx ? size_t(OperationCost::DIFFERENTVECTORNOSHUFFLE)
128 }
129 }
130 return totalCost;
131}
OperationCost
OperationCosts getInputVectorsCost(VectorizeOp vecOp)
DenseMap< Operation *, OperationCosts > opCostCache
OperationCosts computeOperationCost(Operation *op)
OperationCosts getCost(Operation *op)
size_t getShufflingCost(const ValueRange &inputVec, bool isSame=false)
Definition arc.py:1
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.