GCC with -O2 setting optimizes very aggressively. In most cases where it makes a potentially 'unsafe' assumption it gives at least a warning. I had to rewrite some code pieces due to pointer-aliasing but that was pretty straightforward.
The biggest headache was with the following code:
Code: Select all
inline Score eg_value(ScorePair s) {
  return Score(short(s & 0xffff));
}
inline Score mg_value(ScorePair s) {
  return Score((int(s) + 0x8000) >> 16);
}
In desperation, I took a look at StockFish's value.h and indeed found a solution therein (SF guys are much better at C/C++ stuff than me).
Now this code works correctly:
Code: Select all
#ifdef __GNUC__
inline Score eg_value(ScorePair s) {
  return Score((int)(unsigned(s) & 0x7fffu) - (int)(unsigned(s) & 0x8000u));
}
inline Score mg_value(ScorePair s) {
  return Score(((int(s) + 0x8000) & ~0xffff) / 0x10000);
}
#else
inline Score eg_value(ScorePair s) {
  return Score(short(s & 0xffff));
}
inline Score mg_value(ScorePair s) {
  return Score((int(s) + 0x8000) >> 16);
}
#endif
Contrary to my fears, the threading, locking and signaling stuff wasn't very hard to port. In case someone finds it useful here is my smp.h:
Code: Select all
#pragma once
#ifdef _WIN32
#include <windows.h>
class Event {
  HANDLE hEvent;
public:
  inline Event() {};
  inline void init() { 
    hEvent = CreateEvent(NULL, false, false, NULL); 
  }
  inline void destroy() { 
    CloseHandle(hEvent); 
  }
  inline void signal() { 
    SetEvent(hEvent); 
  }
  inline void wait_for() { 
    WaitForSingleObject(hEvent, INFINITE); 
  }
  inline bool wait_for(int timeout) {
    return (WaitForSingleObject(hEvent, timeout) == WAIT_TIMEOUT);
  }
};
#define ThreadProcResult DWORD WINAPI
typedef LPVOID ThreadProcParam;
typedef ThreadProcResult ThreadProc(ThreadProcParam);
inline void start_thread(ThreadProc proc, ThreadProcParam param) {
  DWORD tid;
  CloseHandle(CreateThread(NULL, 0, proc, param, 0, &tid));
}
typedef CRITICAL_SECTION Lock;
#define lock_init(lock) InitializeCriticalSection(&(lock))
#define lock_acquire(lock) EnterCriticalSection(&(lock))
#define lock_release(lock) LeaveCriticalSection(&(lock))
#define lock_delete(lock) DeleteCriticalSection(&(lock))
#else
#include <pthread.h>
#include <errno.h>
class Event {
  pthread_cond_t cond;
  pthread_mutex_t mutex;
  volatile bool signaled;
public:
  inline Event() {};
  inline void init() {
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);
    signaled = false;
  }
  inline void destroy() {
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);
  }
  inline void signal() {
    pthread_mutex_lock(&mutex);
    pthread_cond_broadcast(&cond);
    signaled = true;
    pthread_mutex_unlock(&mutex);
  }
  inline void wait_for() {
    pthread_mutex_lock(&mutex);
    if (!signaled)
      pthread_cond_wait(&cond, &mutex);
    signaled = false;
    pthread_mutex_unlock(&mutex);
  }
  inline bool wait_for(int timeout) {
    pthread_mutex_lock(&mutex);
    int res = 0;
    if (!signaled) {
      struct timespec abstime;
      abstime.tv_sec  = timeout / 1000000;
      abstime.tv_nsec = timeout % 1000000;
      res = pthread_cond_timedwait(&cond, &mutex, &abstime);
    }
    signaled = false;
    pthread_mutex_unlock(&mutex);
    return (res == ETIMEDOUT);
  }
};
#define ThreadProcResult void *
typedef void * ThreadProcParam;
typedef ThreadProcResult ThreadProc(ThreadProcParam);
inline void start_thread(ThreadProc proc, ThreadProcParam param) {
  pthread_t pthread[1];
  pthread_attr_t attrib;
  pthread_attr_init(&attrib);
  pthread_create(pthread, &attrib, proc, param);
}
typedef pthread_mutex_t Lock;
#define lock_init(x) pthread_mutex_init(&(x), NULL)
#define lock_acquire(x) pthread_mutex_lock(&(x))
#define lock_release(x) pthread_mutex_unlock(&(x))
#define lock_delete(x) pthread_mutex_destroy(&(x))
#endif


