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

--- Comment #8 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
Thank you, Jakub! 

> The reason the testcase FAILs is the same as in the other PRs, it is trying 
> to convert {0x0.8p+33f, 0x0.8p+33f, 0x0.8p+33f, 0x0.8p+33f} V4SFmode vector 
> to V4SImode, and because the backend sees the constant operand of the fix, it 
> folds it to the unspecified value as with scalar conversion.

To be super-clear: the problem is the out-of-range value, not just any
V4SFmode->V4SImode, right?

Specifically, float32{INT32_MAX} -> int32_t should be fine, right?

I was trying to extract the following example (and likely failed):

It tries very hard not to pass anything outside float32{INT32_MAX} to
(a different) `PromoteTo()` at the end of the function from
https://github.com/google/highway/blob/2270e77d0d0ccc1d6bc7393f0ebb0b6352ddfd00/hwy/ops/x86_128-inl.h#L10275

 HWY_API VFromD<D> PromoteTo(D di64, VFromD<Rebind<float, D>> v) {
  const Rebind<int32_t, decltype(di64)> di32;
  const RebindToFloat<decltype(di32)> df32;
  const RebindToUnsigned<decltype(di32)> du32;
  const Repartition<uint8_t, decltype(du32)> du32_as_du8;

  const auto exponent_adj = BitCast(
      du32,
      Min(SaturatedSub(BitCast(du32_as_du8, ShiftRight<23>(BitCast(du32, v))),
                       BitCast(du32_as_du8, Set(du32, uint32_t{157}))),
          BitCast(du32_as_du8, Set(du32, uint32_t{32}))));
  const auto adj_v =
      BitCast(df32, BitCast(du32, v) - ShiftLeft<23>(exponent_adj));

  const auto f32_to_i32_result = ConvertTo(di32, adj_v);
  const auto lo64_or_mask = PromoteTo(
      di64,
      BitCast(du32, VecFromMask(di32, Eq(f32_to_i32_result,
                                         Set(di32, LimitsMax<int32_t>())))));

  return Or(PromoteTo(di64, BitCast(di32, f32_to_i32_result))
                << PromoteTo(di64, exponent_adj),
            lo64_or_mask);
 }

Specifically `const auto f32_to_i32_result = ConvertTo(di32, adj_v);` hits
overflow
and the masking below should account for that (I tried to preserve masking in
the original sample):

https://github.com/google/highway/blob/2270e77d0d0ccc1d6bc7393f0ebb0b6352ddfd00/hwy/ops/x86_128-inl.h#L10870

  template <class D, HWY_IF_I32_D(D)>
  HWY_API VFromD<D> ConvertTo(D di, VFromD<RebindToFloat<D>> v) {
    const RebindToFloat<decltype(di)> df;
    // See comment at the first occurrence of "IfThenElse(overflow,".
    const MFromD<D> overflow = RebindMask(di, Ge(v, Set(df, 2147483648.0f)));
    return IfThenElse(overflow, Set(di, LimitsMax<int32_t>()),
                      ConvertInRangeTo(di, v));
  }

Is it obvious from the minimized C code where I got it into overflow condition?
Or constant folding propagates through masks here?

I'll try to re-minimize it again.

Reply via email to