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