SSE と union

はよ評価関数入れろやって感じなんですが、息抜きに高速化でも。
自分のCPU(Core2Duo T8300 2.4GHz)はSSE2までしか対応してないと思ってたけど、Bonanza6.0 の Makefile 見たらデフォルトでSSE4.1使ってて、普通に動いてました。
ってことでBitboardのSSE化にトライ。
SSE使うのもunion使うのも初めてでワクワクしました。


で、SSE使用前


SSE使用後


マジで? SSE使って速度1/4って何なん?
Bitboard のソースはこんな感じ。

class Bitboard;
extern const Bitboard SetMaskBB[SquareNum];
extern const Bitboard ClearMaskBB[SquareNum];

class Bitboard {
public:
	Bitboard() {}
	Bitboard(const u64 v0, const u64 v1) {
		this->p_[0] = v0;
		this->p_[1] = v1;
	}
	u64 p(const int index) const {
		return p_[index];
	}
	void set(const int index, const u64 val) {
		p_[index] = val;
	}
	// SSE 化出来るならすること。
	bool isNot0() const {
#ifdef HAVE_SSE4
		return !_mm_testz_si128(this->m_, _mm_set1_epi8(0xff));
#else		
		return (this->merge()) ? true : false;
#endif
	}
	u64 merge() const {
		return this->p(0) | this->p(1);
	}
	Bitboard operator ~ () const {
		Bitboard tmp;
		tmp.p_[0] = ~this->p(0);
		tmp.p_[1] = ~this->p(1);
		return tmp;
	}
	Bitboard operator &= (const Bitboard& rhs) {
#if defined (HAVE_SSE2) || defined (HAVE_SSE4)
		this->m_ = _mm_and_si128(this->m_, rhs.m_);
		return *this;
#else
		this->p_[0] &= rhs.p(0);
		this->p_[1] &= rhs.p(1);
		return *this;
#endif
	}
	Bitboard operator |= (const Bitboard& rhs) {
#if defined (HAVE_SSE2) || defined (HAVE_SSE4)
		this->m_ = _mm_or_si128(this->m_, rhs.m_);
		return *this;
#else
		this->p_[0] |= rhs.p(0);
		this->p_[1] |= rhs.p(1);
		return *this;
#endif
	}
	Bitboard operator ^= (const Bitboard& rhs) {
#if defined (HAVE_SSE2) || defined (HAVE_SSE4)
		this->m_ = _mm_xor_si128(this->m_, rhs.m_);
		return *this;
#else
		this->p_[0] ^= rhs.p(0);
		this->p_[1] ^= rhs.p(1);
		return *this;
#endif
	}
	Bitboard operator <<= (const int i) {
		this->p_[0] <<= i;
		this->p_[1] <<= i;
		return *this;
	}
	Bitboard operator >>= (const int i) {
		this->p_[0] >>= i;
		this->p_[1] >>= i;
		return *this;
	}
	Bitboard operator & (const Bitboard& rhs) const {
		Bitboard temp(*this);
		temp &= rhs;
		return temp;
	}
	Bitboard operator | (const Bitboard& rhs) const {
		Bitboard temp(*this);
		temp |= rhs;
		return temp;
	}
	Bitboard operator ^ (const Bitboard& rhs) const {
		Bitboard temp(*this);
		temp ^= rhs;
		return temp;
	}
	Bitboard operator << (const int i) const {
		Bitboard temp(*this);
		temp <<= i;
		return temp;
	}
	Bitboard operator >> (const int i) const {
		Bitboard temp(*this);
		temp >>= i;
		return temp;
	}
	// todo: SSE化すること。
	bool operator == (const Bitboard& rhs) const {
		return ((this->p(0) == rhs.p(0)) && (this->p(1) == rhs.p(1))) ? true : false;
	}
	// todo: SSE化すること。
	bool operator != (const Bitboard& rhs) const {
		return ((this->p(0) != rhs.p(0)) || (this->p(1) != rhs.p(1))) ? true : false;
	}
	bool isSet(const Square sq) const {
		return (*this & SetMaskBB[sq]).isNot0();
	}
	void setBit(const Square sq) {
		*this |= SetMaskBB[sq];
	}
	void clearBit(const Square sq) {
		*this &= ClearMaskBB[sq];
	}
	void xorBit(const Square sq) {
		(*this) ^= SetMaskBB[sq];
	}
	void xorBit(const Square sq1, const Square sq2) {
		(*this) ^= (SetMaskBB[sq1] | SetMaskBB[sq2]);
	}
	void xorBit(const Bitboard bb) {
		(*this) ^= bb;
	}
	// Bitboard の right 側だけの要素を調べて、最初に 1 であるマスの index を返す。
	// そのマスを 0 にする。
	// Bitboard の right 側が 0 でないことを前提にしている。
	Square firstOneRightFromI9() {
		const Square sq = static_cast<Square>(firstOneFromLSB(this->p(0)));
		// 最も LSB 側の 1 の bit を 0 にする
		this->p_[0] &= this->p(0) - 1;
		return sq;
	}
	// Bitboard の left 側だけの要素を調べて、最初に 1 であるマスの index を返す。
	// そのマスを 0 にする。
	// Bitboard の left 側が 0 でないことを前提にしている。
	Square firstOneLeftFromB9() {
		const Square sq = static_cast<Square>(firstOneFromLSB(this->p(1)) + 63);
		// 最も LSB 側の 1 の bit を 0 にする
		this->p_[1] &= this->p(1) - 1;
		return sq;
	}
	// Bitboard を I9 から A1 まで調べて、最初に 1 であるマスの index を返す。
	// そのマスを 0 にする。
	// Bitboard が Bitboard(0, 0) でないことを前提にしている。
	// VC++ の _BitScanForward() は入力が 0 のときに 0 を返す仕様なので、
	// 最初に 0 でないか判定するのは少し損。
	Square firstOneFromI9() {
		if(this->p(0)) {
			return firstOneRightFromI9();
		}
		return firstOneLeftFromB9();
	}
	// 返す位置を 0 にしないバージョン。不要かもしれない。
	Square constFirstOneRightFromI9() const {
		return static_cast<Square>(firstOneFromLSB(this->p(0)));
	}
	Square constFirstOneLeftFromB9() const {
		return static_cast<Square>(firstOneFromLSB(this->p(1)) + 63);
	}
	Square constFirstOneFromI9() const {
		if(this->p(0)) {
			return constFirstOneRightFromI9();
		}
		return constFirstOneLeftFromB9();
	}
	// bit が 1 つだけ立っているかどうかを判定する。
	// bit が 少なくとも 1 つは立っていると仮定する。
	bool isOneBit() const {
		assert(this->isNot0());
		if(this->p(0)) {
			return !((this->p(0) & (this->p(0) - 1)) | this->p(1));
		}
		return !(this->p(1) & (this->p(1) - 1));
	}

	void print() const {
		printf("%016"PRIx64", %016"PRIx64"\n", this->p(0), this->p(1));
	}
	void printBoard() const;

	// for debug
	void printTable(const int part) const {
		for(Rank r = Rank9; r < RankNum; ++r) {
			for(File f = FileC; FileI <= f; --f) {
				printf("%"PRIx64"", UINT64_C(1) & (this->p(part) >> makeSquare(f, r)));
			}
			printf("\n");
		}
		printf("\n");
	}

private:
#if defined (HAVE_SSE2) || defined (HAVE_SSE4)
	union {
		u64 p_[2];
		__m128i m_;
	};
#else
	u64 p_[2];	// p_[0] : 先手から見て、1一から7九までを縦に並べたbit. 63bit使用. right 呼ぶ。
				// p_[1] : 8一から1九までを縦に並べたbit. 18bit使用. left と呼ぶ。
#endif
};

使い方おかしいのかなぁ?もう少し調べます。