https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127055

--- Comment #22 from Matthias Kretz (Vir) <mkretz at gcc dot gnu.org> ---
> for patch at #c8, please also remove !flag_trapping_mathb from vector 
> 27017:trunc<mode>2

That's already the case.

> 1) we need to fix the current vector expander with !flag_rounding_math 
> there's different rounding mode used in the existed implementation --- 
> roundps $3(ROUND_TRUNC) is used.

How is that wrong? Because it doesn't set if imm[3] = 1? That means it can just
emit more spurious FE_INEXACT, which we don't care about with
!flag_rounding_math anyway. But I agree we could be nicer here.

> The bit-manipulation solution seem correct and can drop !flag_rounding_math, 
> but not sure about performance(the existed solution takes only 4 uops with 
> -frounding-math).

The solution I posted in #c19 has higher latency than the existing solution.
Consequently, it should only be used with flag_rounding_math.
!flag_rounding_math already has a better solution.

The bit-manipulation solution is not ready yet (neither tested nor
benchmarked). In a std::simd implementation it looks like this (this is
inspired by the glibc implementation for round):
      using _Up = _UInt<sizeof(_Tp)>;
      using _Ip = __integer_from<sizeof(_Tp)>;
      using _Lf = numeric_limits<_Tp>;
      using _Vf = vec<_Tp, __width_of<_TV>>;
      using _Vu = rebind_t<_Up, _Vf>;
      using _Vi = rebind_t<_Ip, _Vf>;

      constexpr int __mant_width = _Lf::digits - 1;
      constexpr _Up __inf_bits = __builtin_bit_cast(_Up, _Lf::infinity());
      constexpr _Up __exp_mask = __inf_bits >> __mant_width;
      constexpr _Up __one_bits = __builtin_bit_cast(_Up, _Tp(1));
      constexpr _Ip __bias = __one_bits >> __mant_width;
      constexpr _Up __mant_mask = (1ull << __mant_width) - 1u;
      constexpr _Up __half_bit = 1ull << (__mant_width - 1);
      constexpr _Up __sign_bit = __builtin_bit_cast(_Up, _S_signmask<_TV>[0]);

      _Vu  __i0     = bit_cast<_Vu>(__x);
      _Vi  __j0     = _Vi((__i0 >> __mant_width) & __exp_mask) - __bias;
      _Vi  __jsatur = clamp(__j0, _Vi(), _Vi(_Ip(__mant_width - 1)));
      _Vu  __frac   = __mant_mask >> _Vu(__jsatur);
      _Vu  __half   = __half_bit >> _Vu(__jsatur);

      _Vu __normal = (__i0 + __half) & ~__frac;
      _Vu __small  = __i0 & __sign_bit;
      _Vu __one    = __small | __one_bits;

      auto __is_small = __j0 < _Ip(-1);    // |x| < 0.5 → ±0.0
      auto __is_one   = __j0 == _Ip(-1);   // 0.5 <= |x| < 1 → ±1.0

      _Vu __r = select(__is_one, __one,
                       select(__is_small, __small, __normal));
      return bit_cast<_TV>(__r);

Reply via email to