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