From 0c5c45f15871852aea7e4838c981903979272afb Mon Sep 17 00:00:00 2001 From: XLS Team Date: Tue, 27 Oct 2026 04:14:35 -0700 Subject: [PATCH] [DSLX] Re-enable tuple-array loop tests and prefix_scan IR lowering. Now that tuple destructuring in `for`-loop array iterators is supported during IR conversion (https://github.com/google/xls/issues/5125, https://github.com/google/xls/issues/1289), tests and examples that worked around or disabled IR lowering for `std::enumerate` loops can use direct tuple destructuring and full IR conversion. - Re-enable `IrConverterTest.LoopThroughTupleArray` in `xls/dslx/ir_convert/ir_converter_match_test.cc` and add its golden IR file (`ir_converter_test_LoopThroughTupleArray.ir`). - Destructure `(i, elem)` / `(i, e)` directly in the `for`-loop header of `prefix_scan_eq` in `xls/examples/dslx_intro/prefix_scan_equality.x`, `docs_src/tutorials/prefix_scan.md`, and `docs_src/dslx_reference.md`, removing the `TODO(https://github.com/google/xls/issues/5125)` workarounds. - Enable IR conversion, optimization, and JIT comparison for `prefix_scan_equality` in `xls/examples/dslx_intro/BUILD` by adding `prefix_scan_equality` (`xls_dslx_opt_ir`) and `prefix_scan_equality_test` (`xls_dslx_opt_ir_test`) and setting `dslx_test_args = {"compare": "jit"}` on `prefix_scan_equality_dslx_test`. PiperOrigin-RevId: 1007990718 --- docs_src/dslx_reference.md | 6 +---- docs_src/tutorials/prefix_scan.md | 5 +--- .../ir_convert/ir_converter_match_test.cc | 4 +-- ...ir_converter_test_LoopThroughTupleArray.ir | 27 +++++++++++++++++++ xls/examples/dslx_intro/BUILD | 19 ++++++++----- .../dslx_intro/prefix_scan_equality.x | 5 +--- 6 files changed, 44 insertions(+), 22 deletions(-) create mode 100644 xls/dslx/ir_convert/testdata/ir_converter_test_LoopThroughTupleArray.ir diff --git a/docs_src/dslx_reference.md b/docs_src/dslx_reference.md index 68c868aef3..6923f028e5 100644 --- a/docs_src/dslx_reference.md +++ b/docs_src/dslx_reference.md @@ -1617,11 +1617,7 @@ ranging from 0 to 7 and the value at the index `e = x[i]`. ``` fn prefix_scan_eq(x: u32[8]) -> u3[8] { let (_, _, result) = - // TODO(https://github.com/google/xls/issues/5125): Destructure `(i, e)` in - // the `for` loop header once supported during IR conversion. - for (item, (prior, count, result)) in std::enumerate(x) { - let (i, e) = item; - ... + for ((i, e), (prior, count, result)) in std::enumerate(x) {... ``` ### `for` Expression diff --git a/docs_src/tutorials/prefix_scan.md b/docs_src/tutorials/prefix_scan.md index a57614e97d..daad4f232a 100644 --- a/docs_src/tutorials/prefix_scan.md +++ b/docs_src/tutorials/prefix_scan.md @@ -80,11 +80,8 @@ Using tuples as the accumulator is a convenient way to model multiple loop-carried values: ```dslx-snippet - // TODO(https://github.com/google/xls/issues/5125): Destructure `(i, elem)` - // in the `for` loop header once supported during IR conversion. - for (item, (prior, count, result)): ((u32, u32), (u32, u3, u3[8])) + for ((i, elem), (prior, count, result)): ((u32, u32), (u32, u3, u3[8])) in std::enumerate(x) { - let (i, elem) = item; ``` The iterable of this loop is created by `std::enumerate(x)`. On each iteration, diff --git a/xls/dslx/ir_convert/ir_converter_match_test.cc b/xls/dslx/ir_convert/ir_converter_match_test.cc index 93889ac2be..2ed6bec180 100644 --- a/xls/dslx/ir_convert/ir_converter_match_test.cc +++ b/xls/dslx/ir_convert/ir_converter_match_test.cc @@ -305,9 +305,7 @@ fn f(x: u2) -> u8 { ExpectIr(converted); } -// TODO: github.com/google/xls/issues/1289 - Need to support this to enumerate -// in a for-loop. -TEST_F(IrConverterTest, DISABLED_LoopThroughTupleArray) { +TEST_F(IrConverterTest, LoopThroughTupleArray) { constexpr std::string_view program = R"( pub fn make_bool_array() -> bool[2] { let enumerated = [(u32:0, u32:0), (u32:1, u32:1)]; diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_LoopThroughTupleArray.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_LoopThroughTupleArray.ir new file mode 100644 index 0000000000..f312b7b952 --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_LoopThroughTupleArray.ir @@ -0,0 +1,27 @@ +package test_module + +file_number 0 "test_module.x" + +fn ____test_module__make_bool_array_counted_for_0_body(__index: bits[32] id=9, x: bits[1][2] id=10, __indexable: (bits[32], bits[32])[2] id=11) -> bits[1][2] { + array_index.12: (bits[32], bits[32]) = array_index(__indexable, indices=[__index], id=12) + literal.15: bits[1] = literal(value=1, id=15) + i: bits[32] = tuple_index(array_index.12, index=1, id=14) + tuple_index.13: bits[32] = tuple_index(array_index.12, index=0, id=13) + ret array_update.16: bits[1][2] = array_update(x, literal.15, indices=[i], id=16) +} + +fn __test_module__make_bool_array() -> bits[1][2] { + literal.1: bits[32] = literal(value=0, id=1) + literal.2: bits[32] = literal(value=0, id=2) + literal.4: bits[32] = literal(value=1, id=4) + literal.5: bits[32] = literal(value=1, id=5) + tuple.3: (bits[32], bits[32]) = tuple(literal.1, literal.2, id=3) + tuple.6: (bits[32], bits[32]) = tuple(literal.4, literal.5, id=6) + literal.8: bits[1][2] = literal(value=[0, 0], id=8) + enumerated: (bits[32], bits[32])[2] = array(tuple.3, tuple.6, id=7) + ret counted_for.17: bits[1][2] = counted_for(literal.8, trip_count=2, stride=1, body=____test_module__make_bool_array_counted_for_0_body, invariant_args=[enumerated], id=17) +} + +top fn __test_module__main() -> bits[1][2] { + ret invoke.18: bits[1][2] = invoke(to_apply=__test_module__make_bool_array, id=18) +} diff --git a/xls/examples/dslx_intro/BUILD b/xls/examples/dslx_intro/BUILD index 26b6ca19ea..3205c17109 100644 --- a/xls/examples/dslx_intro/BUILD +++ b/xls/examples/dslx_intro/BUILD @@ -56,15 +56,22 @@ xls_dslx_opt_ir_test( dep = ":crc32_one_byte_inferred", ) -# TODO: Remove `lower_to_ir` flag once the support for std::enumerate -# is merged: https://github.com/google/xls/pull/3816 +xls_dslx_opt_ir( + name = "prefix_scan_equality", + srcs = ["prefix_scan_equality.x"], + dslx_top = "prefix_scan_eq", + ir_conv_args = {"lower_to_proc_scoped_channels": "true"}, +) + +xls_dslx_opt_ir_test( + name = "prefix_scan_equality_test", + dep = ":prefix_scan_equality", +) + xls_dslx_test( name = "prefix_scan_equality_dslx_test", srcs = ["prefix_scan_equality.x"], - dslx_test_args = { - "compare": "none", - "lower_to_ir": "false", - }, + dslx_test_args = {"compare": "jit"}, ) filegroup( diff --git a/xls/examples/dslx_intro/prefix_scan_equality.x b/xls/examples/dslx_intro/prefix_scan_equality.x index 0a799774bc..302560eba6 100644 --- a/xls/examples/dslx_intro/prefix_scan_equality.x +++ b/xls/examples/dslx_intro/prefix_scan_equality.x @@ -18,11 +18,8 @@ import std; fn prefix_scan_eq(x: u32[8]) -> u3[8] { let (_, _, result) = - // TODO(https://github.com/google/xls/issues/5125): Destructure `(i, elem)` - // in the `for` loop header once supported during IR conversion. - for (item, (prior, count, result)): ((u32, u32), (u32, u3, u3[8])) + for ((i, elem), (prior, count, result)): ((u32, u32), (u32, u3, u3[8])) in std::enumerate(x) { - let (i, elem) = item; let (to_place, new_count): (u3, u3) = match (i == u32:0, prior == elem) { // The first iteration always places 0 and propagates seen count of 1. (true, _) => (u3:0, u3:1),