<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 5/5/22 11:17, Serge Pavlov wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CACOhrX6-1EzKTbZjUEN5wOErMhdUcJGUDmP9GGKDfmKtH5ywvQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div dir="ltr">OK, I reverted the change.</div>
      </div>
    </blockquote>
    Thank you.<br>
    <blockquote type="cite"
cite="mid:CACOhrX6-1EzKTbZjUEN5wOErMhdUcJGUDmP9GGKDfmKtH5ywvQ@mail.gmail.com">
      <div dir="ltr">
        <div dir="ltr"><br>
        </div>
        <div dir="ltr">
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">For the constant example,
            you're correct.  If SimplifyCall decided to use e.g. a
            weaker side effecting call, you still have the same problem.<br
              clear="all">
          </blockquote>
          <div><br>
          </div>
          <div>Could you please elaborate on this case? Side effect of a
            constrained intrinsic is only the interaction with floating
            point environment: dependence on control modes, including
            rounding direction, and change of floating point exception
            flags. What do you mean by "weaker side effecting call"?</div>
        </div>
      </div>
    </blockquote>
    <p>Ok, I think I talked myself into a corner here and need to back
      up a bit.  The "weaker side effecting call" point was wrong.  I
      was thinking about simplifyLibCall (which can replace one call
      with a new one), not SimplifyCall which is only allowed to replace
      a call with an existing IR Value.  <br>
    </p>
    <p>Given hat, let me stop and explicitly apologize.  I explained
      this badly and got myself confused in the process.  While I do
      think it's important to promptly revert changes with potential
      correctness bugs noted, I can understand your hesitation given my
      comments weren't making sense.  Sorry.</p>
    <p><br>
    </p>
    <p>I still think this patch needs some adjustment before relanding,
      but the reasoning is a bit different (and not correctness
      related).</p>
    <p>The structure given in the patch is not idiomatic.  The idiomatic
      piece would be:</p>
    <p>if (sa<ConstrainedFPIntrinsic>(CI)) {<br>
         if (Value *V = SimplifyCall(&CI,
      SQ.getWithInstruction(&CI))) {<br>
           return IC.replaceAllUsesOf(CI, V);<br>
        }<br>
      }</p>
    <p>The key piece here is that using the result of SimplifyX to
      remove X without doing a replacement is very non-idiomatic.  It
      causes readers - like say me - to go "why?".  Unless I'm, still,
      missing something, the idiomatic usage should cover your case
      right?<br>
    </p>
    <p><br>
    </p>
    <p>Thinking about this deeper though, I somewhat think you're
      solving this problem in the wrong place.  Independently of whether
      we can simplify the call, being able to figure out whether the
      semantics need to be "strict" would seem like an interesting
      transform on it's own.  Combined with this existing code from
      wouldInstructionBeTriviallyDead:<br>
    </p>
    <p>if (auto *FPI = dyn_cast<ConstrainedFPIntrinsic>(I)) {<br>
            Optional<fp::ExceptionBehavior> ExBehavior =
      FPI->getExceptionBehavior();<br>
            return ExBehavior.getValue() != fp::ebStrict;<br>
          }</p>
    <p>It seems like you'd end up with something strictly more powerful
      than this patch.<br>
    </p>
    <br>
    <blockquote type="cite"
cite="mid:CACOhrX6-1EzKTbZjUEN5wOErMhdUcJGUDmP9GGKDfmKtH5ywvQ@mail.gmail.com">
      <div dir="ltr">
        <div dir="ltr">
          <div>
            <div dir="ltr" class="gmail_signature"
              data-smartmail="gmail_signature">Thanks,<br>
              --Serge<br>
            </div>
          </div>
          <br>
        </div>
        <br>
        <div class="gmail_quote">
          <div dir="ltr" class="gmail_attr">On Fri, May 6, 2022 at 1:01
            AM Philip Reames <<a
              href="mailto:listmail@philipreames.com"
              moz-do-not-send="true" class="moz-txt-link-freetext">listmail@philipreames.com</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <div>
              <p>Serge,</p>
              <p>Please revert this change.  If you do not, I will. <br>
              </p>
              <div>On 5/5/22 10:25, Serge Pavlov wrote:<br>
              </div>
              <blockquote type="cite">
                <div dir="ltr">
                  <blockquote class="gmail_quote" style="margin:0px 0px
                    0px 0.8ex;border-left:1px solid
                    rgb(204,204,204);padding-left:1ex">
                    <p>This is the perfect illustration of my point. 
                      Consider what happens when %result is used. <br>
                    </p>
                    <p>SimplifyCall returns ConstantFloat(2.0) in your
                      example.  Dropping the call *without* doing
                      replaceAllUsesWith is a bug.  </p>
                  </blockquote>
                  <div>This path is executed for calls that have no
                    uses. In this case call to replaceAllUsesWith does
                    not make sense.</div>
                </div>
              </blockquote>
              <p>For the constant example, you're correct.  If
                SimplifyCall decided to use e.g. a weaker side effecting
                call, you still have the same problem.</p>
              <blockquote type="cite">
                <div dir="ltr">
                  <div><br>
                  </div>
                  <div>The resulting transformation in this case may be
                    considered as merging of two operations:</div>
                  <div>1. SimplifyCall returns ConstantFloat(2.0) and
                    the call is replaced by this expression.</div>
                  <div>2. As this ConstantFloat(2.0) is not used, it is
                    removed.</div>
                  <div>Both operations are valid and occur in
                    InstCombiner. Their combination must be valid also.
                    It is just what the discussed code does.</div>
                  <div> </div>
                  <div>
                    <div dir="ltr">Thanks,<br>
                      --Serge<br>
                    </div>
                  </div>
                  <br>
                </div>
                <br>
                <div class="gmail_quote">
                  <div dir="ltr" class="gmail_attr">On Thu, May 5, 2022
                    at 11:39 PM Philip Reames <<a
                      href="mailto:listmail@philipreames.com"
                      target="_blank" moz-do-not-send="true"
                      class="moz-txt-link-freetext">listmail@philipreames.com</a>>
                    wrote:<br>
                  </div>
                  <blockquote class="gmail_quote" style="margin:0px 0px
                    0px 0.8ex;border-left:1px solid
                    rgb(204,204,204);padding-left:1ex">
                    <div>
                      <p><br>
                      </p>
                      <div>On 5/5/22 09:32, Serge Pavlov wrote:<br>
                      </div>
                      <blockquote type="cite">
                        <div dir="ltr">
                          <blockquote class="gmail_quote"
                            style="margin:0px 0px 0px
                            0.8ex;border-left:1px solid
                            rgb(204,204,204);padding-left:1ex">My point
                            is that SimplifyCall is allowed to simplify
                            one side effecting call to another side
                            effecting call.<br clear="all">
                          </blockquote>
                          <div><br>
                          </div>
                          <div>It also may simplify side effecting call
                            to something that has no side effect, if the
                            side effect is actually absent. It takes
                            place for the code: </div>
                          <div><br>
                          </div>
                          <div>define float @f_unused_precise() #0 {<br>
                              %result = call float
                            @llvm.experimental.constrained.fadd.f32(float
                            1.0, float 1.0, metadata !"round.upward",
                            metadata !"fpexcept.strict") #0<br>
                              ret float 1.0<br>
                            }<br>
                          </div>
                          <div><br>
                          </div>
                          <div>In it experimental.constrained.fadd has
                            side effect, because exception behavior is
                            strict, but SimplifyCall can reveal that
                            actually side effect is absent and
                            simplifies the call to the constant 2.0. As
                            the result of the call is not used the net
                            result is removal of the call.</div>
                        </div>
                      </blockquote>
                      <p>This is the perfect illustration of my point. 
                        Consider what happens when %result is used.  <br>
                      </p>
                      <p>SimplifyCall returns ConstantFloat(2.0) in your
                        example.  Dropping the call *without* doing
                        replaceAllUsesWith is a bug.  </p>
                      <p>Please revert this change.  If you want, we can
                        continue discussing on the review afterwards,
                        but please revert this change now.  <br>
                      </p>
                      <blockquote type="cite">
                        <div dir="ltr">
                          <div><br>
                          </div>
                          <div>
                            <div dir="ltr">Thanks,<br>
                              --Serge<br>
                            </div>
                          </div>
                          <br>
                        </div>
                        <br>
                        <div class="gmail_quote">
                          <div dir="ltr" class="gmail_attr">On Thu, May
                            5, 2022 at 11:17 PM Philip Reames <<a
                              href="mailto:listmail@philipreames.com"
                              target="_blank" moz-do-not-send="true"
                              class="moz-txt-link-freetext">listmail@philipreames.com</a>>
                            wrote:<br>
                          </div>
                          <blockquote class="gmail_quote"
                            style="margin:0px 0px 0px
                            0.8ex;border-left:1px solid
                            rgb(204,204,204);padding-left:1ex">
                            <div>
                              <p><br>
                              </p>
                              <div>On 5/5/22 09:14, Serge Pavlov wrote:<br>
                              </div>
                              <blockquote type="cite">
                                <div dir="ltr">
                                  <div dir="ltr">
                                    <blockquote class="gmail_quote"
                                      style="margin:0px 0px 0px
                                      0.8ex;border-left:1px solid
                                      rgb(204,204,204);padding-left:1ex">This
                                      looks incorrect to me. 
                                      SimplifyCall returns a Value* for
                                      a<br>
                                      simplified expression and you're
                                      interpreting that as a boolean
                                      meaning<br>
                                      "delete call".<br>
                                    </blockquote>
                                    <div><br>
                                    </div>
                                    <div>In this case SimplifyCall is
                                      called for a call, which is not
                                      used and was not removed only
                                      because it has declared side
                                      effect. Non-null replacement
                                      returned by SimplifyCall is used
                                      as an indicator that the call may
                                      be simplified, so its side effect
                                      is absent or may be ignored. Such
                                      unused calls appear as a result of
                                      other transformations, they are
                                      not removed due to the side effect
                                      and produce useless instructions
                                      in resulting code. <br>
                                    </div>
                                  </div>
                                </div>
                              </blockquote>
                              <p>My point is that SimplifyCall is
                                allowed to simplify one side effecting
                                call to another side effecting call.  As
                                in, you can't make assumptions about
                                *which* simplifications SimplifyCall has
                                made.  If it returns a nonnull result,
                                you must use it (or leave the
                                instruction unmodified).  <br>
                              </p>
                              <blockquote type="cite">
                                <div dir="ltr">
                                  <div dir="ltr">
                                    <div><br>
                                    </div>
                                    <blockquote class="gmail_quote"
                                      style="margin:0px 0px 0px
                                      0.8ex;border-left:1px solid
                                      rgb(204,204,204);padding-left:1ex">I
                                      would expect this to be in
                                      isInstructionTriviallyDead
                                      anyways.<br>
                                    </blockquote>
                                    <div><br>
                                    </div>
                                    <div>It would be nice but the
                                      concern is that simplifying such
                                      calls is expensive and
                                      isInstructionTriviallyDead is
                                      called often enough, so negative
                                      impact on compile time is
                                      unavoidable. There are many
                                      transformations, not only constant
                                      folding and their number will
                                      increase, so putting all of them
                                      into isInstructionTriviallyDead
                                      does not look like a good design.</div>
                                    <div><br>
                                    </div>
                                    <div>Probably it is not a perfect
                                      solution, but it seems that we
                                      have no other solution at the
                                      moment. This problem was discussed
                                      in <a
                                        href="https://reviews.llvm.org/D118426"
                                        rel="noreferrer" target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">https://reviews.llvm.org/D118426</a> and
                                      in some previous patch reviews. If
                                      you have any ideas you could
                                      continue that discussion.</div>
                                    <div> </div>
                                    <div>
                                      <div dir="ltr">Thanks,<br>
                                        --Serge<br>
                                      </div>
                                    </div>
                                    <br>
                                  </div>
                                  <br>
                                  <div class="gmail_quote">
                                    <div dir="ltr" class="gmail_attr">On
                                      Thu, May 5, 2022 at 10:00 PM
                                      Philip Reames <<a
                                        href="mailto:listmail@philipreames.com"
                                        target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">listmail@philipreames.com</a>>
                                      wrote:<br>
                                    </div>
                                    <blockquote class="gmail_quote"
                                      style="margin:0px 0px 0px
                                      0.8ex;border-left:1px solid
                                      rgb(204,204,204);padding-left:1ex"><br>
                                      On 5/4/22 22:03, Serge Pavlov via
                                      llvm-commits wrote:<br>
                                      > Author: Serge Pavlov<br>
                                      > Date:
                                      2022-05-05T12:02:42+07:00<br>
                                      > New Revision:
                                      83914ee96fc2d828e1cfb8913f5d156d39150e2c<br>
                                      ><br>
                                      > URL: <a
href="https://github.com/llvm/llvm-project/commit/83914ee96fc2d828e1cfb8913f5d156d39150e2c"
                                        rel="noreferrer" target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">https://github.com/llvm/llvm-project/commit/83914ee96fc2d828e1cfb8913f5d156d39150e2c</a><br>
                                      > DIFF: <a
href="https://github.com/llvm/llvm-project/commit/83914ee96fc2d828e1cfb8913f5d156d39150e2c.diff"
                                        rel="noreferrer" target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">https://github.com/llvm/llvm-project/commit/83914ee96fc2d828e1cfb8913f5d156d39150e2c.diff</a><br>
                                      ><br>
                                      > LOG: [InstCombine] Remove
                                      side effect of replaced
                                      constrained intrinsics<br>
                                      ><br>
                                      > If a constrained intrinsic
                                      call was replaced by some value,
                                      it was not<br>
                                      > removed in some cases. The
                                      dangling instruction resulted in
                                      useless<br>
                                      > instructions executed in
                                      runtime. It happened because
                                      constrained<br>
                                      > intrinsics usually have side
                                      effect, it is used to model the
                                      interaction<br>
                                      > with floating-point
                                      environment. In some cases it is
                                      correct behavior<br>
                                      > but often the side effect is
                                      actually absent or can be ignored.<br>
                                      ><br>
                                      > This change adds specific
                                      treatment of constrained
                                      intrinsics so that<br>
                                      > their side effect can be
                                      removed if it actually absents.<br>
                                      ><br>
                                      > Differential Revision: <a
                                        href="https://reviews.llvm.org/D118426"
                                        rel="noreferrer" target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">https://reviews.llvm.org/D118426</a><br>
                                      ><br>
                                      > Added:<br>
                                      >     
                                      llvm/test/Transforms/InstCombine/constrained.ll<br>
                                      ><br>
                                      > Modified:<br>
                                      >     
                                      llvm/include/llvm/Analysis/InstructionSimplify.h<br>
                                      >     
                                      llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp<br>
                                      ><br>
                                      > Removed:<br>
                                      >      <br>
                                      ><br>
                                      ><br>
                                      >
################################################################################<br>
                                      > diff  --git
                                      a/llvm/include/llvm/Analysis/InstructionSimplify.h
b/llvm/include/llvm/Analysis/InstructionSimplify.h<br>
                                      > index
                                      8f6ed3a6a1928..612a73551f720
                                      100644<br>
                                      > ---
                                      a/llvm/include/llvm/Analysis/InstructionSimplify.h<br>
                                      > +++
                                      b/llvm/include/llvm/Analysis/InstructionSimplify.h<br>
                                      > @@ -299,6 +299,10 @@ Value
                                      *SimplifyBinOp(unsigned Opcode,
                                      Value *LHS, Value *RHS,
                                      FastMathFlags FMF,<br>
                                      >                        const
                                      SimplifyQuery &Q);<br>
                                      >   <br>
                                      >   /// Given a callsite, fold
                                      the result or return null.<br>
                                      > +///<br>
                                      > +/// \note A call with
                                      declared side effect may be
                                      simplified into a value<br>
                                      > +/// without such. It happens
                                      if simplification code deduces
                                      that side effect<br>
                                      > +/// is actually absent.<br>
                                      >   Value
                                      *SimplifyCall(CallBase *Call,
                                      const SimplifyQuery &Q);<br>
                                      >   <br>
                                      >   /// Given an operand for a
                                      Freeze, see if we can fold the
                                      result.<br>
                                      ><br>
                                      > diff  --git
                                      a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp<br>
                                      > index
                                      c96919caee2b1..6b2ab24b4b746
                                      100644<br>
                                      > ---
                                      a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp<br>
                                      > +++
                                      b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp<br>
                                      > @@ -1237,6 +1237,16 @@
                                      Instruction
                                      *InstCombinerImpl::visitCallInst(CallInst
                                      &CI) {<br>
                                      >         return NewCall;<br>
                                      >     }<br>
                                      >   <br>
                                      > +  // Unused constrained FP
                                      intrinsic calls may have declared
                                      side effect, which<br>
                                      > +  // actually absent. If
                                      SimplifyCall returns a replacement
                                      for such call,<br>
                                      > +  // assume side effect is
                                      absent and the call may be
                                      removed.<br>
                                      > +  if (CI.use_empty()
                                      &&
                                      isa<ConstrainedFPIntrinsic>(CI))
                                      {<br>
                                      > +    if
                                      (SimplifyCall(&CI,
                                      SQ.getWithInstruction(&CI))) {<br>
                                      > +     
                                      eraseInstFromFunction(CI);<br>
                                      > +      return nullptr;<br>
                                      > +    }<br>
                                      > +  }<br>
                                      > +<br>
                                      <br>
                                      This looks incorrect to me. 
                                      SimplifyCall returns a Value* for
                                      a <br>
                                      simplified expression and you're
                                      interpreting that as a boolean
                                      meaning <br>
                                      "delete call".<br>
                                      <br>
                                      I would expect this to be in
                                      isInstructionTriviallyDead
                                      anyways.<br>
                                      <br>
                                      Please revert unless I'm
                                      misreading.<br>
                                      <br>
                                      >     Intrinsic::ID IID =
                                      II->getIntrinsicID();<br>
                                      >     switch (IID) {<br>
                                      >     case
                                      Intrinsic::objectsize:<br>
                                      ><br>
                                      > diff  --git
                                      a/llvm/test/Transforms/InstCombine/constrained.ll
b/llvm/test/Transforms/InstCombine/constrained.ll<br>
                                      > new file mode 100644<br>
                                      > index
                                      0000000000000..b5ef71e6edfba<br>
                                      > --- /dev/null<br>
                                      > +++
                                      b/llvm/test/Transforms/InstCombine/constrained.ll<br>
                                      > @@ -0,0 +1,125 @@<br>
                                      > +; NOTE: Assertions have been
                                      autogenerated by
                                      utils/update_test_checks.py<br>
                                      > +; RUN: opt -S -instcombine
                                      %s | FileCheck %s<br>
                                      > +<br>
                                      > +; Treatment of operation
                                      with unused result.<br>
                                      > +<br>
                                      > +; If operation does not
                                      raise exceptions, it may be
                                      removed even in strict mode.<br>
                                      > +define float
                                      @f_unused_precise() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_unused_precise(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      1.000000e+00<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fadd.f32(float
                                      1.0, float 1.0, metadata
                                      !"round.upward", metadata
                                      !"fpexcept.strict") #0<br>
                                      > +  ret float 1.0<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If operation raises
                                      exceptions, it cannot be removed
                                      in strict mode.<br>
                                      > +define float
                                      @f_unused_strict() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_unused_strict(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:   
                                      [[RESULT:%.*]] = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.000000e+00, float 3.000000e+00,
                                      metadata !"round.tonearest",
                                      metadata !"fpexcept.strict")
                                      #[[ATTR0:[0-9]+]]<br>
                                      > +; CHECK-NEXT:    ret float
                                      1.000000e+00<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.tonearest", metadata
                                      !"fpexcept.strict") #0<br>
                                      > +  ret float 1.0<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If operation raises
                                      exceptions, it can be removed in
                                      non-strict mode.<br>
                                      > +define float
                                      @f_unused_ignore() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_unused_ignore(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      1.000000e+00<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.towardzero", metadata
                                      !"fpexcept.ignore") #0<br>
                                      > +  ret float 1.0<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If operation raises
                                      exceptions, it can be removed in
                                      non-strict mode even if rounding
                                      mode is dynamic.<br>
                                      > +define float
                                      @f_unused_dynamic_ignore() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_unused_dynamic_ignore(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      1.000000e+00<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.dynamic", metadata
                                      !"fpexcept.ignore") #0<br>
                                      > +  ret float 1.0<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If operation raises
                                      exceptions, it can be removed in
                                      "maytrap" mode.<br>
                                      > +define float
                                      @f_unused_maytrap() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_unused_maytrap(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      1.000000e+00<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.tonearest", metadata
                                      !"fpexcept.maytrap") #0<br>
                                      > +  ret float 1.0<br>
                                      > +}<br>
                                      > +<br>
                                      > +; Constant evaluation.<br>
                                      > +<br>
                                      > +; If operation does not
                                      raise exceptions, it may be folded
                                      even in strict mode.<br>
                                      > +define float
                                      @f_eval_precise() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_eval_precise(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      2.000000e+00<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fadd.f32(float
                                      1.0, float 1.0, metadata
                                      !"round.upward", metadata
                                      !"fpexcept.strict") #0<br>
                                      > +  ret float %result<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If operation raises
                                      exceptions, it cannot be folded in
                                      strict mode.<br>
                                      > +define float
                                      @f_eval_strict() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_eval_strict(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:   
                                      [[RESULT:%.*]] = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.000000e+00, float 3.000000e+00,
                                      metadata !"round.upward", metadata
                                      !"fpexcept.strict") #[[ATTR0]]<br>
                                      > +; CHECK-NEXT:    ret float
                                      [[RESULT]]<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.upward", metadata
                                      !"fpexcept.strict") #0<br>
                                      > +  ret float %result<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If operation raises
                                      exceptions, it can be folded in
                                      non-strict mode.<br>
                                      > +define float
                                      @f_eval_ignore() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_eval_ignore(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      0x3FD5555540000000<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.downward", metadata
                                      !"fpexcept.ignore") #0<br>
                                      > +  ret float %result<br>
                                      > +}<br>
                                      > +<br>
                                      > +; if result is imprecise, it
                                      cannot be folded if rounding mode
                                      is dynamic.<br>
                                      > +define float
                                      @f_eval_dynamic_ignore() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_eval_dynamic_ignore(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:   
                                      [[RESULT:%.*]] = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.000000e+00, float 3.000000e+00,
                                      metadata !"round.dynamic",
                                      metadata !"fpexcept.ignore")
                                      #[[ATTR0]]<br>
                                      > +; CHECK-NEXT:    ret float
                                      [[RESULT]]<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.dynamic", metadata
                                      !"fpexcept.ignore") #0<br>
                                      > +  ret float %result<br>
                                      > +}<br>
                                      > +<br>
                                      > +; If result is imprecise and
                                      rounding mode is not dynamic,
                                      operation can be folded in
                                      "maytrap" mode.<br>
                                      > +define float
                                      @f_eval_maytrap() #0 {<br>
                                      > +; CHECK-LABEL:
                                      @f_eval_maytrap(<br>
                                      > +; CHECK-NEXT:  entry:<br>
                                      > +; CHECK-NEXT:    ret float
                                      0x3FD5555560000000<br>
                                      > +;<br>
                                      > +entry:<br>
                                      > +  %result = call float
                                      @llvm.experimental.constrained.fdiv.f32(float
                                      1.0, float 3.0, metadata
                                      !"round.tonearest", metadata
                                      !"fpexcept.maytrap") #0<br>
                                      > +  ret float %result<br>
                                      > +}<br>
                                      > +<br>
                                      > +<br>
                                      > +declare float
                                      @llvm.experimental.constrained.fadd.f32(float,
                                      float, metadata, metadata)<br>
                                      > +declare float
                                      @llvm.experimental.constrained.fdiv.f32(float,
                                      float, metadata, metadata)<br>
                                      > +<br>
                                      > +attributes #0 = { strictfp }<br>
                                      ><br>
                                      ><br>
                                      >          <br>
                                      >
                                      _______________________________________________<br>
                                      > llvm-commits mailing list<br>
                                      > <a
                                        href="mailto:llvm-commits@lists.llvm.org"
                                        target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">llvm-commits@lists.llvm.org</a><br>
                                      > <a
                                        href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits"
                                        rel="noreferrer" target="_blank"
                                        moz-do-not-send="true"
                                        class="moz-txt-link-freetext">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
                                    </blockquote>
                                  </div>
                                </div>
                              </blockquote>
                            </div>
                          </blockquote>
                        </div>
                      </blockquote>
                    </div>
                  </blockquote>
                </div>
              </blockquote>
            </div>
          </blockquote>
        </div>
      </div>
    </blockquote>
  </body>
</html>