From 5a64f69ef3e3611129a4b34a076a9fc843d75135 Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Thu, 26 Sep 2024 15:37:28 +0300 Subject: [PATCH 1/2] Allow defining const negative `NonZero`. commit-id:790154f7 --- corelib/src/zeroable.cairo | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/corelib/src/zeroable.cairo b/corelib/src/zeroable.cairo index 8685bf09c35..41d7c45c5bd 100644 --- a/corelib/src/zeroable.cairo +++ b/corelib/src/zeroable.cairo @@ -76,6 +76,14 @@ pub(crate) impl Felt252Zeroable = zero_based::ZeroableImpl; /// This type guarantees that the wrapped value is never zero. #[derive(Copy, Drop)] pub extern type NonZero; +impl NonZeroNeg, +TryInto>> of Neg> { + fn neg(a: NonZero) -> NonZero { + // TODO(orizi): Optimize using bounded integers. + let value: T = a.into(); + let negated: T = -value; + negated.try_into().unwrap() + } +} /// Represents the result of checking whether a value is zero. pub(crate) enum IsZeroResult { From 299525ab8610736204802415551606587226fe95 Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Thu, 26 Sep 2024 15:39:57 +0300 Subject: [PATCH 2/2] Added additional tests for `bounded_int` const folding. commit-id:9bba3df9 --- .../src/optimizations/test_data/const_folding | 263 +++++++++++++++++- 1 file changed, 262 insertions(+), 1 deletion(-) diff --git a/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding b/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding index 6907660a377..bacc0a4a54d 100644 --- a/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding +++ b/crates/cairo-lang-lowering/src/optimizations/test_data/const_folding @@ -3348,7 +3348,7 @@ End: //! > ========================================================================== -//! > `bounded_int_constrain` and `bounded_int_mul`. +//! > `AbsAndSign` on positive const. //! > test_runner_name test_match_optimizer @@ -3439,6 +3439,97 @@ End: //! > ========================================================================== +//! > `AbsAndSign` on negative const. + +//! > test_runner_name +test_match_optimizer + +//! > function +fn foo() -> (u8, bool) { + core::integer::AbsAndSign::::abs_and_sign(-6_i8) +} + +//! > function_name +foo + +//! > module_code + +//! > semantic_diagnostics + +//! > before +Parameters: +blk0 (root): +Statements: + (v0: core::integer::i8) <- -6 +End: + Match(match core::internal::bounded_int::bounded_int_constrain::>(v0) { + Result::Ok(v1) => blk1, + Result::Err(v2) => blk2, + }) + +blk1: +Statements: + (v3: core::internal::bounded_int::BoundedInt::<-1, -1>) <- core::internal::bounded_int::minus_1::const_as_immediate::, -1>>() + (v4: core::internal::bounded_int::BoundedInt::<1, 128>) <- core::internal::bounded_int::bounded_int_mul::, core::internal::bounded_int::BoundedInt::<-1, -1>, core::internal::bounded_int::MulMinus1::<-128, -1, core::internal::bounded_int::neg_felt252::Impl::<-128, 128>, core::internal::bounded_int::neg_felt252::Impl::<-1, 1>>>(v1, v3) + (v5: core::integer::u8) <- core::integer::upcast::, core::integer::u8>(v4) + (v6: ()) <- struct_construct() + (v7: core::bool) <- bool::True(v6) + (v8: (core::integer::u8, core::bool)) <- struct_construct(v5, v7) +End: + Goto(blk3, {v8 -> v9}) + +blk2: +Statements: + (v10: core::integer::u8) <- core::integer::upcast::, core::integer::u8>(v2) + (v11: ()) <- struct_construct() + (v12: core::bool) <- bool::False(v11) + (v13: (core::integer::u8, core::bool)) <- struct_construct(v10, v12) +End: + Goto(blk3, {v13 -> v9}) + +blk3: +Statements: +End: + Return(v9) + +//! > after +Parameters: +blk0 (root): +Statements: + (v0: core::integer::i8) <- -6 + (v1: core::internal::bounded_int::BoundedInt::<-128, -1>) <- -6 +End: + Goto(blk1, {}) + +blk1: +Statements: + (v3: core::internal::bounded_int::BoundedInt::<-1, -1>) <- core::internal::bounded_int::minus_1::const_as_immediate::, -1>>() + (v4: core::internal::bounded_int::BoundedInt::<1, 128>) <- core::internal::bounded_int::bounded_int_mul::, core::internal::bounded_int::BoundedInt::<-1, -1>, core::internal::bounded_int::MulMinus1::<-128, -1, core::internal::bounded_int::neg_felt252::Impl::<-128, 128>, core::internal::bounded_int::neg_felt252::Impl::<-1, 1>>>(v1, v3) + (v5: core::integer::u8) <- core::integer::upcast::, core::integer::u8>(v4) + (v6: ()) <- struct_construct() + (v7: core::bool) <- bool::True(v6) + (v8: (core::integer::u8, core::bool)) <- struct_construct(v5, v7) +End: + Goto(blk3, {v8 -> v9}) + +blk2: +Statements: + (v10: core::integer::u8) <- core::integer::upcast::, core::integer::u8>(v2) + (v11: ()) <- struct_construct() + (v12: core::bool) <- bool::False(v11) + (v13: (core::integer::u8, core::bool)) <- struct_construct(v10, v12) +End: + Goto(blk3, {v13 -> v9}) + +blk3: +Statements: +End: + Return(v9) + +//! > lowering_diagnostics + +//! > ========================================================================== + //! > Bitwise not const folding. //! > test_runner_name @@ -3479,3 +3570,173 @@ End: Return(v3) //! > lowering_diagnostics + +//! > ========================================================================== + +//! > bounded_int_constrain on NonZero below. + +//! > test_runner_name +test_match_optimizer + +//! > function +fn foo() -> Result>>, Box>>> { + match core::internal::bounded_int::constrain::, 0>(-5) { + Result::Ok(v) => Result::Ok(BoxTrait::new(v)), + Result::Err(v) => Result::Err(BoxTrait::new(v)), + } +} + +//! > function_name +foo + +//! > module_code +use core::internal::bounded_int::BoundedInt; + +//! > semantic_diagnostics + +//! > before +Parameters: +blk0 (root): +Statements: + (v0: core::zeroable::NonZero::) <- NonZero(-5) +End: + Match(match core::internal::bounded_int::bounded_int_constrain::, 0, core::internal::bounded_int::NonZeroConstrainHelper::>>(v0) { + Result::Ok(v1) => blk1, + Result::Err(v2) => blk2, + }) + +blk1: +Statements: + (v3: core::box::Box::>>) <- core::box::into_box::>>(v1) + (v4: core::result::Result::>>, core::box::Box::>>>) <- Result::Ok(v3) +End: + Goto(blk3, {v4 -> v5}) + +blk2: +Statements: + (v6: core::box::Box::>>) <- core::box::into_box::>>(v2) + (v7: core::result::Result::>>, core::box::Box::>>>) <- Result::Err(v6) +End: + Goto(blk3, {v7 -> v5}) + +blk3: +Statements: +End: + Return(v5) + +//! > after +Parameters: +blk0 (root): +Statements: + (v0: core::zeroable::NonZero::) <- NonZero(-5) +End: + Match(match core::internal::bounded_int::bounded_int_constrain::, 0, core::internal::bounded_int::NonZeroConstrainHelper::>>(v0) { + Result::Ok(v1) => blk1, + Result::Err(v2) => blk2, + }) + +blk1: +Statements: + (v3: core::box::Box::>>) <- core::box::into_box::>>(v1) + (v4: core::result::Result::>>, core::box::Box::>>>) <- Result::Ok(v3) +End: + Goto(blk3, {v4 -> v5}) + +blk2: +Statements: + (v6: core::box::Box::>>) <- core::box::into_box::>>(v2) + (v7: core::result::Result::>>, core::box::Box::>>>) <- Result::Err(v6) +End: + Goto(blk3, {v7 -> v5}) + +blk3: +Statements: +End: + Return(v5) + +//! > lowering_diagnostics + +//! > ========================================================================== + +//! > bounded_int_constrain on NonZero above. + +//! > test_runner_name +test_match_optimizer + +//! > function +fn foo() -> Result>>, Box>>> { + match core::internal::bounded_int::constrain::, 0>(5) { + Result::Ok(v) => Result::Ok(BoxTrait::new(v)), + Result::Err(v) => Result::Err(BoxTrait::new(v)), + } +} + +//! > function_name +foo + +//! > module_code +use core::internal::bounded_int::BoundedInt; + +//! > semantic_diagnostics + +//! > before +Parameters: +blk0 (root): +Statements: + (v0: core::zeroable::NonZero::) <- NonZero(5) +End: + Match(match core::internal::bounded_int::bounded_int_constrain::, 0, core::internal::bounded_int::NonZeroConstrainHelper::>>(v0) { + Result::Ok(v1) => blk1, + Result::Err(v2) => blk2, + }) + +blk1: +Statements: + (v3: core::box::Box::>>) <- core::box::into_box::>>(v1) + (v4: core::result::Result::>>, core::box::Box::>>>) <- Result::Ok(v3) +End: + Goto(blk3, {v4 -> v5}) + +blk2: +Statements: + (v6: core::box::Box::>>) <- core::box::into_box::>>(v2) + (v7: core::result::Result::>>, core::box::Box::>>>) <- Result::Err(v6) +End: + Goto(blk3, {v7 -> v5}) + +blk3: +Statements: +End: + Return(v5) + +//! > after +Parameters: +blk0 (root): +Statements: + (v0: core::zeroable::NonZero::) <- NonZero(5) +End: + Match(match core::internal::bounded_int::bounded_int_constrain::, 0, core::internal::bounded_int::NonZeroConstrainHelper::>>(v0) { + Result::Ok(v1) => blk1, + Result::Err(v2) => blk2, + }) + +blk1: +Statements: + (v3: core::box::Box::>>) <- core::box::into_box::>>(v1) + (v4: core::result::Result::>>, core::box::Box::>>>) <- Result::Ok(v3) +End: + Goto(blk3, {v4 -> v5}) + +blk2: +Statements: + (v6: core::box::Box::>>) <- core::box::into_box::>>(v2) + (v7: core::result::Result::>>, core::box::Box::>>>) <- Result::Err(v6) +End: + Goto(blk3, {v7 -> v5}) + +blk3: +Statements: +End: + Return(v5) + +//! > lowering_diagnostics