@@ -726,51 +726,42 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
726
726
"__builtin_clzll"
727
727
}
728
728
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" ) ;
734
734
let sixty_four = self . const_uint ( arg_type, 64 ) ;
735
735
let shift = self . lshr ( arg, sixty_four) ;
736
736
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 ) ;
742
737
743
738
let clzll = self . context . get_builtin_function ( "__builtin_clzll" ) ;
744
739
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
+ ) ;
749
748
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) ;
755
751
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) ;
760
754
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) ;
770
761
771
- let res = self . context . new_array_access ( self . location , result , index ) ;
762
+ self . switch_to_block ( ctlz_after_block ) ;
772
763
773
- return self . gcc_int_cast ( res . to_rvalue ( ) , result_type ) ;
764
+ return result . to_rvalue ( ) ;
774
765
}
775
766
else {
776
767
let count_leading_zeroes = self . context . get_builtin_function ( "__builtin_clzll" ) ;
0 commit comments