xls
xls copied to clipboard
[enhancement] Treat for-loop iterator value as constant when iteration over constant values
What's hard to do? (limit 100 words)
As for today, the value of DSLX for-loop iterator is not treated as constant when iterating over constant values. Having the ability to use the for-loop iterator in this way can improve the expressiveness of the language. In all these cases, when iterating over constant values it should be possible to unroll the for-loop.
These small examples show the current limitations of the language:
let data = u64:0x00_11_22_33_44_55_66_77;
for (i, ()) in s32:0..s32:8 {
// works if rewritten with width slices
let slice = data[(i * s32:8) : (i + s32:1) * s32:8];
trace_fmt!("slice is {}", slice);
}(());
// for (i, ()) in s32:0..s32:8 {
// let slice = data[(i * s32:8) : (i + s32:1) * s32:8];
// ~~~~~~~~~~~~~~~~~~~~~~~~^ TypeInferenceError: Unable to resolve slice start to a compile-time constant.
// the unrolled version works
let slice = data[(s32:0 * s32:8) : (s32:0 + s32:1) * s32:8];
let slice = data[(s32:1 * s32:8) : (s32:1 + s32:1) * s32:8];
let slice = data[(s32:2 * s32:8) : (s32:2 + s32:1) * s32:8];
//...
let slice = data[(s32:7 * s32:8) : (s32:7 + s32:1) * s32:8];
fn add_const<Y: s32>(x: s32) -> s32 { x + Y }
for (i, acc) in s32:0..s32:8 {
add_const<i>(acc);
}((u32:3));
// for (i, acc) in s32:0..s32:8 {
// add_const<i>(acc);
// ~~~~~~~~~~~~~~^ TypeInferenceError: sN[32] Parametric expression `i` was not constexpr -- parametric values must be compile-time constants
- An example of data concatenation. We tried to use similar logic as a part of a buffering proc. The proc accumulated incoming data in the state and sent back the requested number of bytes of data.
//This data may come from channels
let s = s32:4;
let data1 = u64:0x00_11_22_33_44_55_66_77;
let data2 = u64:0x88_99_AA_BB_CC_DD_EE_FF;
let slice = for (i, slice) in s32:0..s32:8 {
if (s == i) {
data1[i * s32:8 : s32:64] ++ data2[0 : i * s32:8]
} else {
slice
}
}(u64:0);
trace_fmt!("slice is {}", slice);
let slice = if s == s32:0 {data1[s32:0 * s32:8 : s32:64] ++ data2[0 : s32:0 * s32:8]} else {u64:0};
let slice = if s == s32:1 {data1[s32:1 * s32:8 : s32:64] ++ data2[0 : s32:1 * s32:8]} else {slice};
let slice = if s == s32:2 {data1[s32:2 * s32:8 : s32:64] ++ data2[0 : s32:2 * s32:8]} else {slice};
let slice = if s == s32:3 {data1[s32:3 * s32:8 : s32:64] ++ data2[0 : s32:3 * s32:8]} else {slice};
let slice = if s == s32:4 {data1[s32:4 * s32:8 : s32:64] ++ data2[0 : s32:4 * s32:8]} else {slice};
let slice = if s == s32:5 {data1[s32:5 * s32:8 : s32:64] ++ data2[0 : s32:5 * s32:8]} else {slice};
let slice = if s == s32:6 {data1[s32:6 * s32:8 : s32:64] ++ data2[0 : s32:6 * s32:8]} else {slice};
let slice = if s == s32:7 {data1[s32:7 * s32:8 : s32:64] ++ data2[0 : s32:7 * s32:8]} else {slice};
trace_fmt!("slice: {:#x}", slice);
Current best alternative workaround (limit 100 words)
Unroll the for-loop as in the examples above
Your view of the "best case XLS enhancement" (limit 100 words)
In cases when the for-loop iterates over constant values, the iterator can be treated as a constant and XLS can treat the loop as if it were unrolled