[utils] Fix undefined behavior in Abs helper.

This fixes undefined behavior in the arithmetic negation operation by
switching to a branch-free implementation.

R=clemensh@chromium.org
TEST=unittests/MachineOperatorReducerTest.Int32DivWithConstant

Change-Id: I518f0e4343fc331607b8bbeefd2bb06285621fe6
Reviewed-on: https://chromium-review.googlesource.com/584870
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46905}
This commit is contained in:
Michael Starzinger 2017-07-26 15:09:42 +02:00 committed by Commit Bot
parent fdf28c7bea
commit a4663baa42

View File

@ -185,9 +185,15 @@ T JSMin(T x, T y) {
// Returns the absolute value of its argument.
template <typename T,
typename = typename std::enable_if<std::is_integral<T>::value>::type>
typename = typename std::enable_if<std::is_signed<T>::value>::type>
typename std::make_unsigned<T>::type Abs(T a) {
return a < 0 ? -a : a;
// This is a branch-free implementation of the absolute value function and is
// described in Warren's "Hacker's Delight", chapter 2. It avoids undefined
// behavior with the arithmetic negation operation on signed values as well.
typedef typename std::make_unsigned<T>::type unsignedT;
unsignedT x = static_cast<unsignedT>(a);
unsignedT y = static_cast<unsignedT>(a >> (sizeof(T) * 8 - 1));
return (x ^ y) - y;
}
// Floor(-0.0) == 0.0