CIRCT 22.0.0git
Loading...
Searching...
No Matches
CombAnalysis.cpp
Go to the documentation of this file.
1//===- CombAnalysis.cpp - Analysis Helpers for Comb+HW operations ---------===//
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 "llvm/Support/KnownBits.h"
12
13using namespace circt;
14using namespace comb;
15
16/// Given an integer SSA value, check to see if we know anything about the
17/// result of the computation. For example, we know that "and with a constant"
18/// always returns zeros for the zero bits in a constant.
19///
20/// Expression trees can be very large, so we need ot make sure to cap our
21/// recursion, this is controlled by `depth`.
22static KnownBits computeKnownBits(Value v, unsigned depth) {
23 Operation *op = v.getDefiningOp();
24 if (!op || depth == 5)
25 return KnownBits(v.getType().getIntOrFloatBitWidth());
26
27 // A constant has all bits known!
28 if (auto constant = dyn_cast<hw::ConstantOp>(op))
29 return KnownBits::makeConstant(constant.getValue());
30
31 // `concat(x, y, z)` has whatever is known about the operands concat'd.
32 if (auto concatOp = dyn_cast<ConcatOp>(op)) {
33 auto result = computeKnownBits(concatOp.getOperand(0), depth + 1);
34 for (size_t i = 1, e = concatOp.getNumOperands(); i != e; ++i) {
35 auto otherBits = computeKnownBits(concatOp.getOperand(i), depth + 1);
36 unsigned width = otherBits.getBitWidth();
37 unsigned newWidth = result.getBitWidth() + width;
38 result.Zero =
39 (result.Zero.zext(newWidth) << width) | otherBits.Zero.zext(newWidth);
40 result.One =
41 (result.One.zext(newWidth) << width) | otherBits.One.zext(newWidth);
42 }
43 return result;
44 }
45
46 // `extract(x from y)` has whatever is known about the extracted bits of the
47 // operand.
48 if (auto extractOp = dyn_cast<ExtractOp>(op)) {
49 unsigned lowBit = extractOp.getLowBit();
50 unsigned width = extractOp.getType().getIntOrFloatBitWidth();
51 // Compute known bits of the input
52 KnownBits inputBits = computeKnownBits(extractOp.getInput(), depth + 1);
53 // Shift down to start at the extract position
54 APInt inputZero = inputBits.Zero.lshr(lowBit);
55 APInt inputOne = inputBits.One.lshr(lowBit);
56
57 // Truncate to the width of the extract result
58 APInt knownZero = inputZero.trunc(width);
59 APInt knownOne = inputOne.trunc(width);
60
61 KnownBits result(width);
62 result.Zero = knownZero;
63 result.One = knownOne;
64 return result;
65 }
66
67 // `and(x, y, z)` has whatever is known about the operands intersected.
68 if (auto andOp = dyn_cast<AndOp>(op)) {
69 auto result = computeKnownBits(andOp.getOperand(0), depth + 1);
70 for (size_t i = 1, e = andOp.getNumOperands(); i != e; ++i)
71 result &= computeKnownBits(andOp.getOperand(i), depth + 1);
72 return result;
73 }
74
75 // `or(x, y, z)` has whatever is known about the operands unioned.
76 if (auto orOp = dyn_cast<OrOp>(op)) {
77 auto result = computeKnownBits(orOp.getOperand(0), depth + 1);
78 for (size_t i = 1, e = orOp.getNumOperands(); i != e; ++i)
79 result |= computeKnownBits(orOp.getOperand(i), depth + 1);
80 return result;
81 }
82
83 // `xor(x, cst)` inverts known bits and passes through unmodified ones.
84 if (auto xorOp = dyn_cast<XorOp>(op)) {
85 auto result = computeKnownBits(xorOp.getOperand(0), depth + 1);
86 for (size_t i = 1, e = xorOp.getNumOperands(); i != e; ++i) {
87 // If we don't know anything, we don't need to evaluate more subexprs.
88 if (result.isUnknown())
89 return result;
90 result ^= computeKnownBits(xorOp.getOperand(i), depth + 1);
91 }
92 return result;
93 }
94
95 // `mux(cond, x, y)` is the intersection of the known bits of `x` and `y`.
96 if (auto muxOp = dyn_cast<MuxOp>(op)) {
97 auto lhs = computeKnownBits(muxOp.getTrueValue(), depth + 1);
98 auto rhs = computeKnownBits(muxOp.getFalseValue(), depth + 1);
99 return lhs.intersectWith(rhs);
100 }
101
102 // `shl(x, y)` is the known bits of `x` << known bits of `y`.
103 if (auto shlOp = dyn_cast<ShlOp>(op)) {
104 auto lhs = computeKnownBits(shlOp.getOperand(0), depth + 1);
105 auto rhs = computeKnownBits(shlOp.getOperand(1), depth + 1);
106 auto res = KnownBits::shl(lhs, rhs);
107 return res;
108 }
109
110 // `shr(x, y)` is the known bits of `x` >> known bits of `y`.
111 if (auto shrOp = dyn_cast<ShrUOp>(op)) {
112 auto lhs = computeKnownBits(shrOp.getOperand(0), depth + 1);
113 auto rhs = computeKnownBits(shrOp.getOperand(1), depth + 1);
114 auto res = KnownBits::lshr(lhs, rhs);
115 return res;
116 }
117
118 return KnownBits(v.getType().getIntOrFloatBitWidth());
119}
120
121/// Given an integer SSA value, check to see if we know anything about the
122/// result of the computation. For example, we know that "and with a
123/// constant" always returns zeros for the zero bits in a constant.
124KnownBits comb::computeKnownBits(Value value) {
125 return ::computeKnownBits(value, 0);
126}
static KnownBits computeKnownBits(Value v, unsigned depth)
Given an integer SSA value, check to see if we know anything about the result of the computation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition comb.py:1