@@ -18,8 +18,7 @@ use super::{
1818 basic_block:: BasicBlock ,
1919 dfg:: { CallStack , InsertInstructionResult } ,
2020 function:: RuntimeType ,
21- instruction:: { ConstrainError , Endian , InstructionId , Intrinsic } ,
22- types:: NumericType ,
21+ instruction:: { ConstrainError , InstructionId , Intrinsic } ,
2322 } ,
2423 ssa_gen:: Ssa ,
2524} ;
@@ -279,115 +278,6 @@ impl FunctionBuilder {
279278 self . insert_instruction ( Instruction :: Call { func, arguments } , Some ( result_types) ) . results ( )
280279 }
281280
282- /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs
283- /// and truncate the result to bit_size
284- pub ( crate ) fn insert_wrapping_shift_left (
285- & mut self ,
286- lhs : ValueId ,
287- rhs : ValueId ,
288- bit_size : u32 ,
289- ) -> ValueId {
290- let base = self . field_constant ( FieldElement :: from ( 2_u128 ) ) ;
291- let typ = self . current_function . dfg . type_of_value ( lhs) ;
292- let ( max_bit, pow) =
293- if let Some ( rhs_constant) = self . current_function . dfg . get_numeric_constant ( rhs) {
294- // Happy case is that we know precisely by how many bits the the integer will
295- // increase: lhs_bit_size + rhs
296- let bit_shift_size = rhs_constant. to_u128 ( ) as u32 ;
297-
298- let ( rhs_bit_size_pow_2, overflows) = 2_u128 . overflowing_pow ( bit_shift_size) ;
299- if overflows {
300- assert ! ( bit_size < 128 , "ICE - shift left with big integers are not supported" ) ;
301- if bit_size < 128 {
302- let zero = self . numeric_constant ( FieldElement :: zero ( ) , typ) ;
303- return InsertInstructionResult :: SimplifiedTo ( zero) . first ( ) ;
304- }
305- }
306- let pow = self . numeric_constant ( FieldElement :: from ( rhs_bit_size_pow_2) , typ) ;
307-
308- let max_lhs_bits = self . current_function . dfg . get_value_max_num_bits ( lhs) ;
309-
310- ( max_lhs_bits + bit_shift_size, pow)
311- } else {
312- // we use a predicate to nullify the result in case of overflow
313- let bit_size_var =
314- self . numeric_constant ( FieldElement :: from ( bit_size as u128 ) , typ. clone ( ) ) ;
315- let overflow = self . insert_binary ( rhs, BinaryOp :: Lt , bit_size_var) ;
316- let predicate = self . insert_cast ( overflow, typ. clone ( ) ) ;
317- // we can safely cast to unsigned because overflow_checks prevent bit-shift with a negative value
318- let rhs_unsigned = self . insert_cast ( rhs, Type :: unsigned ( bit_size) ) ;
319- let pow = self . pow ( base, rhs_unsigned) ;
320- let pow = self . insert_cast ( pow, typ) ;
321- ( FieldElement :: max_num_bits ( ) , self . insert_binary ( predicate, BinaryOp :: Mul , pow) )
322- } ;
323-
324- if max_bit <= bit_size {
325- self . insert_binary ( lhs, BinaryOp :: Mul , pow)
326- } else {
327- let result = self . insert_binary ( lhs, BinaryOp :: Mul , pow) ;
328- self . insert_truncate ( result, bit_size, max_bit)
329- }
330- }
331-
332- /// Insert ssa instructions which computes lhs >> rhs by doing lhs/2^rhs
333- pub ( crate ) fn insert_shift_right (
334- & mut self ,
335- lhs : ValueId ,
336- rhs : ValueId ,
337- bit_size : u32 ,
338- ) -> ValueId {
339- let lhs_typ = self . type_of_value ( lhs) ;
340- let base = self . field_constant ( FieldElement :: from ( 2_u128 ) ) ;
341- // we can safely cast to unsigned because overflow_checks prevent bit-shift with a negative value
342- let rhs_unsigned = self . insert_cast ( rhs, Type :: unsigned ( bit_size) ) ;
343- let pow = self . pow ( base, rhs_unsigned) ;
344- // We need at least one more bit for the case where rhs == bit_size
345- let div_type = Type :: unsigned ( bit_size + 1 ) ;
346- let casted_lhs = self . insert_cast ( lhs, div_type. clone ( ) ) ;
347- let casted_pow = self . insert_cast ( pow, div_type) ;
348- let div_result = self . insert_binary ( casted_lhs, BinaryOp :: Div , casted_pow) ;
349- // We have to cast back to the original type
350- self . insert_cast ( div_result, lhs_typ)
351- }
352-
353- /// Computes lhs^rhs via square&multiply, using the bits decomposition of rhs
354- /// Pseudo-code of the computation:
355- /// let mut r = 1;
356- /// let rhs_bits = to_bits(rhs);
357- /// for i in 1 .. bit_size + 1 {
358- /// let r_squared = r * r;
359- /// let b = rhs_bits[bit_size - i];
360- /// r = (r_squared * lhs * b) + (1 - b) * r_squared;
361- /// }
362- pub ( crate ) fn pow ( & mut self , lhs : ValueId , rhs : ValueId ) -> ValueId {
363- let typ = self . current_function . dfg . type_of_value ( rhs) ;
364- if let Type :: Numeric ( NumericType :: Unsigned { bit_size } ) = typ {
365- let to_bits = self . import_intrinsic_id ( Intrinsic :: ToBits ( Endian :: Little ) ) ;
366- let length = self . field_constant ( FieldElement :: from ( bit_size as i128 ) ) ;
367- let result_types =
368- vec ! [ Type :: field( ) , Type :: Array ( Rc :: new( vec![ Type :: bool ( ) ] ) , bit_size as usize ) ] ;
369- let rhs_bits = self . insert_call ( to_bits, vec ! [ rhs, length] , result_types) ;
370- let rhs_bits = rhs_bits[ 1 ] ;
371- let one = self . field_constant ( FieldElement :: one ( ) ) ;
372- let mut r = one;
373- for i in 1 ..bit_size + 1 {
374- let r_squared = self . insert_binary ( r, BinaryOp :: Mul , r) ;
375- let a = self . insert_binary ( r_squared, BinaryOp :: Mul , lhs) ;
376- let idx = self . field_constant ( FieldElement :: from ( ( bit_size - i) as i128 ) ) ;
377- let b = self . insert_array_get ( rhs_bits, idx, Type :: bool ( ) ) ;
378- let not_b = self . insert_not ( b) ;
379- let b = self . insert_cast ( b, Type :: field ( ) ) ;
380- let not_b = self . insert_cast ( not_b, Type :: field ( ) ) ;
381- let r1 = self . insert_binary ( a, BinaryOp :: Mul , b) ;
382- let r2 = self . insert_binary ( r_squared, BinaryOp :: Mul , not_b) ;
383- r = self . insert_binary ( r1, BinaryOp :: Add , r2) ;
384- }
385- r
386- } else {
387- unreachable ! ( "Value must be unsigned in power operation" ) ;
388- }
389- }
390-
391281 /// Insert an instruction to extract an element from an array
392282 pub ( crate ) fn insert_array_get (
393283 & mut self ,
0 commit comments