Skip to content
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

feat: add iterator-based for loops #1176

Merged
merged 42 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d967ac7
chore: clean up comments in native compiler
yi-sun Jan 1, 2025
2c53f1a
feat: add iterator for loop
yi-sun Jan 7, 2025
b07c4ea
feat: convert more for loops
yi-sun Jan 7, 2025
674f894
fix: lint
yi-sun Jan 7, 2025
df77c86
wip: zipped iterator
yi-sun Jan 7, 2025
1190233
fix: lint
yi-sun Jan 7, 2025
43e7a86
feat: iterator for loop in poseidon
yi-sun Jan 8, 2025
2b84329
feat: optimize store
yi-sun Jan 8, 2025
9f6a3e6
fix: keep loop variable
yi-sun Jan 8, 2025
cd7fcbf
fix: store
yi-sun Jan 8, 2025
3378cc2
opt: try removing get_ref
yi-sun Jan 8, 2025
2ac690c
opt: remove duplicate get
yi-sun Jan 8, 2025
a64cb2b
opt: remove idx
yi-sun Jan 8, 2025
56bff31
chore: remove unused code
yi-sun Jan 8, 2025
6533f8d
fix: lint
yi-sun Jan 8, 2025
053a4ee
feat: add ZipFor and zipped_iter
yi-sun Jan 8, 2025
5d72e21
fix: lint
yi-sun Jan 8, 2025
7dc4557
feat: implement zipped_iter
yi-sun Jan 9, 2025
8c27cdf
fix: faulty assert
yi-sun Jan 9, 2025
f71efd7
fix: read
yi-sun Jan 9, 2025
9266fba
fix: lint
yi-sun Jan 9, 2025
6851b5a
fix: lint
yi-sun Jan 9, 2025
9d9c5c4
fix: vec
yi-sun Jan 9, 2025
9b4cc0e
feat: add more zipped_iter
yi-sun Jan 9, 2025
f85ae11
feat: optimize verify_batch
yi-sun Jan 9, 2025
c9aa05e
fix: use first array for zipped_iter
yi-sun Jan 9, 2025
45134ad
feat: add zipped_iter to hint
yi-sun Jan 9, 2025
84c9d75
chore: remove print
yi-sun Jan 9, 2025
8e8b062
feat: optimize hint_words
yi-sun Jan 9, 2025
2e68d6e
fix: lifetime issues
yi-sun Jan 9, 2025
f5cc632
chore: add comment with example
yi-sun Jan 10, 2025
0aff4b0
feat: use square-and-multiply for exp_reverse_bits_len
yi-sun Jan 10, 2025
46ddb6b
fix: input size for exp_reverse_bits_len
yi-sun Jan 10, 2025
392355b
fix: slice and shift for V::size_of() greater than 1, optimization
yi-sun Jan 10, 2025
beae4ce
fix: replace incorrectly removed side effect
yi-sun Jan 10, 2025
2d5a26e
feat: optimize adds
yi-sun Jan 10, 2025
7d8670b
feat: optimize for loops in duplex challenger
yi-sun Jan 10, 2025
8fc92db
chore: use larger runner for build workflow
yi-sun Jan 10, 2025
df89bb1
feat: address comments
yi-sun Jan 10, 2025
71c958b
feat: remove all but the first end ptr in ZipFor
yi-sun Jan 10, 2025
e0886a8
feat: implement and use compile_zip! macro
yi-sun Jan 10, 2025
4a1d614
feat: add tests for iter and zip
yi-sun Jan 11, 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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: Build
runs-on:
- runs-on=${{ github.run_id }}
- runner=8cpu-linux-x64
- runner=64cpu-linux-arm64
- extras=s3-cache
steps:
- uses: runs-on/action@v1
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

107 changes: 107 additions & 0 deletions extensions/native/compiler/src/asm/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,16 @@ impl<F: PrimeField32 + TwoAdicField, EF: ExtensionField<F> + TwoAdicField> AsmCo
};
for_compiler.for_each(move |_, builder| builder.build(block), debug_info);
}
DslIr::ZipFor(starts, ends, step_sizes, loop_vars, block) => {
let zip_for_compiler = ZipForCompiler {
compiler: self,
starts,
ends,
step_sizes,
loop_vars,
};
zip_for_compiler.for_each(move |_, builder| builder.build(block), debug_info);
}
DslIr::Loop(block) => {
let loop_compiler = LoopCompiler { compiler: self };
loop_compiler.compile(move |builder| builder.build(block), debug_info);
Expand Down Expand Up @@ -825,6 +835,103 @@ impl<F: PrimeField32 + TwoAdicField, EF: ExtensionField<F> + TwoAdicField> IfCom
}
}

// Zipped for loop -- loop extends over the first entry in starts and ends
pub struct ZipForCompiler<'a, F: Field, EF> {
compiler: &'a mut AsmCompiler<F, EF>,
starts: Vec<RVar<F>>,
ends: Vec<RVar<F>>,
step_sizes: Vec<F>,
loop_vars: Vec<Var<F>>,
zlangley marked this conversation as resolved.
Show resolved Hide resolved
}

impl<F: PrimeField32 + TwoAdicField, EF: ExtensionField<F> + TwoAdicField>
ZipForCompiler<'_, F, EF>
{
pub(super) fn for_each(
self,
f: impl FnOnce(Vec<Var<F>>, &mut AsmCompiler<F, EF>),
debug_info: Option<DebugInfo>,
) {
// initialize the loop variables
self.starts
.iter()
.zip(self.loop_vars.iter())
.for_each(|(start, loop_var)| match start {
RVar::Const(start) => {
self.compiler.push(
AsmInstruction::ImmF(loop_var.fp(), *start),
debug_info.clone(),
);
}
RVar::Val(start) => {
self.compiler.push(
AsmInstruction::CopyF(loop_var.fp(), start.fp()),
debug_info.clone(),
);
}
});

let loop_call_label = self.compiler.block_label();
let break_label = self.compiler.new_break_label();
self.compiler.break_label = Some(break_label);

self.compiler.basic_block();
let loop_label = self.compiler.block_label();

f(self.loop_vars.clone(), self.compiler);

self.loop_vars
.iter()
.zip(self.step_sizes.iter())
.for_each(|(loop_var, step_size)| {
self.compiler.push(
AsmInstruction::AddFI(loop_var.fp(), loop_var.fp(), *step_size),
debug_info.clone(),
);
});

self.compiler.basic_block();
let end = self.ends[0];
yi-sun marked this conversation as resolved.
Show resolved Hide resolved
let loop_var = self.loop_vars[0];
match end {
RVar::Const(end) => {
self.compiler.push(
AsmInstruction::BneI(loop_label, loop_var.fp(), end),
debug_info.clone(),
);
}
RVar::Val(end) => {
self.compiler.push(
AsmInstruction::Bne(loop_label, loop_var.fp(), end.fp()),
debug_info.clone(),
);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Small optimization: We can put the Bne after the first AddFI so that we don't spend cycles incrementing pointers we don't need to use.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think we need the first Bne to cover the case where starts[0] == end0.


let label = self.compiler.block_label();
let instr = AsmInstruction::j(label);
self.compiler
.push_to_block(loop_call_label, instr, debug_info.clone());

self.compiler.basic_block();
let label = self.compiler.block_label();
self.compiler.break_label_map.insert(break_label, label);

for block in self.compiler.contains_break.iter() {
for instruction in self.compiler.basic_blocks[block.as_canonical_u32() as usize]
.0
.iter_mut()
{
if let AsmInstruction::Break(l) = instruction {
if *l == break_label {
*instruction = AsmInstruction::j(label);
}
}
}
}
}
}

/// A builder for a for loop.
///
/// SAFETY: Starting with end < start will lead to undefined behavior.
Expand Down
Loading