Mill Computing, Inc. Forums The Mill Architecture Switches Reply To: Switches

Thomas D
Participant
Post count: 24

Does the Mill provide any features for handling indirect (virtual) function calls? In, say C++, you can wrap switch cases in classes and turn the switch statement into a virtual function call. Does the Mill have any improvements to handle this?

Say I have this simple state machine (I hope these come out well):

#include <iostream>

int main (void)
 {
   long i [10];

   i[0] = 1;
   *reinterpret_cast<double*>(reinterpret_cast<void*>(&i[1])) = 3.0; // Assume LP64
   i[2] = 1;
   *reinterpret_cast<double*>(reinterpret_cast<void*>(&i[3])) = 5.0; // And IEEE-754 double
   i[4] = 2;
   i[5] = 3;
   i[6] = 0;

   const int BELT_SIZE = 10;
   double belt [BELT_SIZE];
   int front = BELT_SIZE - 1;
   int pc = 0;

   while (0 != i[pc])
    {
      switch(i[pc++])
       {
         case 1:
            front = (front + 1) % BELT_SIZE;
            belt[front] = *reinterpret_cast<double*>(reinterpret_cast<void*>(&i[pc++]));
            break;
         case 2:
          {
            int lhs = front;
            int rhs = (front + BELT_SIZE - 1) % BELT_SIZE;
            front = (front + 1) % BELT_SIZE;
            belt[front] = belt[lhs] + belt[rhs];
          }
            break;
         case 3:
            std::cout << belt[front] << std::endl;
            break;
       }
    }

   return 0;
 }

I can make it Object-Oriented, trying to follow the Interpreter Pattern:

#include <iostream>

const int BELT_SIZE = 10;

class operation
 {
   public:
      operation() : next(nullptr) { }
      virtual operation *execute(double *belt, int &front) const = 0;
      virtual ~operation()
       {
         delete next;
         next = nullptr;
       }
      operation *next;
 };

class value : public operation
 {
   public:
      value(double val) : val(val) { }
      double val;
      operation * execute(double *belt, int &front) const
       {
         front = (front + 1) % BELT_SIZE;
         belt[front] = val;
         return next;
       }
 };

class add : public operation
 {
   public:
      operation * execute(double *belt, int &front) const
       {
         int lhs = front;
         int rhs = (front + BELT_SIZE - 1) % BELT_SIZE;
         front = (front + 1) % BELT_SIZE;
         belt[front] = belt[lhs] + belt[rhs];
         return next;
       }
 };

class print : public operation
 {
   public:
      operation * execute(double *belt, int &front) const
       {
         std::cout << belt[front] << std::endl;
         return next;
       }
 };

int main (void)
 {
   operation *first = nullptr, *cur = nullptr;

   first = new value(3.0);
   cur = first;
   cur->next = new value(5.0);
   cur = cur->next;
   cur->next = new add();
   cur = cur->next;
   cur->next = new print();

   double belt [BELT_SIZE];
   int front = BELT_SIZE - 1;
   cur = first;

   while (nullptr != cur)
    {
      cur = cur->execute(belt, front);
    }

   delete first;
   first = nullptr;
   cur = nullptr;

   return 0;
 }

Will the Mill mispredict the while loop as bad as any modern superscalar? Or is there yet another Not-Yet-Filed patent up your sleeve?