Modified: trunk/Source/WTF/ChangeLog (177728 => 177729)
--- trunk/Source/WTF/ChangeLog 2014-12-25 02:31:36 UTC (rev 177728)
+++ trunk/Source/WTF/ChangeLog 2014-12-25 02:46:32 UTC (rev 177729)
@@ -1,3 +1,19 @@
+2014-12-24 Benjamin Poulain <[email protected]>
+
+ Simplify saturated integer add/sub
+ https://bugs.webkit.org/show_bug.cgi?id=139854
+
+ Reviewed by Darin Adler.
+
+ * wtf/Compiler.h:
+ Make a wrapper for __has_builtin for compilers that do not support it.
+
+ * wtf/SaturatedArithmetic.h:
+ (saturatedAddition):
+ (saturatedSubtraction):
+ Use the builtins when possible instead of reinventing the wheel.
+ On ARMv7, use the saturated math instructions.
+
2014-12-23 Anders Carlsson <[email protected]>
Move dynamic_objc_cast to RetainPtr.h
Modified: trunk/Source/WTF/wtf/Compiler.h (177728 => 177729)
--- trunk/Source/WTF/wtf/Compiler.h 2014-12-25 02:31:36 UTC (rev 177728)
+++ trunk/Source/WTF/wtf/Compiler.h 2014-12-25 02:46:32 UTC (rev 177729)
@@ -35,6 +35,13 @@
/* COMPILER_QUIRK() - whether the compiler being used to build the project requires a given quirk. */
#define COMPILER_QUIRK(WTF_COMPILER_QUIRK) (defined WTF_COMPILER_QUIRK_##WTF_COMPILER_QUIRK && WTF_COMPILER_QUIRK_##WTF_COMPILER_QUIRK)
+/* COMPILER_HAS_CLANG_BUILTIN() - wether the compiler supports a particular clang builtin. */
+#ifdef __has_builtin
+#define COMPILER_HAS_CLANG_BUILTIN(x) __has_builtin(x)
+#else
+#define COMPILER_HAS_CLANG_BUILTIN(x) 0
+#endif
+
/* ==== COMPILER() - primary detection of the compiler being used to build the project, in alphabetical order ==== */
/* COMPILER(CLANG) - Clang */
Modified: trunk/Source/WTF/wtf/SaturatedArithmetic.h (177728 => 177729)
--- trunk/Source/WTF/wtf/SaturatedArithmetic.h 2014-12-25 02:31:36 UTC (rev 177728)
+++ trunk/Source/WTF/wtf/SaturatedArithmetic.h 2014-12-25 02:46:32 UTC (rev 177729)
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012, Google Inc. All rights reserved.
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -31,35 +32,72 @@
#ifndef SaturatedArithmetic_h
#define SaturatedArithmetic_h
+#include "Compiler.h"
#include <limits>
#include <stdint.h>
#include <stdlib.h>
-inline int32_t saturatedAddition(int32_t a, int32_t b)
+inline bool signedAddOverflows(int32_t a, int32_t b, int32_t& result)
{
+#if COMPILER_HAS_CLANG_BUILTIN(__builtin_sadd_overflow)
+ return __builtin_sadd_overflow(a, b, &result);
+#else
uint32_t ua = a;
uint32_t ub = b;
- uint32_t result = ua + ub;
+ uint32_t uresult = ua + ub;
+ result = static_cast<int32_t>(uresult);
// Can only overflow if the signed bit of the two values match. If the signed
// bit of the result and one of the values differ it did overflow.
- if (!((ua ^ ub) >> 31) & (result ^ ua) >> 31)
- result = std::numeric_limits<int>::max() + (ua >> 31);
+ return !((ua ^ ub) >> 31) & (uresult ^ ua) >> 31;
+#endif
+}
+inline int32_t saturatedAddition(int32_t a, int32_t b)
+{
+ int32_t result;
+#if CPU(ARM_THUMB2)
+ asm("qadd %[sum], %[addend], %[augend]"
+ : [sum]"=r"(result)
+ : [augend]"r"(a), [addend]"r"(b)
+ : /* Nothing is clobbered. */
+ );
+#else
+ if (signedAddOverflows(a, b, result))
+ result = std::numeric_limits<int32_t>::max() + (static_cast<uint32_t>(a) >> 31);
+#endif
return result;
}
-inline int32_t saturatedSubtraction(int32_t a, int32_t b)
+inline bool signedSubtractOverflows(int32_t a, int32_t b, int32_t& result)
{
+#if COMPILER_HAS_CLANG_BUILTIN(__builtin_ssub_overflow)
+ return __builtin_ssub_overflow(a, b, &result);
+#else
uint32_t ua = a;
uint32_t ub = b;
- uint32_t result = ua - ub;
+ uint32_t uresult = ua - ub;
+ result = static_cast<int32_t>(uresult);
// Can only overflow if the signed bit of the two values do not match. If the
// signed bit of the result and the first value differ it did overflow.
- if ((ua ^ ub) >> 31 & (result ^ ua) >> 31)
- result = std::numeric_limits<int>::max() + (ua >> 31);
+ return (ua ^ ub) >> 31 & (uresult ^ ua) >> 31;
+#endif
+}
+inline int32_t saturatedSubtraction(int32_t a, int32_t b)
+{
+ int32_t result;
+#if CPU(ARM_THUMB2)
+ asm("qsub %[difference], %[minuend], %[subtrahend]"
+ : [difference]"=r"(result)
+ : [minuend]"r"(a), [subtrahend]"r"(b)
+ : /* Nothing is clobbered. */
+ );
+#else
+ if (signedSubtractOverflows(a, b, result))
+ result = std::numeric_limits<uint32_t>::max() + (static_cast<uint32_t>(a) >> 31);
+#endif
return result;
}