From 44ff4c5cde82e193f3f1a55742cebe0e25757a5b Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Fri, 27 Sep 2024 15:33:33 +0000 Subject: [PATCH] simplify signed casts, conservative in the field/unsigned -> signed case --- .../src/ssa/ir/instruction/cast.rs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs index d0ed5a1fa9c..ed588def1d7 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/cast.rs @@ -27,10 +27,10 @@ pub(super) fn simplify_cast( SimplifiedTo(value) } ( - Type::Numeric(NumericType::Unsigned { .. }), + Type::Numeric(NumericType::Unsigned { .. } | NumericType::Signed { .. }), Type::Numeric(NumericType::NativeField), ) => { - // Unsigned -> Field: redefine same constant as Field + // Unsigned/Signed -> Field: redefine same constant as Field SimplifiedTo(dfg.make_constant(constant, dst_typ.clone())) } ( @@ -48,6 +48,24 @@ pub(super) fn simplify_cast( let truncated = FieldElement::from_be_bytes_reduce(&truncated.to_bytes_be()); SimplifiedTo(dfg.make_constant(truncated, dst_typ.clone())) } + ( + Type::Numeric( + NumericType::NativeField + | NumericType::Unsigned { .. } + | NumericType::Signed { .. }, + ), + Type::Numeric(NumericType::Signed { bit_size }), + ) => { + // Field/Unsigned -> signed + // We only simplify to signed when we are below the maximum signed integer of the destination type. + let integer_modulus = BigUint::from(2u128).pow(*bit_size - 1); + let constant_uint: BigUint = BigUint::from_bytes_be(&constant.to_be_bytes()); + if constant_uint < integer_modulus { + SimplifiedTo(dfg.make_constant(constant, dst_typ.clone())) + } else { + None + } + } _ => None, } } else if *dst_typ == dfg.type_of_value(value) {