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

chore: simplify boolean in a mul of a mul #6951

Merged
merged 3 commits into from
Jan 6, 2025
Merged

chore: simplify boolean in a mul of a mul #6951

merged 3 commits into from
Jan 6, 2025

Conversation

guipublic
Copy link
Contributor

Description

Problem*

Resolves #6879

Summary*

When multiplying a boolean with the result of another multiplication involving the same boolean, we can discard one multiplication.

Additional Context

The regression is a bit subtle, the optimisation introduced by PR #6875 was simplifying an ifesle instruction if one of its operand is also an ifelse with the same condition.
When the operands are an array and the array with one element modified, the merge of values only happens on the modified element, which induces only one multiplication.
However, when the array is a result of of an ifelse, the optimisation from #6875 replace it with another array (the operand of the inner ifselse). So we are no longer merging two almost identical arrays, and we get one multiplication per array element instead.
So basically, the optimisation is preventing another optimisation.
I could not find a way to get the two optimisation to be effective at the same time. The value merge is done when we eliminate IfElse, so the #6875 must be done before. But then the link between the arrays is not obvious.
Fortunately, since this happens when we have inner If statements with the same condition, that means we are multiplying several times with the condition, and this can be optimised from the instruction simplification pass.

Documentation*

Check one:

  • No documentation needed.
  • Documentation included in this PR.
  • [For Experimental Features] Documentation to be submitted in a separate PR.

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

@guipublic guipublic requested a review from TomAFrench January 6, 2025 16:38
Copy link
Contributor

github-actions bot commented Jan 6, 2025

Changes to circuit sizes

Generated at commit: a5d40d2691c12857f077dab3bfdcb7d76b0f2cb0, compared to commit: ab8807d27b0442bd7e9ff73050f44bacea3add16

🧾 Summary (10% most significant diffs)

Program ACIR opcodes (+/-) % Circuit size (+/-) %
sha256_var_size_regression -138 ✅ -0.63% -217 ✅ -0.27%
fold_call_witness_condition -1 ✅ -16.67% -1 ✅ -5.00%

Full diff report 👇
Program ACIR opcodes (+/-) % Circuit size (+/-) %
hashmap 53,816 (-2) -0.00% 119,079 (-2) -0.00%
sha256_regression 42,363 (-6) -0.01% 207,800 (-7) -0.00%
nested_array_dynamic 3,358 (0) 0.00% 12,754 (-1) -0.01%
sha256 2,064 (-3) -0.15% 25,338 (-5) -0.02%
sha256_var_witness_const_regression 1,702 (-3) -0.18% 17,231 (-4) -0.02%
slices 796 (-2) -0.25% 3,960 (-2) -0.05%
conditional_regression_661 35 (-3) -7.89% 2,804 (-3) -0.11%
slice_dynamic_index 1,068 (-7) -0.65% 6,498 (-7) -0.11%
conditional_1 9,039 (-24) -0.26% 18,367 (-30) -0.16%
sha256_var_size_regression 21,617 (-138) -0.63% 79,344 (-217) -0.27%
fold_call_witness_condition 5 (-1) -16.67% 19 (-1) -5.00%

Copy link
Contributor

github-actions bot commented Jan 6, 2025

Compilation Report

Program Compilation Time %
sha256_regression 1.332s -1%
regression_4709 0.776s -1%
ram_blowup_regression 15.000s -1%
rollup-root 3.530s -17%
rollup-block-merge 3.630s -5%
rollup-base-public 31.600s -16%
rollup-base-private 12.700s -36%
private-kernel-tail 1.008s -4%
private-kernel-reset 6.844s -3%
private-kernel-inner 2.086s -6%
noir-contracts 84.700s -1%

Copy link
Contributor

github-actions bot commented Jan 6, 2025

Execution Report

Program Execution Time %
sha256_regression 0.100s 0%
regression_4709 0.001s 0%
ram_blowup_regression 0.581s 0%
rollup-root 0.106s -16%
rollup-block-merge 0.105s -19%
rollup-base-public 1.440s -42%
rollup-base-private 0.644s -63%
private-kernel-tail 0.024s 4%
private-kernel-reset 0.388s -1%
private-kernel-inner 0.116s -1%

Copy link
Contributor

github-actions bot commented Jan 6, 2025

Compilation Memory Report

Program Peak Memory
keccak256 78.50M
workspace 123.62M
regression_4709 422.91M
ram_blowup_regression 1.58G
rollup-base-public 2.55G
rollup-base-private 1.25G
private-kernel-tail 201.95M
private-kernel-reset 716.58M
private-kernel-inner 292.22M

Copy link
Contributor

github-actions bot commented Jan 6, 2025

Execution Memory Report

Program Peak Memory %
keccak256 74.61M 0%
workspace 123.31M 0%
regression_4709 315.93M 0%
ram_blowup_regression 512.47M 0%
rollup-base-public 773.36M 100%
rollup-base-private 424.91M -49%
private-kernel-tail 181.99M 0%
private-kernel-reset 255.57M 0%
private-kernel-inner 215.17M 0%

@TomAFrench
Copy link
Member

This PR drops the number of opcodes in rollup-base-private from 617798 (ab8807d) to 215613. Not bad!

Copy link
Member

@TomAFrench TomAFrench left a comment

Choose a reason for hiding this comment

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

LGTM!

@TomAFrench TomAFrench added this pull request to the merge queue Jan 6, 2025
Merged via the queue into master with commit 04714a7 Jan 6, 2025
88 checks passed
@TomAFrench TomAFrench deleted the gd/issue_6875 branch January 6, 2025 21:40
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 7, 2025
…oir#6926)

chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 7, 2025
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 7, 2025
)

feat: `--pedantic-solving` flag (noir-lang/noir#6716)
feat!: update `aes128_encrypt` to return an array (noir-lang/noir#6973)
fix: wrong module to lookup trait when using crate or super (noir-lang/noir#6974)
fix: Start RC at 1 again (noir-lang/noir#6958)
feat!: turn TypeIsMorePrivateThenItem into an error (noir-lang/noir#6953)
fix: don't fail parsing macro if there are parser warnings (noir-lang/noir#6969)
fix: error on missing function parameters (noir-lang/noir#6967)
feat: don't report warnings for dependencies (noir-lang/noir#6926)
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 7, 2025
feat: `--pedantic-solving` flag (noir-lang/noir#6716)
feat!: update `aes128_encrypt` to return an array (noir-lang/noir#6973)
fix: wrong module to lookup trait when using crate or super (noir-lang/noir#6974)
fix: Start RC at 1 again (noir-lang/noir#6958)
feat!: turn TypeIsMorePrivateThenItem into an error (noir-lang/noir#6953)
fix: don't fail parsing macro if there are parser warnings (noir-lang/noir#6969)
fix: error on missing function parameters (noir-lang/noir#6967)
feat: don't report warnings for dependencies (noir-lang/noir#6926)
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
TomAFrench added a commit that referenced this pull request Jan 8, 2025
* master: (51 commits)
  feat!: type-check trait default methods (#6645)
  feat: `--pedantic-solving` flag (#6716)
  feat!: update `aes128_encrypt` to return an array (#6973)
  fix: wrong module to lookup trait when using crate or super (#6974)
  fix: Start RC at 1 again (#6958)
  feat!: turn TypeIsMorePrivateThenItem into an error (#6953)
  fix: don't fail parsing macro if there are parser warnings (#6969)
  fix: error on missing function parameters (#6967)
  feat: don't report warnings for dependencies (#6926)
  chore: simplify boolean in a mul of a mul (#6951)
  feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (#6893)
  chore: Move comment as part of #6945 (#6959)
  chore: Separate unconstrained functions during monomorphization (#6894)
  feat!: turn CannotReexportItemWithLessVisibility into an error (#6952)
  feat: lock on Nargo.toml on several nargo commands (#6941)
  feat: don't simplify SSA instructions when creating them from a string (#6948)
  chore: add reproduction case for bignum test failure (#6464)
  chore: bump `noir-gates-diff` (#6949)
  feat(test): Enable the test fuzzer for Wasm (#6835)
  chore: also print test output to stdout in CI (#6930)
  ...
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 8, 2025
)

feat: `--pedantic-solving` flag (noir-lang/noir#6716)
feat!: update `aes128_encrypt` to return an array (noir-lang/noir#6973)
fix: wrong module to lookup trait when using crate or super (noir-lang/noir#6974)
fix: Start RC at 1 again (noir-lang/noir#6958)
feat!: turn TypeIsMorePrivateThenItem into an error (noir-lang/noir#6953)
fix: don't fail parsing macro if there are parser warnings (noir-lang/noir#6969)
fix: error on missing function parameters (noir-lang/noir#6967)
feat: don't report warnings for dependencies (noir-lang/noir#6926)
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 8, 2025
feat: `--pedantic-solving` flag (noir-lang/noir#6716)
feat!: update `aes128_encrypt` to return an array (noir-lang/noir#6973)
fix: wrong module to lookup trait when using crate or super (noir-lang/noir#6974)
fix: Start RC at 1 again (noir-lang/noir#6958)
feat!: turn TypeIsMorePrivateThenItem into an error (noir-lang/noir#6953)
fix: don't fail parsing macro if there are parser warnings (noir-lang/noir#6969)
fix: error on missing function parameters (noir-lang/noir#6967)
feat: don't report warnings for dependencies (noir-lang/noir#6926)
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
Rumata888 pushed a commit that referenced this pull request Jan 8, 2025
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 8, 2025
fix: Do not emit range check for multiplication by bool (noir-lang/noir#6983)
fix: do not panic on indices which are not valid `u32`s (noir-lang/noir#6976)
feat!: require trait method calls (`foo.bar()`) to have the trait in scope (imported) (noir-lang/noir#6895)
feat!: type-check trait default methods (noir-lang/noir#6645)
feat: `--pedantic-solving` flag (noir-lang/noir#6716)
feat!: update `aes128_encrypt` to return an array (noir-lang/noir#6973)
fix: wrong module to lookup trait when using crate or super (noir-lang/noir#6974)
fix: Start RC at 1 again (noir-lang/noir#6958)
feat!: turn TypeIsMorePrivateThenItem into an error (noir-lang/noir#6953)
fix: don't fail parsing macro if there are parser warnings (noir-lang/noir#6969)
fix: error on missing function parameters (noir-lang/noir#6967)
feat: don't report warnings for dependencies (noir-lang/noir#6926)
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
AztecBot added a commit to AztecProtocol/aztec-packages that referenced this pull request Jan 8, 2025
fix: Do not emit range check for multiplication by bool (noir-lang/noir#6983)
fix: do not panic on indices which are not valid `u32`s (noir-lang/noir#6976)
feat!: require trait method calls (`foo.bar()`) to have the trait in scope (imported) (noir-lang/noir#6895)
feat!: type-check trait default methods (noir-lang/noir#6645)
feat: `--pedantic-solving` flag (noir-lang/noir#6716)
feat!: update `aes128_encrypt` to return an array (noir-lang/noir#6973)
fix: wrong module to lookup trait when using crate or super (noir-lang/noir#6974)
fix: Start RC at 1 again (noir-lang/noir#6958)
feat!: turn TypeIsMorePrivateThenItem into an error (noir-lang/noir#6953)
fix: don't fail parsing macro if there are parser warnings (noir-lang/noir#6969)
fix: error on missing function parameters (noir-lang/noir#6967)
feat: don't report warnings for dependencies (noir-lang/noir#6926)
chore: simplify boolean in a mul of a mul (noir-lang/noir#6951)
feat(ssa): Immediately simplify away RefCount instructions in ACIR functions (noir-lang/noir#6893)
chore: Move comment as part of #6945 (noir-lang/noir#6959)
chore: Separate unconstrained functions during monomorphization (noir-lang/noir#6894)
feat!: turn CannotReexportItemWithLessVisibility into an error (noir-lang/noir#6952)
feat: lock on Nargo.toml on several nargo commands (noir-lang/noir#6941)
feat: don't simplify SSA instructions when creating them from a string (noir-lang/noir#6948)
chore: add reproduction case for bignum test failure (noir-lang/noir#6464)
chore: bump `noir-gates-diff` (noir-lang/noir#6949)
feat(test): Enable the test fuzzer for Wasm (noir-lang/noir#6835)
chore: also print test output to stdout in CI (noir-lang/noir#6930)
fix: Non-determinism from under constrained checks (noir-lang/noir#6945)
chore: use logs for benchmarking (noir-lang/noir#6911)
chore: bump `noir-gates-diff` (noir-lang/noir#6944)
chore: bump `noir-gates-diff` (noir-lang/noir#6943)
fix: Show output of `test_program_is_idempotent` on failure (noir-lang/noir#6942)
chore: delete a bunch of dead code from `noirc_evaluator` (noir-lang/noir#6939)
feat: require trait function calls (`Foo::bar()`) to have the trait in scope (imported) (noir-lang/noir#6882)
chore: Bump arkworks to version `0.5.0` (noir-lang/noir#6871)
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.

Fix regression caused by #6875
2 participants