From c684d586cb3c124414d3d949161e47d05095af60 Mon Sep 17 00:00:00 2001 From: Etienne Renault Date: Fri, 13 Jul 2018 09:15:38 +0000 Subject: [PATCH] misc: add clz wrapper for builtin * spot/bricks/brick-bitlevel, spot/misc/Makefile.am, spot/misc/bitset.hh, spot/misc/clz.cc, spot/misc/clz.hh, spot/misc/fixpool.hh: here. --- spot/bricks/brick-bitlevel | 7 ++- spot/misc/Makefile.am | 2 + spot/misc/bitset.hh | 3 +- spot/misc/clz.cc | 115 +++++++++++++++++++++++++++++++++++++ spot/misc/clz.hh | 33 +++++++++++ spot/misc/fixpool.hh | 6 +- 6 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 spot/misc/clz.cc create mode 100644 spot/misc/clz.hh diff --git a/spot/bricks/brick-bitlevel b/spot/bricks/brick-bitlevel index 86d8ce265..0c33b8ee9 100644 --- a/spot/bricks/brick-bitlevel +++ b/spot/bricks/brick-bitlevel @@ -37,6 +37,7 @@ #include #include +#include #ifndef BRICK_BITLEVEL_H #define BRICK_BITLEVEL_H @@ -182,19 +183,19 @@ static inline unsigned MSB( T x ) { template<> inline unsigned MSB< unsigned int >( unsigned int x ) { static const unsigned long bits = sizeof( unsigned int ) * 8 - 1; - return bits - __builtin_clz( x ); + return bits - spot::clz( x ); } template<> inline unsigned MSB< unsigned long >( unsigned long x ) { static const unsigned bits = sizeof( unsigned long ) * 8 - 1; - return bits - __builtin_clzl( x ); + return bits - spot::clz( x ); } template<> inline unsigned MSB< unsigned long long >( unsigned long long x ) { static const unsigned bits = sizeof( unsigned long long ) * 8 - 1; - return bits - __builtin_clzll( x ); + return bits - spot::clz( x ); } // gets only Most Significant Bit diff --git a/spot/misc/Makefile.am b/spot/misc/Makefile.am index ab1085cfa..3fb3e70d8 100644 --- a/spot/misc/Makefile.am +++ b/spot/misc/Makefile.am @@ -36,6 +36,7 @@ misc_HEADERS = \ bitvect.hh \ casts.hh \ common.hh \ + clz.hh \ escape.hh \ fixpool.hh \ formater.hh \ @@ -63,6 +64,7 @@ libmisc_la_SOURCES = \ bareword.cc \ bitset.cc \ bitvect.cc \ + clz.cc \ escape.cc \ formater.cc \ game.cc \ diff --git a/spot/misc/bitset.hh b/spot/misc/bitset.hh index bb1693d2b..0ab26763a 100644 --- a/spot/misc/bitset.hh +++ b/spot/misc/bitset.hh @@ -22,6 +22,7 @@ #include #include #include +#include namespace spot { @@ -362,7 +363,7 @@ namespace spot continue; } #ifdef __GNUC__ - res += 8*sizeof(word_t) - __builtin_clz(v); + res += 8*sizeof(word_t) - clz(v); #else while (v) { diff --git a/spot/misc/clz.cc b/spot/misc/clz.cc new file mode 100644 index 000000000..6b2173501 --- /dev/null +++ b/spot/misc/clz.cc @@ -0,0 +1,115 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2018 Laboratoire de Recherche et Développement +// de l'Epita (LRDE). +// +// This file is part of Spot, a model checking library. +// +// Spot is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// Spot is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "config.h" +#include + +namespace spot +{ + // use gcc and clang built-in functions + // both compilers use the same function names, and define __GNUC__ +#if __GNUC__ + template + struct _clz; + + template<> + struct _clz + { + unsigned + operator()(unsigned n) const noexcept + { + return __builtin_clz(n); + } + }; + + template<> + struct _clz + { + unsigned long + operator()(unsigned long n) const noexcept + { + return __builtin_clzl(n); + } + }; + + template<> + struct _clz + { + unsigned long long + operator()(unsigned long long n) const noexcept + { + return __builtin_clzll(n); + } + }; + + size_t + clz(unsigned n) + { + return _clz()(n); + } + + size_t + clz(unsigned long n) + { + return _clz()(n); + } + + size_t + clz(unsigned long long n) + { + return _clz()(n); + } +#else + size_t + clz(unsigned n) + { + size_t res = CHAR_BIT*sizeof(size_t); + while (n) + { + --res; + n >>= 1; + } + return res; + } + + size_t + clz(unsigned long n) + { + size_t res = CHAR_BIT*sizeof(unsigned long); + while (n) + { + --res; + n >>= 1; + } + return res; + } + + size_t + clz(unsigned long long n) + { + size_t res = CHAR_BIT*sizeof(unsigned long long); + while (n) + { + --res; + n >>= 1; + } + return res; + } +#endif +} diff --git a/spot/misc/clz.hh b/spot/misc/clz.hh new file mode 100644 index 000000000..5b3d674c7 --- /dev/null +++ b/spot/misc/clz.hh @@ -0,0 +1,33 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2018 Laboratoire de Recherche et Développement +// de l'Epita (LRDE). +// +// This file is part of Spot, a model checking library. +// +// Spot is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// Spot is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include +#include +#include + +namespace spot +{ + SPOT_API size_t clz(unsigned n); + + SPOT_API size_t clz(unsigned long n); + + SPOT_API size_t clz(unsigned long long n); +} diff --git a/spot/misc/fixpool.hh b/spot/misc/fixpool.hh index 285e9e932..d07dfd14e 100644 --- a/spot/misc/fixpool.hh +++ b/spot/misc/fixpool.hh @@ -20,8 +20,7 @@ #pragma once #include -#include -#include +#include #if SPOT_DEBUG && defined(HAVE_VALGRIND_MEMCHECK_H) #include @@ -59,8 +58,7 @@ namespace spot return size; // small numbers are best aligned to the next power of 2 else if (size < alignof(std::max_align_t)) - return size_t{1} << (CHAR_BIT*sizeof(size_t) - - __builtin_clz(size)); + return size_t{1} << (CHAR_BIT*sizeof(size_t) - clz(size)); else { size_t mask = alignof(std::max_align_t)-1; -- GitLab