[llvm-dev] [FPEnv] undef and constrained intrinsics?

Sanjay Patel via llvm-dev llvm-dev at lists.llvm.org
Thu Jul 22 05:29:31 PDT 2021


Unfortunately, it's not as easy as "any undef in --> undef out". That's a
big reason for moving away from undef in IR.

If you read this page bottom-up (there must be a better link somewhere?)
and then read the follow-ups in the thread, you'll see how we arrived at
the current rules for the standard FP ops:
https://lists.llvm.org/pipermail/llvm-dev/2018-March/121481.html

On Thu, Jul 22, 2021 at 6:34 AM Serge Pavlov <sepavloff at gmail.com> wrote:

> The concept of undefined value has always been obscure and caused many
> questions. I'd like to share my opinion, however I am not sure if I
> understand this concept correctly.
>
> LLVM documentation (https://llvm.org/docs/LangRef.html#undefined-values)
> describes undefined values:
> "Undefined values are useful because they indicate to the compiler that
> the program is well defined no matter what value is used". So these are
> values on which the result of program execution does not depend. This is
> why an undefined value may be replaced by an arbitrary value of proper type
> and range. The choice of the replacement value is dictated mainly by
> convenience. If however the produced result depends on this choice, it
> means the value of `undef` affects results, so the initial supposition is
> broken and we have undefined behavior.
>
> I agree with Sanjay that constrained intrinsics should behave in the same
> way as regular FP operations with respect to `undef`. Control modes (like
> rounding mode) influence result value, but we know that particular value of
> `undef` is not important. FP exceptions are a bit more complex. If the
> value of `undef` may be arbitrary, it is not possible to guarantee that FP
> exceptions would be the same for all possible values. So we can assume that
> `undef` operands do not affect FP exceptions. Either such operation is
> eliminated, because its value is not used, or the operation itself does not
> use the `undef` argument.
>
> If any of standard IR FP operations has undef argument, the result may be
> either `undef` or any FP value. It is convenient to use NaN in such cases.
> It does not make the program more correct but it can help to detect
> undefined behavior in some FP environments. However `undef` result seems
> better choice than NaN, because in this case the user of `undef` value may
> choose a convenient representation for `undef`.
>
> I do not see any reason to distinguish between the cases "all operands are
> undefs" and "only one operand is undef". In both cases we get a value that
> is not used in the correct program.
>
> So I would propose transformations:
>
> %r = call float @llvm.experimental.constrained.fadd.f32(float undef, float
> undef, metadata !"round.dynamic", metadata !"fpexcept.strict")
>   -->
>   %r = undef
>
> And
>
> %r = call float @llvm.experimental.constrained.fadd.f32(float undef, float
> %x, metadata !"round.dynamic", metadata !"fpexcept.strict")
>   -->
>   %r = undef
>
> What do you think about it?
>
> Thanks,
> --Serge
>
>
> On Wed, Jul 21, 2021 at 8:15 PM Sanjay Patel <spatel at rotateright.com>
> wrote:
>
>> Can we use the regular FP instructions (fadd, fmul, etc.) as a model?
>>
>> If both operands to any of the binops are undef, then the result is
>> undef. So for the corresponding constrained intrinsic, if both operands are
>> undef, the result is undef and the exception state is also undef:
>>
>>   %r = call float @llvm.experimental.constrained.fadd.f32(float undef,
>> float undef, metadata !"round.dynamic", metadata !"fpexcept.strict")
>>   -->
>>   %r = undef
>>
>>   %r = call float @llvm.experimental.constrained.fadd.f32(float undef,
>> float undef, metadata !"round.dynamic", metadata !"fpexcept.maytrap")
>>   -->
>>   %r = undef
>>
>>
>> If one operand is undef and the other is regular value, assume that the
>> undef value takes on some encoding of SNaN:
>>
>>   %r = call float @llvm.experimental.constrained.fadd.f32(float undef,
>> float %x, metadata !"round.dynamic", metadata !"fpexcept.strict")
>>   -->
>>   %r = call float @llvm.experimental.constrained.fadd.f32(float SNaN,
>> float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") ; raise
>> invalid op exception
>>   (%r could be folded to QNaN here, but we can't get rid of the call, so
>> don't bother?)
>>
>>   %r = call float @llvm.experimental.constrained.fadd.f32(float undef,
>> float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap")
>>   -->
>>   %r = QNaN ; exception state does not have to be preserved
>>
>> Does that match the proposed behavior in https://reviews.llvm.org/D102673 (cc
>> @sepavloff)?
>>
>> We could go further (potentially reduce to poison) if we have
>> fast-math-flags on the calls -- just as we partially do with the regular
>> instructions -- but it probably doesn't matter much to real code.
>>
>>
>> On Fri, Jul 9, 2021 at 12:06 PM Kevin Neal via llvm-dev <
>> llvm-dev at lists.llvm.org> wrote:
>>
>>> How should the constrained FP intrinsics behave when called with an
>>> operand that is “undef” and the FP environment is _*not*_ the default
>>> environment? I’m specifically working in the middle end passes if it
>>> matters. Let me start with the assumption that the rounding mode is not
>>> relevant. That still leaves the exception handling as a factor:
>>>
>>> With “fpexcept.maytrap” we are allowed to drop instructions that could
>>> or would cause a trap at run-time. Does this imply we can fold the entire
>>> instruction to a new undef?
>>>
>>> With “fpexcept.strict” we are _*not*_ allowed to lose or reorder traps.
>>> So how does that affect undef? What happens in the backend? Perhaps the
>>> middle end should leave the instruction with the undef and let the backend
>>> do something reasonable?
>>>
>>> The “maytrap” case is the one I’m most interested in. An earlier version
>>> of D103169 would fold away undef constrained intrinsics in the maytrap
>>> case. This was removed so it could be handled without affecting the rest of
>>> the patch I believe.
>>>
>>> Opinions?
>>> --
>>> Kevin P. Neal
>>> SAS/C and SAS/C++ Compiler
>>> Compute Services
>>> SAS Institute, Inc.
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> LLVM Developers mailing list
>>> llvm-dev at lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210722/0480c994/attachment.html>


More information about the llvm-dev mailing list