From 148782e61ba4efbf2981e7d9e18279e92054e149 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 13 Aug 2024 13:50:19 -0400 Subject: Create inlined fast versions of integer ops --- builtins/integers.c | 72 ++++++----------------------- builtins/integers.h | 129 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 129 insertions(+), 72 deletions(-) diff --git a/builtins/integers.c b/builtins/integers.c index 6a976d42..776fdc3d 100644 --- a/builtins/integers.c +++ b/builtins/integers.c @@ -137,12 +137,7 @@ public CORD Int$octal(Int_t i, Int_t digits_int, bool prefix) { } } -public Int_t Int$plus(Int_t x, Int_t y) { - - const int64_t z = (int64_t)((uint64_t)x.small + (uint64_t)y.small); - if (__builtin_expect(((z|2) == (int32_t)z), 1)) - return (Int_t){.small=(z-1)}; - +public Int_t Int$slow_plus(Int_t x, Int_t y) { mpz_t result; mpz_init_set_int(result, x); if (y.small & 1) { @@ -155,11 +150,7 @@ public Int_t Int$plus(Int_t x, Int_t y) { return Int$from_mpz(result); } -public Int_t Int$minus(Int_t x, Int_t y) { - const int64_t z = (int64_t)(((uint64_t)x.small ^ 3) - (uint64_t)y.small); - if (__builtin_expect(((z & ~2) == (int32_t)z), 1)) - return (Int_t){.small=z}; - +public Int_t Int$slow_minus(Int_t x, Int_t y) { mpz_t result; mpz_init_set_int(result, x); if (y.small & 1) { @@ -172,13 +163,7 @@ public Int_t Int$minus(Int_t x, Int_t y) { return Int$from_mpz(result); } -public Int_t Int$times(Int_t x, Int_t y) { - if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { - const int64_t z = (x.small>>1) * (y.small>>1); - if (__builtin_expect(z == (int32_t)z, 1)) - return (Int_t){.small=z+1}; - } - +public Int_t Int$slow_times(Int_t x, Int_t y) { mpz_t result; mpz_init_set_int(result, x); if (y.small & 1) { @@ -191,13 +176,7 @@ public Int_t Int$times(Int_t x, Int_t y) { return Int$from_mpz(result); } -public Int_t Int$divided_by(Int_t x, Int_t y) { - if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { - const int64_t z = 4*(x.small>>1) / (y.small>>1); - if (__builtin_expect(z == (int32_t)z, 1)) - return (Int_t){.small=z+1}; - } - +public Int_t Int$slow_divided_by(Int_t x, Int_t y) { mpz_t result; mpz_init_set_int(result, x); if (y.small & 1) { @@ -210,7 +189,7 @@ public Int_t Int$divided_by(Int_t x, Int_t y) { return Int$from_mpz(result); } -public Int_t Int$modulo(Int_t x, Int_t modulus) +public Int_t Int$slow_modulo(Int_t x, Int_t modulus) { mpz_t result; mpz_init_set_int(result, x); @@ -220,7 +199,7 @@ public Int_t Int$modulo(Int_t x, Int_t modulus) return Int$from_mpz(result); } -public Int_t Int$modulo1(Int_t x, Int_t modulus) +public Int_t Int$slow_modulo1(Int_t x, Int_t modulus) { mpz_t result; mpz_init_set_int(result, x); @@ -232,14 +211,8 @@ public Int_t Int$modulo1(Int_t x, Int_t modulus) return Int$from_mpz(result); } -public Int_t Int$left_shifted(Int_t x, Int_t y) +public Int_t Int$slow_left_shifted(Int_t x, Int_t y) { - if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { - const int64_t z = 4*((x.small>>2) << (y.small>>2)); - if (__builtin_expect(z == (int32_t)z, 1)) - return (Int_t){.small=z+1}; - } - mp_bitcnt_t bits = (mp_bitcnt_t)Int$as_i64(y); mpz_t result; mpz_init_set_int(result, x); @@ -247,14 +220,8 @@ public Int_t Int$left_shifted(Int_t x, Int_t y) return Int$from_mpz(result); } -public Int_t Int$right_shifted(Int_t x, Int_t y) +public Int_t Int$slow_right_shifted(Int_t x, Int_t y) { - if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { - const int64_t z = 4*((x.small>>2) >> (y.small>>2)); - if (__builtin_expect(z == (int32_t)z, 1)) - return (Int_t){.small=z+1}; - } - mp_bitcnt_t bits = (mp_bitcnt_t)Int$as_i64(y); mpz_t result; mpz_init_set_int(result, x); @@ -262,12 +229,8 @@ public Int_t Int$right_shifted(Int_t x, Int_t y) return Int$from_mpz(result); } -public Int_t Int$bit_and(Int_t x, Int_t y) +public Int_t Int$slow_bit_and(Int_t x, Int_t y) { - const int64_t z = x.small & y.small; - if (__builtin_expect((z & 1) == 1, 1)) - return (Int_t){.small=z}; - mpz_t result; mpz_init_set_int(result, x); mpz_t y_mpz; @@ -276,11 +239,8 @@ public Int_t Int$bit_and(Int_t x, Int_t y) return Int$from_mpz(result); } -public Int_t Int$bit_or(Int_t x, Int_t y) +public Int_t Int$slow_bit_or(Int_t x, Int_t y) { - if (__builtin_expect(((x.small & y.small) & 1) == 1, 1)) - return (Int_t){.small=(x.small | y.small)}; - mpz_t result; mpz_init_set_int(result, x); mpz_t y_mpz; @@ -289,11 +249,8 @@ public Int_t Int$bit_or(Int_t x, Int_t y) return Int$from_mpz(result); } -public Int_t Int$bit_xor(Int_t x, Int_t y) +public Int_t Int$slow_bit_xor(Int_t x, Int_t y) { - if (__builtin_expect(((x.small & y.small) & 1) == 1, 1)) - return (Int_t){.small=(x.small ^ y.small) | 1}; - mpz_t result; mpz_init_set_int(result, x); mpz_t y_mpz; @@ -302,11 +259,8 @@ public Int_t Int$bit_xor(Int_t x, Int_t y) return Int$from_mpz(result); } -public Int_t Int$negated(Int_t x) +public Int_t Int$slow_negated(Int_t x) { - if (__builtin_expect((x.small & 1), 1)) - return (Int_t){.small=(~x.small) ^ 3}; - mpz_t result; mpz_init_set_int(result, x); mpz_neg(result, result); @@ -314,7 +268,7 @@ public Int_t Int$negated(Int_t x) return Int$from_mpz(result); } -public Int_t Int$negative(Int_t x) +public Int_t Int$slow_negative(Int_t x) { if (__builtin_expect((x.small & 1), 1)) return (Int_t){.small=4*-((x.small)>>2) + 1}; diff --git a/builtins/integers.h b/builtins/integers.h index 218d8d23..f9051ff5 100644 --- a/builtins/integers.h +++ b/builtins/integers.h @@ -82,22 +82,125 @@ Int_t Int$from_num(double n); double Int$as_num(Int_t i); #define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int$from_i64(i)) -Int_t Int$plus(Int_t x, Int_t y); -Int_t Int$minus(Int_t x, Int_t y); -Int_t Int$times(Int_t x, Int_t y); -Int_t Int$divided_by(Int_t x, Int_t y); -Int_t Int$modulo(Int_t x, Int_t y); -Int_t Int$modulo1(Int_t x, Int_t y); -Int_t Int$left_shifted(Int_t x, Int_t y); -Int_t Int$right_shifted(Int_t x, Int_t y); -Int_t Int$bit_and(Int_t x, Int_t y); -Int_t Int$bit_or(Int_t x, Int_t y); -Int_t Int$bit_xor(Int_t x, Int_t y); -Int_t Int$negative(Int_t x); -Int_t Int$negated(Int_t x); +Int_t Int$slow_plus(Int_t x, Int_t y); +Int_t Int$slow_minus(Int_t x, Int_t y); +Int_t Int$slow_times(Int_t x, Int_t y); +Int_t Int$slow_divided_by(Int_t x, Int_t y); +Int_t Int$slow_modulo(Int_t x, Int_t y); +Int_t Int$slow_modulo1(Int_t x, Int_t y); +Int_t Int$slow_left_shifted(Int_t x, Int_t y); +Int_t Int$slow_right_shifted(Int_t x, Int_t y); +Int_t Int$slow_bit_and(Int_t x, Int_t y); +Int_t Int$slow_bit_or(Int_t x, Int_t y); +Int_t Int$slow_bit_xor(Int_t x, Int_t y); +Int_t Int$slow_negative(Int_t x); +Int_t Int$slow_negated(Int_t x); Int_t Int$abs(Int_t x); extern const TypeInfo $Int; +// Fast-path inline versions for the common case where integer arithmetic is +// between two small ints. + +static inline Int_t Int$plus(Int_t x, Int_t y) { + const int64_t z = (int64_t)((uint64_t)x.small + (uint64_t)y.small); + if (__builtin_expect(((z|2) == (int32_t)z), 1)) + return (Int_t){.small=(z-1)}; + return Int$slow_plus(x, y); +} + +static inline Int_t Int$minus(Int_t x, Int_t y) { + const int64_t z = (int64_t)(((uint64_t)x.small ^ 3) - (uint64_t)y.small); + if (__builtin_expect(((z & ~2) == (int32_t)z), 1)) + return (Int_t){.small=z}; + return Int$slow_minus(x, y); +} + +static inline Int_t Int$times(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { + const int64_t z = (x.small>>1) * (y.small>>1); + if (__builtin_expect(z == (int32_t)z, 1)) + return (Int_t){.small=z+1}; + } + return Int$slow_times(x, y); +} + +static inline Int_t Int$divided_by(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { + const int64_t z = 4*(x.small>>1) / (y.small>>1); + if (__builtin_expect(z == (int32_t)z, 1)) + return (Int_t){.small=z+1}; + } + return Int$slow_divided_by(x, y); +} + +static inline Int_t Int$modulo(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { + int64_t mod = (x.small>>2) % (y.small>>2); + if (mod < 0) mod += (y.small>>2); + return (Int_t){.small=(mod<<2)+1}; + } + return Int$slow_modulo(x, y); +} + +static inline Int_t Int$modulo1(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { + int64_t mod = ((x.small>>2)-1) % (y.small>>2); + if (mod < 0) mod += (y.small>>2); + return (Int_t){.small=((mod+1)<<2)+1}; + } + return Int$slow_modulo1(x, y); +} + +static inline Int_t Int$left_shifted(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { + const int64_t z = 4*((x.small>>2) << (y.small>>2)); + if (__builtin_expect(z == (int32_t)z, 1)) + return (Int_t){.small=z+1}; + } + return Int$slow_left_shifted(x, y); +} + +static inline Int_t Int$right_shifted(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) != 0, 1)) { + const int64_t z = 4*((x.small>>2) >> (y.small>>2)); + if (__builtin_expect(z == (int32_t)z, 1)) + return (Int_t){.small=z+1}; + } + return Int$slow_right_shifted(x, y); +} + +static inline Int_t Int$bit_and(Int_t x, Int_t y) { + const int64_t z = x.small & y.small; + if (__builtin_expect((z & 1) == 1, 1)) + return (Int_t){.small=z}; + return Int$slow_bit_and(x, y); +} + +static inline Int_t Int$bit_or(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) == 1, 1)) + return (Int_t){.small=(x.small | y.small)}; + return Int$slow_bit_or(x, y); +} + +static inline Int_t Int$bit_xor(Int_t x, Int_t y) { + if (__builtin_expect(((x.small & y.small) & 1) == 1, 1)) + return (Int_t){.small=(x.small ^ y.small) | 1}; + return Int$slow_bit_xor(x, y); +} + +static inline Int_t Int$negated(Int_t x) +{ + if (__builtin_expect((x.small & 1), 1)) + return (Int_t){.small=(~x.small) ^ 3}; + return Int$slow_negated(x); +} + +static inline Int_t Int$negative(Int_t x) +{ + if (__builtin_expect((x.small & 1), 1)) + return (Int_t){.small=4*-((x.small)>>2) + 1}; + return Int$slow_negative(x); +} // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 -- cgit v1.2.3