Skip to content

Conversation

@Bynaryman
Copy link
Contributor

Implemented a convert-index-to-uint transform pass to rewrite index-typed arith.cmpi/constants back to their originating integer type (removing redundant arith.index_cast and dead index constants). This unblocks map-arith-to-comb and other hardware mappings that can’t legalize index arithmetic, e.g. after lowering scf.index_switch or any flow that leaves index compares.

Added pass definition/registration in include/circt/Transforms/Passes.{td,h} and implementation in lib/Transforms/ConvertIndexToUInt.cpp; wired into the transforms CMake.
New lit coverage (test/Transforms/convert-index-to-uint.mlir) exercises both plain index compares and switch-lowering cases to ensure index types disappear and compares run on the original integer widths.
Tests:

ninja -C build circt-opt
llvm-lit build/test/Transforms/convert-index-to-uint.mlir

@Bynaryman
Copy link
Contributor Author

@cowardsa This is another transform we have in our flow to go down to datapath dialect. Therefore I try to push it to upstream circt ! Thanks for looking at it.

Copy link
Contributor

@cowardsa cowardsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good - cool to see this pipeline progressing!

Would just split the tests please so we can isolate testing of the newly added pass as otherwise it could mask bugs.

@@ -0,0 +1,154 @@
//===- ConvertIndexToUInt.cpp - Rewrite index compares to integers --------===//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this header format is no longer required - can just use:
//===----------------------------------------------------------------------===//

//
//===----------------------------------------------------------------------===//
//
// Contains the definitions of the ConvertIndexToUInt pass.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: slightly redundant comment given the filename? I also think these are not entirely necessary if you see for example the datapath dialect files they do not have these comments

Comment on lines +42 to +43
if (!op.getLhs().getType().isIndex())
return failure();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: worth also checking Rhs? Or adding an assertion if you get past the lhs check that RHS is index type?

return failure();

auto convertOperand = [&](Value operand) -> FailureOr<Value> {
if (auto castOp = operand.getDefiningOp<arith::IndexCastOp>()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can we add a comment explaining what this block is matching and doing?

Comment on lines +76 to +81
Replace `arith.cmpi` operations whose operands are `index` values (often
produced when lowering `scf.index_switch`) with comparisons over the
original integer type so that downstream hardware mapping passes (e.g.
`--map-arith-to-comb`) do not encounter unsupported index-typed arithmetic.
The pass converts any associated index constants and erases the redundant
casts that become dead afterwards.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: a concrete example potentially one from the tests would help to understand what transformation is performed?

@@ -0,0 +1,81 @@
// RUN: circt-opt -split-input-file --switch-to-if --convert-index-to-uint --canonicalize %s | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general CIRCT tries to avoid chaining passes in tests - can you split this into two tests (possibly in the same file as is done here integration_test/circt-lec/comb.mlir)? That way we can isolate testing of convert-index-to-uint?

Comment on lines +152 to +154
std::unique_ptr<mlir::Pass> circt::createConvertIndexToUIntPass() {
return std::make_unique<ConvertIndexToUIntPass>();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uenoku - these definitions get automatically generated now right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not automatically generated if there is " let constructor = "circt::createConvertIndexToUIntPass()"; in pass definition so the current implementation looks good to me.

Comment on lines +33 to +42
%0 = scf.index_switch %switch_val -> i1
case 5 {
%t = arith.constant true
scf.yield %t : i1
}
default {
%f = arith.constant false
scf.yield %f : i1
}
return %0 : i1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once tests are split this will probably need to use different CHECK-*** labels - see examples in circt-lec tests of how to specify multiple filecheck labels

Comment on lines +55 to +56
// CHECK: %[[RES:.*]] = scf.if %[[CMP0]] -> (i1) {
// CHECK: } else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Is there a missing yield line here? for the return of the if branch?

@uenoku
Copy link
Member

uenoku commented Nov 27, 2025

I think inferring bitwidth for index based on cast(consant(c)) pattern seems to be a bit restrictive. As mentioned in #5297 it may be a better direction to lower index type to a specific bit width, and later narrow the width in comb dialect. WDYT?

Currently, this pass strictly does operation mapping. If needed, index-type conversion could also be moved to this pass (e.g. setting index type width as a parameter of the pass).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants