aboutsummaryrefslogtreecommitdiff
path: root/builtins/integers.h
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-13 13:50:19 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-13 13:50:19 -0400
commit148782e61ba4efbf2981e7d9e18279e92054e149 (patch)
tree8ef1b1cf37957926ee944100265365cf4ebcce6f /builtins/integers.h
parent1ce826b9c3e9e57fe3acbd2abb5252bdeb630963 (diff)
Create inlined fast versions of integer ops
Diffstat (limited to 'builtins/integers.h')
-rw-r--r--builtins/integers.h129
1 files changed, 116 insertions, 13 deletions
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