]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
fib.fth benchmark; some minor coreword optimizations
authorClyne Sullivan <clyne@bitgloo.com>
Wed, 8 Nov 2023 20:31:44 +0000 (15:31 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Wed, 8 Nov 2023 20:31:44 +0000 (15:31 -0500)
alee.cpp
forth/fib.fth [new file with mode: 0644]
libalee/corewords.cpp
libalee/state.hpp

index 55cae573635c048aa6f4b9a17711a4682e0b985b..99bc276fa8cab012437530021f67af34f2962693 100644 (file)
--- a/alee.cpp
+++ b/alee.cpp
@@ -20,6 +20,7 @@
 #include "memdict.hpp"
 
 #include <charconv>
+#include <chrono>
 #include <fstream>
 #include <iostream>
 #include <vector>
@@ -82,6 +83,8 @@ static void load(State& state)
 
 void user_sys(State& state)
 {
+    static std::chrono::time_point<std::chrono::high_resolution_clock> last;
+    static bool start = false;
     char buf[32] = {0};
 
     switch (state.pop()) {
@@ -102,6 +105,20 @@ void user_sys(State& state)
     case 4: // load
         load(state);
         break;
+    case 5: // time
+        if (!start) {
+            start = true;
+            last = std::chrono::high_resolution_clock::now();
+        } else {
+            start = false;
+            auto diff = std::chrono::duration_cast<std::chrono::microseconds>(
+                std::chrono::high_resolution_clock::now() - last);
+            state.push((Cell)diff.count());
+        }
+        break;
+    case 6: // double-add
+        { auto sum = state.popd() + state.popd(); state.pushd(sum); }
+        break;
     default:
         break;
     }
diff --git a/forth/fib.fth b/forth/fib.fth
new file mode 100644 (file)
index 0000000..82c87cd
--- /dev/null
@@ -0,0 +1,19 @@
+: fib ( n -- d )
+  >r 0 dup 1 0 r> 0 do
+  2dup 2>r 2swap 6 sys 2r> 2swap loop 2drop ;
+
+: fibtest ( n -- )
+  0 do i fib <# #s #> type space loop ;
+
+: fibbench ( n -- )
+  5 sys fib 5 sys >r 2drop r> ;
+
+variable avg 0 avg !
+100 constant iters
+
+: bench ( -- )
+  iters 0 do 100 fibbench avg +! loop
+  avg @ iters / avg ! ;
+
+bench ." avg time: " avg @ . ." us" cr
+bye
index e3ba6b3b05513ea13eabce3d00a02cdf6378997e..e323ed97b30965a89dfc0c31d4d16801ed48a21e 100644 (file)
@@ -39,31 +39,17 @@ void find(State& state, Word word)
 
 void CoreWords::run(Cell ins, State& state)
 {
-    Cell cell;
     DoubleCell dcell;
-
-    Addr index = ins;
-
+    const Addr index = ins;
     auto& ip = state.ip();
 
-    auto popd = [](State& s) {
-        DoubleCell dcell = s.pop();
-        dcell <<= sizeof(Cell) * 8;
-        dcell |= static_cast<Addr>(s.pop());
-        return dcell;
-    };
-
-    auto pushd = [](State& s, DoubleCell d) {
-        s.push(static_cast<Cell>(d));
-        s.push(static_cast<Cell>(d >> (sizeof(Cell) * 8)));
-    };
-
-execute:
     if (index >= Dictionary::Begin) {
         // must be calling a defined subroutine
         state.pushr(ip);
         ip = index;
         return;
+    } else if (index >= WordCount) {
+        state.push(index - WordCount);
     } else switch (index) {
     case 0: // _lit
         state.push(state.beyondip());
@@ -84,27 +70,25 @@ execute:
         user_sys(state);
         break;
     case 6: // add
-        cell = state.pop();
-        state.top() += cell;
+        { auto& cell = state.pop(); state.top() += cell; }
         break;
     case 7: // sub
-        cell = state.pop();
-        state.top() -= cell;
+        { auto& cell = state.pop(); state.top() -= cell; }
         break;
     case 8: // mul ( n n -- d )
-        cell = state.pop();
-        dcell = state.pop() * cell;
-        pushd(state, dcell);
+        { auto& cell = state.pop();
+          dcell = state.pop() * cell;
+          state.pushd(dcell); }
         break;
     case 9: // div ( d n -- n )
-        cell = state.pop();
-        dcell = popd(state);
-        state.push(static_cast<Cell>(dcell / cell));
+        { auto& cell = state.pop();
+          dcell = state.popd();
+          state.push(static_cast<Cell>(dcell / cell)); }
         break;
     case 10: // mod ( d n -- n )
-        cell = state.pop();
-        dcell = popd(state);
-        state.push(static_cast<Cell>(dcell % cell));
+        { auto& cell = state.pop();
+          dcell = state.popd();
+          state.push(static_cast<Cell>(dcell % cell)); }
         break;
     case 11: // peek
         if (state.pop())
@@ -113,11 +97,11 @@ execute:
             state.push(state.dict.readbyte(state.pop()));
         break;
     case 12: // poke
-        cell = state.pop();
-        if (auto addr = state.pop(); cell)
-            state.dict.write(addr, state.pop());
-        else
-            state.dict.writebyte(addr, state.pop() & 0xFFu);
+        { auto& cell = state.pop();
+          if (auto addr = state.pop(); cell)
+              state.dict.write(addr, state.pop());
+          else
+              state.dict.writebyte(addr, state.pop() & 0xFFu); }
         break;
     case 13: // pushr
         state.pushr(state.pop());
@@ -126,32 +110,29 @@ execute:
         state.push(state.popr());
         break;
     case 15: // equal
-        cell = state.pop();
-        state.top() = state.top() == cell ? -1 : 0;
+        { auto& cell = state.pop();
+          state.top() = state.top() == cell ? -1 : 0; }
         break;
     case 16: // lt
-        cell = state.pop();
-        state.top() = state.top() < cell ? -1 : 0;
+        { auto& cell = state.pop();
+          state.top() = state.top() < cell ? -1 : 0; }
         break;
     case 17: // and
-        cell = state.pop();
-        state.top() &= cell;
+        { auto& cell = state.pop(); state.top() &= cell; }
         break;
     case 18: // or
-        cell = state.pop();
-        state.top() |= cell;
+        { auto& cell = state.pop(); state.top() |= cell; }
         break;
     case 19: // xor
-        cell = state.pop();
-        state.top() ^= cell;
+        { auto& cell = state.pop(); state.top() ^= cell; }
         break;
     case 20: // shl
-        cell = state.pop();
-        reinterpret_cast<Addr&>(state.top()) <<= static_cast<Addr>(cell);
+        { auto& cell = state.pop();
+          reinterpret_cast<Addr&>(state.top()) <<= static_cast<Addr>(cell); }
         break;
     case 21: // shr
-        cell = state.pop();
-        reinterpret_cast<Addr&>(state.top()) >>= static_cast<Addr>(cell);
+        { auto& cell = state.pop();
+          reinterpret_cast<Addr&>(state.top()) >>= static_cast<Addr>(cell); }
         break;
     case 22: // colon
         state.push(state.dict.alignhere());
@@ -167,8 +148,8 @@ execute:
         find(state, state.dict.input());
         break;
     case 24: // execute
-        index = state.pop();
-        goto execute;
+        ip = state.pop();
+        return;
     case 25: // exit
         ip = state.popr();
         state.verify(ip != 0, Error::exit);
@@ -177,14 +158,18 @@ execute:
         state.dict.add(findi("exit"));
         state.compiling(false);
 
-        cell = state.pop();
-        dcell = cell - state.dict.latest();
-        if (dcell > (1 << (sizeof(Cell) * 8 - 6)) - 1) {
-            state.dict.write(static_cast<Addr>(cell) + sizeof(Cell), static_cast<Cell>(dcell));
-            dcell = ((1 << (sizeof(Cell) * 8 - 6)) - 1);
+        {
+            auto& cell = state.pop();
+            dcell = cell - state.dict.latest();
+            if (dcell > (1 << (sizeof(Cell) * 8 - 6)) - 1) {
+                state.dict.write(static_cast<Addr>(cell) + sizeof(Cell),
+                    static_cast<Cell>(dcell));
+                dcell = ((1 << (sizeof(Cell) * 8 - 6)) - 1);
+            }
+            state.dict.write(cell,
+                (state.dict.read(cell) & 0x1F) | static_cast<Cell>(dcell << 6));
+            state.dict.latest(cell);
         }
-        state.dict.write(cell, (state.dict.read(cell) & 0x1F) | static_cast<Cell>(dcell << 6));
-        state.dict.latest(cell);
         break;
     case 27: // _jmp0
         if (state.pop()) {
@@ -213,39 +198,38 @@ execute:
         }
         break;
     case 33: // find
-        cell = state.pop();
-        find(state,
-             Word::fromLength(static_cast<Addr>(cell + 1),
-                              state.dict.readbyte(cell)));
+        { auto& cell = state.pop();
+          find(state,
+               Word::fromLength(static_cast<Addr>(cell + 1),
+                                state.dict.readbyte(cell))); }
         break;
     case 34: // _uma
         {
-        const auto plus = state.pop();
-        cell = state.pop();
-        dcell = popd(state);
-        dcell *= static_cast<Addr>(cell);
-        dcell += static_cast<Addr>(plus);
-        pushd(state, dcell);
+            const auto& plus = state.pop();
+            const auto& cell = state.pop();
+            dcell = state.popd();
+            dcell *= static_cast<Addr>(cell);
+            dcell += static_cast<Addr>(plus);
+            state.pushd(dcell);
         }
         break;
     case 35: // u<
-        cell = state.pop();
-        state.top() = static_cast<Addr>(state.top()) <
-                      static_cast<Addr>(cell) ? -1 : 0;
+        { auto& cell = state.pop();
+          state.top() = static_cast<Addr>(state.top()) <
+                        static_cast<Addr>(cell) ? -1 : 0; }
         break;
     case 36: // um/mod
-        cell = state.pop();
-        dcell = popd(state);
-
-        state.push(static_cast<Cell>(
-            static_cast<DoubleAddr>(dcell) %
-            static_cast<Addr>(cell)));
-        state.push(static_cast<Cell>(
-            static_cast<DoubleAddr>(dcell) /
-            static_cast<Addr>(cell)));
-        break;
-    default:
-        state.push(ins - WordCount);
+        {
+            const auto& cell = state.pop();
+            dcell = state.popd();
+
+            state.push(static_cast<Cell>(
+                static_cast<DoubleAddr>(dcell) %
+                static_cast<Addr>(cell)));
+            state.push(static_cast<Cell>(
+                static_cast<DoubleAddr>(dcell) /
+                static_cast<Addr>(cell)));
+        }
         break;
     }
 
index e77a223bd7375323a235e951c8d3fdc07ecd7d69..2e69463da0c41aadd66f9a217d0208232dbb494d 100644 (file)
@@ -87,31 +87,42 @@ public:
         *dsp++ = value;
     }
 
-    inline Cell pop() {
+    inline const Cell& pop() {
         verify(dsp > dstack, Error::pop);
         return *--dsp;
     }
 
+    inline DoubleCell popd() {
+        DoubleCell dcell = pop();
+        dcell <<= sizeof(Cell) * 8;
+        dcell |= static_cast<Addr>(pop());
+        return dcell;
+    }
+
+    inline void pushd(DoubleCell d) {
+        push(static_cast<Cell>(d));
+        push(static_cast<Cell>(d >> (sizeof(Cell) * 8)));
+    }
+
     inline void pushr(Cell value) {
         verify(rsp < rstack + ReturnStackSize, Error::pushr);
         *rsp++ = value;
     }
 
-    inline Cell popr() {
+    inline const Cell& popr() {
         verify(rsp > rstack, Error::popr);
         return *--rsp;
     }
 
-    inline Cell& top() {
-        verify(dsp > dstack, Error::top);
-        return *(dsp - 1);
-    }
-
     inline Cell& pick(std::size_t i) {
         verify(dsp - i > dstack, Error::pick);
         return *(dsp - i - 1);
     }
 
+    inline Cell& top() {
+        return pick(0);
+    }
+
     // Advances the instruction pointer and returns that cell's contents.
     inline Cell beyondip() {
         context.ip += sizeof(Cell);