Re: [hackers] [libgrapheme] Mark likely branches || Laslo Hunhold

2022-01-05 Thread Laslo Hunhold
On Wed, 5 Jan 2022 02:24:01 +0600
NRK  wrote:

Dear NRK,

> Answering my own question: because it fails if `__has_builtin` is not
> defined. I was expecting the 2nd expression wouldn't get evaluated at
> all. Should probably take some time and learn more about the
> pre-processor sometimes.

yes exactly. If you use normal non-function-like-macros that don't
exist, it works out, as they are simply replaced with 0 in such an
expression. At least GCC, from what I know of, always evaluates all
macros in each expression, and it seems to be undefined in the standard
if you do that beforehand.

It's different for function-like-macros: If they do not exist, it
throws an error instead of replacing it with 0, which can easily be
confirmed by trying to compile a file test.c containing

   #if defined (idontexist) && idontexist(test)
   #endif

yielding

   $ cc -o test test.c
   test.c:1:29: error: function-like macro 'idontexist' is not defined
   #if defined (idontexist) && idontexist(test)
   ^
   1 error generated.
   $

This is also probably a good reason to always use nested ifdefs instead
of ifs, as using if-constructs leads to such surprises given the
macro-logic-operators don't seem to behave like the ones in the
language itself. Using ifdef forces you to only evaluate one condition
per line.

With best regards

Laslo



Re: [hackers] [libgrapheme] Mark likely branches || Laslo Hunhold

2022-01-04 Thread Silvan Jegen
NRK  wrote:
> On Wed, Jan 05, 2022 at 01:56:26AM +0600, NRK wrote:
> > Just curious, why not use:
> > 
> > #if defined(__has_builtin) && __has_builtin(__builtin_expect)
> > #define likely(expr) __builtin_expect(!!(expr), 1)
> > #define unlikely(expr) __builtin_expect(!!(expr), 0)
> > #else
> > #define likely(expr) (expr)
> > #define unlikely(expr) (expr)
> > #endif
> 
> Answering my own question: because it fails if `__has_builtin` is not
> defined. I was expecting the 2nd expression wouldn't get evaluated at
> all. Should probably take some time and learn more about the
> pre-processor sometimes.

Same for me! I didn't know that the C pre-processor doesn't
short-circuit ...

Thanks for answering your own question! As you can see, it's
useful for others as well :)


Cheers,

Silvan



Re: [hackers] [libgrapheme] Mark likely branches || Laslo Hunhold

2022-01-04 Thread NRK
On Wed, Jan 05, 2022 at 01:56:26AM +0600, NRK wrote:
> Just curious, why not use:
> 
> #if defined(__has_builtin) && __has_builtin(__builtin_expect)
>   #define likely(expr) __builtin_expect(!!(expr), 1)
>   #define unlikely(expr) __builtin_expect(!!(expr), 0)
> #else
>   #define likely(expr) (expr)
>   #define unlikely(expr) (expr)
> #endif

Answering my own question: because it fails if `__has_builtin` is not
defined. I was expecting the 2nd expression wouldn't get evaluated at
all. Should probably take some time and learn more about the
pre-processor sometimes.

- NRK



Re: [hackers] [libgrapheme] Mark likely branches || Laslo Hunhold

2022-01-04 Thread NRK
> +#ifdef __has_builtin
> + #if __has_builtin(__builtin_expect)
> + #define likely(expr) __builtin_expect(!!(expr), 1)
> + #define unlikely(expr) __builtin_expect(!!(expr), 0)
> + #else
> + #define likely(expr) (expr)
> + #define unlikely(expr) (expr)
> + #endif
> +#else
> + #define likely(expr) (expr)
> + #define unlikely(expr) (expr)
> +#endif

Just curious, why not use:

#if defined(__has_builtin) && __has_builtin(__builtin_expect)
#define likely(expr) __builtin_expect(!!(expr), 1)
#define unlikely(expr) __builtin_expect(!!(expr), 0)
#else
#define likely(expr) (expr)
#define unlikely(expr) (expr)
#endif


- NRK



[hackers] [libgrapheme] Mark likely branches || Laslo Hunhold

2022-01-04 Thread git
commit e917e53a05de7cab2591d6b2fa3f2ce5ece89bcf
Author: Laslo Hunhold 
AuthorDate: Tue Jan 4 18:56:38 2022 +0100
Commit: Laslo Hunhold 
CommitDate: Tue Jan 4 18:56:38 2022 +0100

Mark likely branches

The likely() and unlikely() macros (known from the Linux kernel) in
src/util.h are defined in a portable way.

This addition brings a performance improvment of around 6%, which also
shows how well-optimized grapheme_is_character_break() already is. One
break check for two codepoints now takes only around 10µs on average on
my machine, which is insanely fast when you consider the complexity of
the algorithm behind it.

Signed-off-by: Laslo Hunhold 

diff --git a/src/character.c b/src/character.c
index 80a9a79..27e1cf0 100644
--- a/src/character.c
+++ b/src/character.c
@@ -105,10 +105,10 @@ static const uint_least16_t dont_break_gb12_13[2 * 
NUM_BREAK_PROPS] = {
 static enum break_property
 get_break_prop(uint_least32_t cp)
 {
-   if (cp > 0x10) {
-   return BREAK_PROP_OTHER;
-   } else {
+   if (likely(cp <= 0x10)) {
return prop[minor[major[cp >> 8] + (cp & 0xff)]].break_property;
+   } else {
+   return BREAK_PROP_OTHER;
}
 }
 
@@ -118,11 +118,11 @@ grapheme_is_character_break(uint_least32_t cp0, 
uint_least32_t cp1, GRAPHEME_STA
enum break_property cp0_prop, cp1_prop;
bool notbreak = false;
 
-   if (state) {
-   if (!state->prop_set) {
-   cp0_prop = get_break_prop(cp0);
-   } else {
+   if (likely(state)) {
+   if (likely(state->prop_set)) {
cp0_prop = state->prop;
+   } else {
+   cp0_prop = get_break_prop(cp0);
}
cp1_prop = get_break_prop(cp1);
 
@@ -153,7 +153,7 @@ grapheme_is_character_break(uint_least32_t cp0, 
uint_least32_t cp1, GRAPHEME_STA
UINT16_C(1 << cp1_prop));
 
/* update or reset flags (when we have a break) */
-   if (!notbreak) {
+   if (likely(!notbreak)) {
state->gb11_flag = state->gb12_13_flag = false;
}
} else {
diff --git a/src/util.h b/src/util.h
index 049af2f..b61a026 100644
--- a/src/util.h
+++ b/src/util.h
@@ -10,4 +10,19 @@
 
 #define LEN(x) (sizeof(x) / sizeof(*(x)))
 
+#undef likely
+#undef unlikely
+#ifdef __has_builtin
+   #if __has_builtin(__builtin_expect)
+   #define likely(expr) __builtin_expect(!!(expr), 1)
+   #define unlikely(expr) __builtin_expect(!!(expr), 0)
+   #else
+   #define likely(expr) (expr)
+   #define unlikely(expr) (expr)
+   #endif
+#else
+   #define likely(expr) (expr)
+   #define unlikely(expr) (expr)
+#endif
+
 #endif /* UTIL_H */