Skip to content

Comb Interval Range Analysis and Comb Opt Narrowing pass #8425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
13133f4
Adding initial template for range analysis pass - currently does not …
cowardsa Apr 9, 2025
683e67d
Implement first few basic integer range analysis interpretations for …
cowardsa Apr 9, 2025
3026ee6
Complete comb interval analysis implementation with the exception of …
cowardsa Apr 10, 2025
fdc061e
Detecting bits to be removed - not implementing the replacement yet -…
cowardsa Apr 10, 2025
4cbc064
Add pass that reduces every operation to its minimum bitwidth
cowardsa Apr 11, 2025
3a56e9d
Format code before publishing branch
cowardsa Apr 14, 2025
bac9024
Update with appropriate narrowing named pass - adjust dependencies an…
cowardsa Apr 15, 2025
ca34eaa
Add further testing of comb-int-range-narrowing pass
cowardsa Apr 16, 2025
aa0aed4
Update file names and add additional documentation - clean up for loo…
cowardsa Apr 16, 2025
d980446
Minor formatting updates
cowardsa Apr 17, 2025
0b36896
Intermediate fixes to EOF, working on swapping tests to REGEX and for…
cowardsa Apr 18, 2025
34a7d31
Replace variables with regex and minor fixes
cowardsa Apr 22, 2025
79b6a67
Addressing Martin's review comments - mostly coding guideline adherance
cowardsa Apr 22, 2025
d230660
Format tidy-up
cowardsa Apr 22, 2025
cec310b
Move comb op interfaces to common classes
cowardsa Apr 22, 2025
22bcbf9
Format operator definitions
cowardsa Apr 22, 2025
7cfe57a
Remove canonicalization pass from int-range-narrowing tests
cowardsa Apr 22, 2025
7457add
Add comb interval range analysis test pass - todo - add a test that a…
cowardsa Apr 23, 2025
a6c3417
Add test-comb-int-range-analysis pass and associated tests
cowardsa Apr 23, 2025
94696ca
Formatting corrections
cowardsa Apr 24, 2025
4e70663
Remove unused includes that broke windows build
cowardsa Apr 24, 2025
607eeab
Explicitly cast comb predicates, handle multioperand addition in narr…
cowardsa Apr 25, 2025
8aa10ed
Extend support to analyze (but not narrow) variadic operators
cowardsa Apr 25, 2025
688447b
Adding tests for replicate, extract and icmp of all variants
cowardsa Apr 25, 2025
72f6df2
Replace variables in test code with regex
cowardsa Apr 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/circt/Dialect/Comb/Comb.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

include "mlir/IR/OpBase.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/InferIntRangeInterface.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/SymbolInterfaces.td"

Expand Down
1 change: 1 addition & 0 deletions include/circt/Dialect/Comb/CombOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/Interfaces/FunctionInterfaces.h"
#include "mlir/Interfaces/InferIntRangeInterface.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"

Expand Down
8 changes: 8 additions & 0 deletions include/circt/Dialect/Comb/CombPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include <memory>
#include <optional>

namespace mlir {
class DataFlowSolver;
}

namespace circt {
namespace comb {

Expand All @@ -26,6 +30,10 @@ namespace comb {
#define GEN_PASS_REGISTRATION
#include "circt/Dialect/Comb/Passes.h.inc"

/// Add patterns for int range based narrowing.
void populateCombNarrowingPatterns(mlir::RewritePatternSet &patterns,
mlir::DataFlowSolver &solver);

} // namespace comb
} // namespace circt

Expand Down
36 changes: 26 additions & 10 deletions include/circt/Dialect/Comb/Combinational.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//

include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/InferIntRangeInterface.td"
include "mlir/IR/EnumAttr.td"

// Base class for binary operators.
Expand All @@ -30,7 +31,9 @@ class BinOp<string mnemonic, list<Trait> traits = []> :
// Binary operator with uniform input/result types.
class UTBinOp<string mnemonic, list<Trait> traits = []> :
BinOp<mnemonic,
traits # [SameTypeOperands, SameOperandsAndResultType]> {
traits # [SameTypeOperands, SameOperandsAndResultType,
DeclareOpInterfaceMethods<InferIntRangeInterface,
["inferResultRanges"]>]> {
let assemblyFormat = "(`bin` $twoState^)? $lhs `,` $rhs attr-dict `:` qualified(type($result))";
}

Expand All @@ -42,8 +45,10 @@ class VariadicOp<string mnemonic, list<Trait> traits = []> :
}

class UTVariadicOp<string mnemonic, list<Trait> traits = []> :
VariadicOp<mnemonic,
traits # [SameTypeOperands, SameOperandsAndResultType]> {
VariadicOp<mnemonic,
traits # [SameTypeOperands, SameOperandsAndResultType,
DeclareOpInterfaceMethods<InferIntRangeInterface,
["inferResultRanges"]>]> {

let hasCanonicalizeMethod = true;
let hasFolder = true;
Expand Down Expand Up @@ -76,7 +81,7 @@ let hasFolder = true in {
}

def AndOp : UTVariadicOp<"and", [Commutative]>;
def OrOp : UTVariadicOp<"or", [Commutative]>;
def OrOp : UTVariadicOp<"or", [Commutative]>;
def XorOp : UTVariadicOp<"xor", [Commutative]> {
let extraClassDeclaration = [{
/// Return true if this is a two operand xor with an all ones constant as
Expand Down Expand Up @@ -114,7 +119,10 @@ def ICmpPredicate : I64EnumAttr<
ICmpPredicateUGT, ICmpPredicateUGE, ICmpPredicateCEQ, ICmpPredicateCNE,
ICmpPredicateWEQ, ICmpPredicateWNE]>;

def ICmpOp : CombOp<"icmp", [Pure, SameTypeOperands]> {
def ICmpOp : CombOp<"icmp",
[Pure,
SameTypeOperands,
DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
let summary = "Compare two integer values";
let description = [{
This operation compares two integers using a predicate. If the predicate is
Expand Down Expand Up @@ -178,7 +186,9 @@ def ParityOp : UnaryI1ReductionOp<"parity">;
//===----------------------------------------------------------------------===//

// Extract a range of bits from the specified input.
def ExtractOp : CombOp<"extract", [Pure]> {
def ExtractOp : CombOp<"extract",
[Pure,
DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
let summary = "Extract a range of bits into a smaller value, lowBit "
"specifies the lowest bit included.";

Expand All @@ -203,7 +213,9 @@ def ExtractOp : CombOp<"extract", [Pure]> {
//===----------------------------------------------------------------------===//
// Other Operations
//===----------------------------------------------------------------------===//
def ConcatOp : CombOp<"concat", [InferTypeOpInterface, Pure]> {
def ConcatOp : CombOp<"concat",
[InferTypeOpInterface, Pure,
DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
let summary = "Concatenate a variadic list of operands together.";
let description = [{
See the comb rationale document for details on operand ordering.
Expand Down Expand Up @@ -237,7 +249,9 @@ def ConcatOp : CombOp<"concat", [InferTypeOpInterface, Pure]> {
}];
}

def ReplicateOp : CombOp<"replicate", [Pure]> {
def ReplicateOp : CombOp<"replicate",
[Pure,
DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
let summary = "Concatenate the operand a constant number of times";

let arguments = (ins HWIntegerType:$input);
Expand Down Expand Up @@ -267,8 +281,10 @@ def ReplicateOp : CombOp<"replicate", [Pure]> {
}

// Select one of two values based on a condition.
def MuxOp : CombOp<"mux",
[Pure, AllTypesMatch<["trueValue", "falseValue", "result"]>]> {
def MuxOp : CombOp<"mux",
[Pure, AllTypesMatch<["trueValue", "falseValue", "result"]>,
DeclareOpInterfaceMethods<InferIntRangeInterface,
["inferResultRangesFromOptional"]>]> {
let summary = "Return one or the other operand depending on a selector bit";
let description = [{
```
Expand Down
10 changes: 10 additions & 0 deletions include/circt/Dialect/Comb/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,14 @@ def LowerComb : Pass<"lower-comb"> {
}];
}

def CombIntRangeNarrowing : Pass<"comb-int-range-narrowing"> {
let summary = "Reduce comb operations bitwidth based on integer range analysis.";
let description = [{
Compute a basic value range analysis, by propagating integer intervals through the domain.
The analysis is limited by a lack of sign-extension operator in the comb dialect, leading to
an over-approximation. Particularly for signed arithmetic, a single interval
is often an over-approximation, a more precise analysis would require a union of intervals.
}];
}

#endif // CIRCT_DIALECT_COMB_PASSES_TD
5 changes: 4 additions & 1 deletion include/circt/Dialect/HW/HWMiscOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ include "circt/Dialect/HW/HWOpInterfaces.td"
include "circt/Dialect/HW/HWTypes.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/InferIntRangeInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"

def ConstantOp
: HWOp<"constant", [Pure, ConstantLike, FirstAttrDerivedResultType,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
DeclareOpInterfaceMethods<InferIntRangeInterface,
["inferResultRanges"]>]> {
let summary = "Produce a constant value";
let description = [{
The constant operation produces a constant value of standard integer type
Expand Down
1 change: 1 addition & 0 deletions include/circt/Dialect/HW/HWOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/FunctionInterfaces.h"
#include "mlir/Interfaces/InferIntRangeInterface.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "llvm/ADT/StringExtras.h"
Expand Down
69 changes: 69 additions & 0 deletions lib/Analysis/TestPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "circt/Dialect/FIRRTL/FIRRTLInstanceGraph.h"
#include "circt/Dialect/HW/HWInstanceGraph.h"
#include "circt/Scheduling/Problems.h"
#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
#include "mlir/Analysis/DataFlow/IntegerRangeAnalysis.h"
#include "mlir/Dialect/Affine/IR/AffineMemoryOpInterfaces.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
Expand All @@ -29,6 +31,7 @@

using namespace mlir;
using namespace mlir::affine;
using namespace mlir::dataflow;
using namespace circt;
using namespace circt::analysis;
using namespace circt::scheduling;
Expand Down Expand Up @@ -263,6 +266,69 @@ void FIRRTLInstanceInfoPass::runOnOperation() {
printModuleInfo(op, iInfo);
}

//===----------------------------------------------------------------------===//
// Comb IntRange Analysis
//===----------------------------------------------------------------------===//

namespace {
struct TestCombIntegerRangeAnalysisPass
: public PassWrapper<TestCombIntegerRangeAnalysisPass,
OperationPass<mlir::ModuleOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestCombIntegerRangeAnalysisPass)

void runOnOperation() override;
StringRef getArgument() const override {
return "test-comb-int-range-analysis";
}
StringRef getDescription() const override {
return "Perform integer range analysis on comb dialect and set results as "
"attributes.";
}
};
} // namespace

void TestCombIntegerRangeAnalysisPass::runOnOperation() {
Operation *op = getOperation();
MLIRContext *ctx = op->getContext();
DataFlowSolver solver;
solver.load<DeadCodeAnalysis>();
solver.load<IntegerRangeAnalysis>();
if (failed(solver.initializeAndRun(op)))
return signalPassFailure();

// Append the integer range analysis as an operation attribute.
op->walk([&](Operation *op) {
for (auto value : op->getResults()) {
if (auto *range = solver.lookupState<IntegerValueRangeLattice>(value)) {
// All analyzed comb operations should return a single result.
assert(op->getResults().size() == 1 &&
"Expected a single result for the operation analysis");
assert(!range->getValue().isUninitialized() &&
"Expected a valid range for the value");
auto interval = range->getValue().getValue();
auto smax = interval.smax();
auto smaxAttr =
IntegerAttr::get(IntegerType::get(ctx, smax.getBitWidth()), smax);
op->setAttr("smax", smaxAttr);
auto smin = interval.smin();
auto sminAttr =
IntegerAttr::get(IntegerType::get(ctx, smin.getBitWidth()), smin);
op->setAttr("smin", sminAttr);
auto umax = interval.umax();
auto umaxAttr = IntegerAttr::get(
IntegerType::get(ctx, umax.getBitWidth(), IntegerType::Unsigned),
umax);
op->setAttr("umax", umaxAttr);
auto umin = interval.umin();
auto uminAttr = IntegerAttr::get(
IntegerType::get(ctx, umin.getBitWidth(), IntegerType::Unsigned),
umin);
op->setAttr("umin", uminAttr);
}
}
});
}

//===----------------------------------------------------------------------===//
// Pass registration
//===----------------------------------------------------------------------===//
Expand All @@ -285,6 +351,9 @@ void registerAnalysisTestPasses() {
registerPass([]() -> std::unique_ptr<Pass> {
return std::make_unique<FIRRTLInstanceInfoPass>();
});
registerPass([]() -> std::unique_ptr<Pass> {
return std::make_unique<TestCombIntegerRangeAnalysisPass>();
});
}
} // namespace test
} // namespace circt
2 changes: 2 additions & 0 deletions lib/Dialect/Comb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_circt_dialect_library(CIRCTComb
CombOps.cpp
CombAnalysis.cpp
CombDialect.cpp
InferIntRangeInterfaceImpls.cpp

ADDITIONAL_HEADER_DIRS
${CIRCT_MAIN_INCLUDE_DIR}/circt/Dialect/Comb
Expand All @@ -19,6 +20,7 @@ add_circt_dialect_library(CIRCTComb
CIRCTHW
MLIRIR
MLIRInferTypeOpInterface
MLIRInferIntRangeInterface
)

add_dependencies(circt-headers MLIRCombIncGen MLIRCombEnumsIncGen)
Expand Down
Loading