Skip to content

Commit c3a0991

Browse files
committed
fix 128bits ctlz intrinsincs UB
1 parent fcac229 commit c3a0991

File tree

1 file changed

+25
-34
lines changed

1 file changed

+25
-34
lines changed

src/intrinsic/mod.rs

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)