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

Sanjay Patel via llvm-dev llvm-dev at lists.llvm.org
Fri Jul 23 09:25:45 PDT 2021


On Fri, Jul 23, 2021 at 11:53 AM Kevin Neal <Kevin.Neal at sas.com> wrote:

> I notice that we’re not currently folding “fadd undef, undef” to “undef”.
> Shouldn’t we be? See simplifyFPOp() in InstructionSimplify.cpp.
>
>
If there's some path where the "fadd undef, undef -> undef" fold doesn't
happen, that seems like a bug.
InstSimplify should have called ConstantFolding on this before reaching
simplifyFPOp(), so we could assert in simplifyFPOp() that we have at least
one non-constant operand.


For ebStrict, and possibly other cases, I like the idea of replacing the
> undef with an SNaN, but we would need to do it late and it would need to be
> done even when optimizations are turned off. I’m not sure what to do if the
> nnan fast math flag is present, though. Ignore it? If an undef reaches a
> backend then it seems like we have an error?
>

It should always be safe to ignore/drop FMF, so yes, I'd ignore those while
we make sure the non-FMF functionality is working.




>
>
> *From:* Serge Pavlov <sepavloff at gmail.com>
> *Sent:* Friday, July 23, 2021 6:24 AM
> *To:* Sanjay Patel <spatel at rotateright.com>
> *Cc:* Kevin Neal <Kevin.Neal at sas.com>; LLVM Developers <
> llvm-dev at lists.llvm.org>
> *Subject:* Re: [llvm-dev] [FPEnv] undef and constrained intrinsics?
>
>
>
> *EXTERNAL*
>
> Thank you for the reference. I saw an even older discussion on this topic
> in the IRC channel. It looks like the problem of understanding `undef` has
> been persisting since long ago. Probably it is because `undef` is "one of
> the set" value, but the set itself is not specified. For floating point
> values it generally includes all possible values, but for example if
> `-fffast-math` is in action, NaNs are not in this set.
>
> Another source of problems is replacing `undef` with concrete value. It
> turns "one of the set" into one value and this contraction cannot be
> equally good for all cases. For example:
>
>   %A = select undef, %X, %Y
>   %B = select undef, %X, 42
>   %C = icmp eq %A, %B
>
> Contraction of `select` instructions to the first operands, as recommended
> in LLVM Language Reference Manual would make the compiler deduce that %C is
> true, which is not correct in general case.
>
> The concept of poison seems more clear and consistent. I wonder if we
> could make transformations like:
>
> %r = fadd undef, %x
> -->
> poison
>
> and similar for constrained intrinsics. Using `poison` is consistent with
> using `undef` for values on which the result does not depend. When poison
> needs representation in machine code, it could be lowered to NaN, which
> behaves similarly in runtime. The same solution is already made for
> shufflevector. Does anything prevents from such transformation?
>
>
> Thanks,
> --Serge
>
>
>
>
>
> On Thu, Jul 22, 2021 at 7:29 PM Sanjay Patel <spatel at rotateright.com>
> wrote:
>
> 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
> <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.llvm.org%2Fpipermail%2Fllvm-dev%2F2018-March%2F121481.html&data=04%7C01%7CKevin.Neal%40sas.com%7C110e7abe889f4c8e625008d94dc40d69%7Cb1c14d5c362545b3a4309552373a0c2f%7C0%7C0%7C637626326700770869%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=22jiHc6fXOp004yVMoW2HbeLKlnrsLryHEC%2FYrHBvcM%3D&reserved=0>
>
>
>
> 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
> <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fllvm.org%2Fdocs%2FLangRef.html%23undefined-values&data=04%7C01%7CKevin.Neal%40sas.com%7C110e7abe889f4c8e625008d94dc40d69%7Cb1c14d5c362545b3a4309552373a0c2f%7C0%7C0%7C637626326700770869%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=mLxyQV%2BnhbSSyR8nFiRvYUoPZF53UJ5x4a2s1UcyKV8%3D&reserved=0>)
> 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
> <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Freviews.llvm.org%2FD102673&data=04%7C01%7CKevin.Neal%40sas.com%7C110e7abe889f4c8e625008d94dc40d69%7Cb1c14d5c362545b3a4309552373a0c2f%7C0%7C0%7C637626326700780837%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=dF3SSPa3SBC2akrxGXT5lJTjstbotjikVXz132vW7GY%3D&reserved=0>
> (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
> <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-dev&data=04%7C01%7CKevin.Neal%40sas.com%7C110e7abe889f4c8e625008d94dc40d69%7Cb1c14d5c362545b3a4309552373a0c2f%7C0%7C0%7C637626326700780837%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=D%2B9ycwE8U3Cc4Jnh9%2FxyXWMIqrOy66YuyMGpyKjWpDQ%3D&reserved=0>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210723/a4eed9f8/attachment.html>


More information about the llvm-dev mailing list