Skip to content

Commit 81c1f39

Browse files
committed
optimize u128/i128 popcounts further
Don't fall back on breaking apart the popcount operation if 128-bit integers are natively supported. Signed-off-by: Andy Sadler <[email protected]>
1 parent a9f31ab commit 81c1f39

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

src/intrinsic/mod.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod simd;
44
#[cfg(feature="master")]
55
use std::iter;
66

7-
use gccjit::{BinaryOp, ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
7+
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
88
use rustc_codegen_ssa::MemFlags;
99
use rustc_codegen_ssa::base::wants_msvc_seh;
1010
use rustc_codegen_ssa::common::IntPredicate;
@@ -819,7 +819,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
819819
value
820820
};
821821

822-
if value_type.is_u128(&self.cx) {
822+
// only break apart 128-bit ints if they're not natively supported
823+
// TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
824+
if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers {
823825
let sixty_four = self.gcc_int(value_type, 64);
824826
let right_shift = self.gcc_lshr(value, sixty_four);
825827
let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
@@ -842,30 +844,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
842844
let counter_type = self.int_type;
843845
let counter = self.current_func().new_local(None, counter_type, "popcount_counter");
844846
let val = self.current_func().new_local(None, value_type, "popcount_value");
845-
let zero = self.context.new_rvalue_zero(counter_type);
847+
let zero = self.gcc_zero(counter_type);
846848
self.llbb().add_assignment(None, counter, zero);
847849
self.llbb().add_assignment(None, val, value);
848850
self.br(loop_head);
849851

850852
// check if value isn't zero
851853
self.switch_to_block(loop_head);
852-
let zero = self.context.new_rvalue_zero(value_type);
853-
let cond = self.context.new_comparison(None, ComparisonOp::NotEquals, val.to_rvalue(), zero);
854+
let zero = self.gcc_zero(value_type);
855+
let cond = self.gcc_icmp(IntPredicate::IntNE, val.to_rvalue(), zero);
854856
self.cond_br(cond, loop_body, loop_tail);
855857

856858
// val &= val - 1;
857859
self.switch_to_block(loop_body);
858-
let sub = val.to_rvalue() - self.context.new_rvalue_one(value_type);
859-
loop_body.add_assignment_op(None, val, BinaryOp::BitwiseAnd, sub);
860+
let one = self.gcc_int(value_type, 1);
861+
let sub = self.gcc_sub(val.to_rvalue(), one);
862+
let op = self.gcc_and(val.to_rvalue(), sub);
863+
loop_body.add_assignment(None, val, op);
860864

861865
// counter += 1
862-
let one = self.context.new_rvalue_one(counter_type);
863-
loop_body.add_assignment_op(None, counter, BinaryOp::Plus, one);
866+
let one = self.gcc_int(counter_type, 1);
867+
let op = self.gcc_add(counter.to_rvalue(), one);
868+
loop_body.add_assignment(None, counter, op);
864869
self.br(loop_head);
865870

866871
// end of loop
867872
self.switch_to_block(loop_tail);
868-
self.context.new_cast(None, counter.to_rvalue(), result_type)
873+
self.gcc_int_cast(counter.to_rvalue(), result_type)
869874
}
870875

871876
// Algorithm from: https://blog.regehr.org/archives/1063

0 commit comments

Comments
 (0)