about summary refs log tree commit diff
diff options
context:
space:
mode:
authorantoyo <antoyo@users.noreply.github.com>2023-10-19 07:42:50 -0400
committerGitHub <noreply@github.com>2023-10-19 07:42:50 -0400
commit2096606684e43302aaa5cd8f64e5ed92e0eac292 (patch)
treef89285198c1c05b27ba168be268d81b95a05e03b
parenta9f31ab4814a936c91dec8be0da8807c7210b44a (diff)
parent81c1f39a86295df471d5d7341a15c4bff44c2545 (diff)
downloadrust-2096606684e43302aaa5cd8f64e5ed92e0eac292.tar.gz
rust-2096606684e43302aaa5cd8f64e5ed92e0eac292.zip
Merge pull request #354 from sadlerap/popcount-128-bits
optimize u128/i128 popcounts further
-rw-r--r--src/intrinsic/mod.rs25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs
index 32cc724bb19..69927b28cd5 100644
--- a/src/intrinsic/mod.rs
+++ b/src/intrinsic/mod.rs
@@ -4,7 +4,7 @@ mod simd;
 #[cfg(feature="master")]
 use std::iter;
 
-use gccjit::{BinaryOp, ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
+use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::common::IntPredicate;
@@ -819,7 +819,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 value
             };
 
-        if value_type.is_u128(&self.cx) {
+        // only break apart 128-bit ints if they're not natively supported
+        // TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
+        if value_type.is_u128(&self.cx) && !self.cx.supports_128bit_integers {
             let sixty_four = self.gcc_int(value_type, 64);
             let right_shift = self.gcc_lshr(value, sixty_four);
             let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
@@ -842,30 +844,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let counter_type = self.int_type;
         let counter = self.current_func().new_local(None, counter_type, "popcount_counter");
         let val = self.current_func().new_local(None, value_type, "popcount_value");
-        let zero = self.context.new_rvalue_zero(counter_type);
+        let zero = self.gcc_zero(counter_type);
         self.llbb().add_assignment(None, counter, zero);
         self.llbb().add_assignment(None, val, value);
         self.br(loop_head);
 
         // check if value isn't zero
         self.switch_to_block(loop_head);
-        let zero = self.context.new_rvalue_zero(value_type);
-        let cond = self.context.new_comparison(None, ComparisonOp::NotEquals, val.to_rvalue(), zero);
+        let zero = self.gcc_zero(value_type);
+        let cond = self.gcc_icmp(IntPredicate::IntNE, val.to_rvalue(), zero);
         self.cond_br(cond, loop_body, loop_tail);
 
         // val &= val - 1;
         self.switch_to_block(loop_body);
-        let sub = val.to_rvalue() - self.context.new_rvalue_one(value_type);
-        loop_body.add_assignment_op(None, val, BinaryOp::BitwiseAnd, sub);
+        let one = self.gcc_int(value_type, 1);
+        let sub = self.gcc_sub(val.to_rvalue(), one);
+        let op = self.gcc_and(val.to_rvalue(), sub);
+        loop_body.add_assignment(None, val, op);
 
         // counter += 1
-        let one = self.context.new_rvalue_one(counter_type);
-        loop_body.add_assignment_op(None, counter, BinaryOp::Plus, one);
+        let one = self.gcc_int(counter_type, 1);
+        let op = self.gcc_add(counter.to_rvalue(), one);
+        loop_body.add_assignment(None, counter, op);
         self.br(loop_head);
 
         // end of loop
         self.switch_to_block(loop_tail);
-        self.context.new_cast(None, counter.to_rvalue(), result_type)
+        self.gcc_int_cast(counter.to_rvalue(), result_type)
     }
 
     // Algorithm from: https://blog.regehr.org/archives/1063