I just discovered Gigantua which inspired me to further optimize my engine with compile time functions. But as I'm a newbie I don't grasp everything just yet. At the moment my engine runs about 100% slower than Gigantua but fully run time so I'm hoping I can further improve this.
I was going through the source code and the "compile time" pext lookup grabbed my attention.
What makes it work for the compiler to allow it to produce a constant expression?
What is missing from this simple function call to make it a constant expression? Just like Gigantua, the parameters are initiliazed as const, and all my arrays are constexpr defined in a file.
Code: Select all
__forceinline static constexpr U64 getRookAttacksC(int square, U64 occupancy) {
return ROOK_ATTACKS[ROOK_OFFSETS[square] + _pext_u64(occupancy, ROOK_MASKS[square])];
}
Struct (removed some irrelevant code)
Code: Select all
struct SliderPext_t
{
const uint64_t* AttackPtr;
const uint64_t Mask;
constexpr SliderPext_t(int offset, uint64_t mask) : AttackPtr(SliderPext + offset), Mask(mask) {
}
_ForceInline constexpr uint64_t operator[](const uint64_t blocker) const
{
if (std::is_constant_evaluated()) {
return AttackPtr[_pext_u64_emulated(blocker, Mask)];
}
else {
return AttackPtr[_pext_u64(blocker, Mask)];
}
}
};
Code: Select all
static const SliderPext_t Pext_RookAttacks[64] = {
SliderPext_t(RookOffset_Pext[0], rmask[0]),
SliderPext_t(RookOffset_Pext[1], rmask[1]),
......
Code: Select all
_Compiletime uint64_t Rook(uint64_t square, uint64_t occupy) {
return Pext_RookAttacks[square][occupy];
}