maths: workaround clang lto ICE in renormalise
This commit is contained in:
parent
f0193ee825
commit
fb2888d2d5
52
maths.hpp
52
maths.hpp
@ -764,32 +764,48 @@ namespace util {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// lo_uint -> hi_uint
|
// lo_uint -> hi_uint
|
||||||
template <typename T, typename U>
|
template <
|
||||||
constexpr
|
typename SrcT,
|
||||||
typename std::enable_if<
|
typename DstT,
|
||||||
std::is_unsigned<T>::value &&
|
typename = std::enable_if_t<
|
||||||
std::is_unsigned<U>::value &&
|
std::is_unsigned<SrcT>::value &&
|
||||||
sizeof (T) < sizeof (U), U
|
std::is_unsigned<DstT>::value &&
|
||||||
>::type
|
sizeof (SrcT) < sizeof (DstT), DstT
|
||||||
renormalise (T t)
|
>
|
||||||
|
>
|
||||||
|
constexpr DstT
|
||||||
|
renormalise (SrcT src)
|
||||||
{
|
{
|
||||||
static_assert (sizeof (T) < sizeof (U),
|
// we can make some simplifying assumptions for the shift distances if
|
||||||
|
// we assume the integers are powers of two. this is probably going to
|
||||||
|
// be the case for every conceivable input type, but we don't want to
|
||||||
|
// get caught out if we extend this routine to more general types
|
||||||
|
// (eg, OpenGL DEPTH24).
|
||||||
|
static_assert (is_pow2 (sizeof (SrcT)));
|
||||||
|
static_assert (is_pow2 (sizeof (DstT)));
|
||||||
|
|
||||||
|
static_assert (sizeof (SrcT) < sizeof (DstT),
|
||||||
"assumes bit creation is required to fill space");
|
"assumes bit creation is required to fill space");
|
||||||
|
|
||||||
// we need to create bits. fill the output integer with copies of ourself.
|
// we need to create bits. fill the output integer with copies of ourself.
|
||||||
// this is approximately correct in the general case (introducing a small
|
// this is approximately correct in the general case (introducing a small
|
||||||
// linear positive bias), but allows us to fill the output space in the
|
// linear positive bias), but it allows us to set all output bits high
|
||||||
// case of input maximum.
|
// when we receive the maximum allowable input value.
|
||||||
|
static_assert (sizeof (DstT) % sizeof (SrcT) == 0,
|
||||||
static_assert (sizeof (U) % sizeof (T) == 0,
|
|
||||||
"assumes integer multiple of sizes");
|
"assumes integer multiple of sizes");
|
||||||
|
|
||||||
U out = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof (U) / sizeof (T); ++i)
|
// clang#xxxx: ideally we wouldn't use a multiplication here, but we
|
||||||
out |= U (t) << sizeof (T) * 8 * i;
|
// trigger a segfault in clang-5.0 when using ld.gold+lto;
|
||||||
|
// 'X86 DAG->DAG Instruction Selection'
|
||||||
return out;
|
//
|
||||||
|
// create a mask of locations we'd like copies of the src bit pattern.
|
||||||
|
//
|
||||||
|
// this replicates repeatedly or'ing and shifting dst with itself.
|
||||||
|
DstT dst { 1 };
|
||||||
|
for (unsigned i = sizeof (SrcT) * 8; i < sizeof (DstT) * 8; i *= 2)
|
||||||
|
dst |= dst << i;
|
||||||
|
return dst * src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user