@@ -726,51 +726,42 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
726726 "__builtin_clzll"
727727 }
728728 else if width == 128 {
729- // Algorithm from: https://stackoverflow.com/a/28433850/389119
730- let array_type = self . context . new_array_type ( None , arg_type , 3 ) ;
731- let result = self . current_func ( )
732- . new_local ( None , array_type , "count_loading_zeroes_results ") ;
733-
729+ // Algorithm from: https://stackoverflow.com/a/28433850/389119 updated to check for high 64bits being 0
730+ let result = self . current_func ( ) . new_local ( None , self . u32_type , "zeros" ) ;
731+ let ctlz_then_block = self . current_func ( ) . new_block ( "ctlz_then" ) ;
732+ let ctlz_else_block = self . current_func ( ) . new_block ( "ctlz_else ") ;
733+ let ctlz_after_block = self . current_func ( ) . new_block ( "ctlz_after" ) ;
734734 let sixty_four = self . const_uint ( arg_type, 64 ) ;
735735 let shift = self . lshr ( arg, sixty_four) ;
736736 let high = self . gcc_int_cast ( shift, self . u64_type ) ;
737- let low = self . gcc_int_cast ( arg, self . u64_type ) ;
738-
739- let zero = self . context . new_rvalue_zero ( self . usize_type ) ;
740- let one = self . context . new_rvalue_one ( self . usize_type ) ;
741- let two = self . context . new_rvalue_from_long ( self . usize_type , 2 ) ;
742737
743738 let clzll = self . context . get_builtin_function ( "__builtin_clzll" ) ;
744739
745- let first_elem = self . context . new_array_access ( None , result, zero) ;
746- let first_value = self . gcc_int_cast ( self . context . new_call ( None , clzll, & [ high] ) , arg_type) ;
747- self . llbb ( )
748- . add_assignment ( self . location , first_elem, first_value) ;
740+ let zero = self . const_uint ( high. get_type ( ) , 0 ) ;
741+ let cond = self . gcc_icmp ( IntPredicate :: IntNE , high, zero) ;
742+ self . llbb ( ) . end_with_conditional (
743+ self . location ,
744+ cond,
745+ ctlz_then_block,
746+ ctlz_else_block,
747+ ) ;
749748
750- let second_elem = self . context . new_array_access ( self . location , result, one) ;
751- let cast = self . gcc_int_cast ( self . context . new_call ( self . location , clzll, & [ low] ) , arg_type) ;
752- let second_value = self . add ( cast, sixty_four) ;
753- self . llbb ( )
754- . add_assignment ( self . location , second_elem, second_value) ;
749+ let leading_zeroes =
750+ self . gcc_int_cast ( self . context . new_call ( None , clzll, & [ high] ) , result_type) ;
755751
756- let third_elem = self . context . new_array_access ( self . location , result, two) ;
757- let third_value = self . const_uint ( arg_type, 128 ) ;
758- self . llbb ( )
759- . add_assignment ( self . location , third_elem, third_value) ;
752+ ctlz_then_block. add_assignment ( None , result, leading_zeroes) ;
753+ ctlz_then_block. end_with_jump ( None , ctlz_after_block) ;
760754
761- let not_high = self . context . new_unary_op ( self . location , UnaryOp :: LogicalNegate , self . u64_type , high) ;
762- let not_low = self . context . new_unary_op ( self . location , UnaryOp :: LogicalNegate , self . u64_type , low) ;
763- let not_low_and_not_high = not_low & not_high;
764- let index = not_high + not_low_and_not_high;
765- // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
766- // gcc.
767- // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
768- // compilation stage.
769- let index = self . context . new_cast ( self . location , index, self . i32_type ) ;
755+ let low = self . gcc_int_cast ( arg, self . u64_type ) ;
756+ let low_leading_zeroes =
757+ self . gcc_int_cast ( self . context . new_call ( None , clzll, & [ low] ) , result_type) ;
758+ let leading_zeroes = self . add ( low_leading_zeroes, sixty_four) ;
759+ ctlz_else_block. add_assignment ( None , result, leading_zeroes) ;
760+ ctlz_else_block. end_with_jump ( None , ctlz_after_block) ;
770761
771- let res = self . context . new_array_access ( self . location , result , index ) ;
762+ self . switch_to_block ( ctlz_after_block ) ;
772763
773- return self . gcc_int_cast ( res . to_rvalue ( ) , result_type ) ;
764+ return result . to_rvalue ( ) ;
774765 }
775766 else {
776767 let count_leading_zeroes = self . context . get_builtin_function ( "__builtin_clzll" ) ;
0 commit comments