[llvm] 5290048 - [FPEnv][InstSimplify] Constrained FP support for NaN

Kevin P. Neal via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 9 08:27:12 PDT 2021


Author: Kevin P. Neal
Date: 2021-07-09T11:26:28-04:00
New Revision: 52900486a1b5d270687b7268dc8dd90061889066

URL: https://github.com/llvm/llvm-project/commit/52900486a1b5d270687b7268dc8dd90061889066
DIFF: https://github.com/llvm/llvm-project/commit/52900486a1b5d270687b7268dc8dd90061889066.diff

LOG: [FPEnv][InstSimplify] Constrained FP support for NaN

Currently InstructionSimplify.cpp knows how to simplify floating point
instructions that have a NaN operand. It does not know how to handle the
matching constrained FP intrinsic.

This patch teaches it how to simplify so long as the exception handling
is not "fpexcept.strict".

Differential Revision: https://reviews.llvm.org/D103169

Added: 
    llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll
    llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll
    llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll

Modified: 
    llvm/include/llvm/Analysis/InstructionSimplify.h
    llvm/include/llvm/IR/FPEnv.h
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/lib/Transforms/Utils/Local.cpp
    llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll
    llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h
index 75ce4e38df166..3a3b02601a500 100644
--- a/llvm/include/llvm/Analysis/InstructionSimplify.h
+++ b/llvm/include/llvm/Analysis/InstructionSimplify.h
@@ -157,23 +157,34 @@ Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
                        const SimplifyQuery &Q);
 
 /// Given operands for an FAdd, fold the result or return null.
-Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
-                        const SimplifyQuery &Q);
+Value *
+SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+                 const SimplifyQuery &Q,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven);
 
 /// Given operands for an FSub, fold the result or return null.
-Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
-                        const SimplifyQuery &Q);
+Value *
+SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+                 const SimplifyQuery &Q,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven);
 
 /// Given operands for an FMul, fold the result or return null.
-Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
-                        const SimplifyQuery &Q);
+Value *
+SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+                 const SimplifyQuery &Q,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven);
 
 /// Given operands for the multiplication of a FMA, fold the result or return
 /// null. In contrast to SimplifyFMulInst, this function will not perform
 /// simplifications whose unrounded results 
diff er when rounded to the argument
 /// type.
 Value *SimplifyFMAFMul(Value *LHS, Value *RHS, FastMathFlags FMF,
-                       const SimplifyQuery &Q);
+                       const SimplifyQuery &Q,
+                       fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                       RoundingMode Rounding = RoundingMode::NearestTiesToEven);
 
 /// Given operands for a Mul, fold the result or return null.
 Value *SimplifyMulInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
@@ -185,8 +196,11 @@ Value *SimplifySDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
 Value *SimplifyUDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
 
 /// Given operands for an FDiv, fold the result or return null.
-Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
-                        const SimplifyQuery &Q);
+Value *
+SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+                 const SimplifyQuery &Q,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven);
 
 /// Given operands for an SRem, fold the result or return null.
 Value *SimplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
@@ -195,8 +209,11 @@ Value *SimplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
 Value *SimplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
 
 /// Given operands for an FRem, fold the result or return null.
-Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
-                        const SimplifyQuery &Q);
+Value *
+SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+                 const SimplifyQuery &Q,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven);
 
 /// Given operands for a Shl, fold the result or return null.
 Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,

diff  --git a/llvm/include/llvm/IR/FPEnv.h b/llvm/include/llvm/IR/FPEnv.h
index 2a765a2d700b7..621540000b5cf 100644
--- a/llvm/include/llvm/IR/FPEnv.h
+++ b/llvm/include/llvm/IR/FPEnv.h
@@ -52,5 +52,11 @@ Optional<fp::ExceptionBehavior> StrToExceptionBehavior(StringRef);
 /// For any ExceptionBehavior enumerator, returns a string valid as
 /// input in constrained intrinsic exception behavior metadata.
 Optional<StringRef> ExceptionBehaviorToStr(fp::ExceptionBehavior);
+
+/// Returns true if the exception handling behavior and rounding mode
+/// match what is used in the default floating point environment.
+inline bool isDefaultFPEnvironment(fp::ExceptionBehavior EB, RoundingMode RM) {
+  return EB == fp::ebIgnore && RM == RoundingMode::NearestTiesToEven;
+}
 }
 #endif

diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index bd22dafa68a4d..4a310a349177f 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4856,7 +4856,9 @@ static Constant *propagateNaN(Constant *In) {
 /// transforms based on poison/undef/NaN because the operation itself makes no
 /// 
diff erence to the result.
 static Constant *simplifyFPOp(ArrayRef<Value *> Ops, FastMathFlags FMF,
-                              const SimplifyQuery &Q) {
+                              const SimplifyQuery &Q,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
   // Poison is independent of anything else. It always propagates from an
   // operand to a math result.
   if (any_of(Ops, [](Value *V) { return match(V, m_Poison()); }))
@@ -4875,22 +4877,34 @@ static Constant *simplifyFPOp(ArrayRef<Value *> Ops, FastMathFlags FMF,
     if (FMF.noInfs() && (IsInf || IsUndef))
       return PoisonValue::get(V->getType());
 
-    if (IsUndef || IsNan)
-      return propagateNaN(cast<Constant>(V));
+    if (isDefaultFPEnvironment(ExBehavior, Rounding)) {
+      if (IsUndef || IsNan)
+        return propagateNaN(cast<Constant>(V));
+    } else if (ExBehavior != fp::ebStrict) {
+      if (IsNan)
+        return propagateNaN(cast<Constant>(V));
+    }
   }
   return nullptr;
 }
 
 /// Given operands for an FAdd, see if we can fold the result.  If not, this
 /// returns null.
-static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                               const SimplifyQuery &Q, unsigned MaxRecurse) {
-  if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q))
-    return C;
+static Value *
+SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
+                 const SimplifyQuery &Q, unsigned MaxRecurse,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {
+  if (isDefaultFPEnvironment(ExBehavior, Rounding))
+    if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q))
+      return C;
 
-  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q))
+  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
     return C;
 
+  if (!isDefaultFPEnvironment(ExBehavior, Rounding))
+    return nullptr;
+
   // fadd X, -0 ==> X
   if (match(Op1, m_NegZeroFP()))
     return Op0;
@@ -4930,14 +4944,21 @@ static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
 
 /// Given operands for an FSub, see if we can fold the result.  If not, this
 /// returns null.
-static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                               const SimplifyQuery &Q, unsigned MaxRecurse) {
-  if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q))
-    return C;
+static Value *
+SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
+                 const SimplifyQuery &Q, unsigned MaxRecurse,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {
+  if (isDefaultFPEnvironment(ExBehavior, Rounding))
+    if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q))
+      return C;
 
-  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q))
+  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
     return C;
 
+  if (!isDefaultFPEnvironment(ExBehavior, Rounding))
+    return nullptr;
+
   // fsub X, +0 ==> X
   if (match(Op1, m_PosZeroFP()))
     return Op0;
@@ -4976,10 +4997,15 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
 }
 
 static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
-                              const SimplifyQuery &Q, unsigned MaxRecurse) {
-  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q))
+                              const SimplifyQuery &Q, unsigned MaxRecurse,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
+  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
     return C;
 
+  if (!isDefaultFPEnvironment(ExBehavior, Rounding))
+    return nullptr;
+
   // fmul X, 1.0 ==> X
   if (match(Op1, m_FPOne()))
     return Op0;
@@ -5009,43 +5035,65 @@ static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
 }
 
 /// Given the operands for an FMul, see if we can fold the result
-static Value *SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                               const SimplifyQuery &Q, unsigned MaxRecurse) {
-  if (Constant *C = foldOrCommuteConstant(Instruction::FMul, Op0, Op1, Q))
-    return C;
+static Value *
+SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF,
+                 const SimplifyQuery &Q, unsigned MaxRecurse,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {
+  if (isDefaultFPEnvironment(ExBehavior, Rounding))
+    if (Constant *C = foldOrCommuteConstant(Instruction::FMul, Op0, Op1, Q))
+      return C;
 
   // Now apply simplifications that do not require rounding.
-  return SimplifyFMAFMul(Op0, Op1, FMF, Q, MaxRecurse);
+  return SimplifyFMAFMul(Op0, Op1, FMF, Q, MaxRecurse, ExBehavior, Rounding);
 }
 
 Value *llvm::SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                              const SimplifyQuery &Q) {
-  return ::SimplifyFAddInst(Op0, Op1, FMF, Q, RecursionLimit);
+                              const SimplifyQuery &Q,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
+  return ::SimplifyFAddInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior,
+                            Rounding);
 }
 
-
 Value *llvm::SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                              const SimplifyQuery &Q) {
-  return ::SimplifyFSubInst(Op0, Op1, FMF, Q, RecursionLimit);
+                              const SimplifyQuery &Q,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
+  return ::SimplifyFSubInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior,
+                            Rounding);
 }
 
 Value *llvm::SimplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                              const SimplifyQuery &Q) {
-  return ::SimplifyFMulInst(Op0, Op1, FMF, Q, RecursionLimit);
+                              const SimplifyQuery &Q,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
+  return ::SimplifyFMulInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior,
+                            Rounding);
 }
 
 Value *llvm::SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
-                             const SimplifyQuery &Q) {
-  return ::SimplifyFMAFMul(Op0, Op1, FMF, Q, RecursionLimit);
-}
+                             const SimplifyQuery &Q,
+                             fp::ExceptionBehavior ExBehavior,
+                             RoundingMode Rounding) {
+  return ::SimplifyFMAFMul(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior,
+                           Rounding);
+}
+
+static Value *
+SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
+                 const SimplifyQuery &Q, unsigned,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {
+  if (isDefaultFPEnvironment(ExBehavior, Rounding))
+    if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q))
+      return C;
 
-static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                               const SimplifyQuery &Q, unsigned) {
-  if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q))
+  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
     return C;
 
-  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q))
-    return C;
+  if (!isDefaultFPEnvironment(ExBehavior, Rounding))
+    return nullptr;
 
   // X / 1.0 -> X
   if (match(Op1, m_FPOne()))
@@ -5080,17 +5128,27 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
 }
 
 Value *llvm::SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                              const SimplifyQuery &Q) {
-  return ::SimplifyFDivInst(Op0, Op1, FMF, Q, RecursionLimit);
-}
+                              const SimplifyQuery &Q,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
+  return ::SimplifyFDivInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior,
+                            Rounding);
+}
+
+static Value *
+SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
+                 const SimplifyQuery &Q, unsigned,
+                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
+                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {
+  if (isDefaultFPEnvironment(ExBehavior, Rounding))
+    if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q))
+      return C;
 
-static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                               const SimplifyQuery &Q, unsigned) {
-  if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q))
+  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q, ExBehavior, Rounding))
     return C;
 
-  if (Constant *C = simplifyFPOp({Op0, Op1}, FMF, Q))
-    return C;
+  if (!isDefaultFPEnvironment(ExBehavior, Rounding))
+    return nullptr;
 
   // Unlike fdiv, the result of frem always matches the sign of the dividend.
   // The constant match may include undef elements in a vector, so return a full
@@ -5108,8 +5166,11 @@ static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
 }
 
 Value *llvm::SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
-                              const SimplifyQuery &Q) {
-  return ::SimplifyFRemInst(Op0, Op1, FMF, Q, RecursionLimit);
+                              const SimplifyQuery &Q,
+                              fp::ExceptionBehavior ExBehavior,
+                              RoundingMode Rounding) {
+  return ::SimplifyFRemInst(Op0, Op1, FMF, Q, RecursionLimit, ExBehavior,
+                            Rounding);
 }
 
 //=== Helper functions for higher up the class hierarchy.
@@ -5755,12 +5816,24 @@ static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) {
     }
     return nullptr;
   }
+  case Intrinsic::experimental_constrained_fma: {
+    Value *Op0 = Call->getArgOperand(0);
+    Value *Op1 = Call->getArgOperand(1);
+    Value *Op2 = Call->getArgOperand(2);
+    auto *FPI = cast<ConstrainedFPIntrinsic>(Call);
+    if (Value *V = simplifyFPOp({Op0, Op1, Op2}, {}, Q,
+                                FPI->getExceptionBehavior().getValue(),
+                                FPI->getRoundingMode().getValue()))
+      return V;
+    return nullptr;
+  }
   case Intrinsic::fma:
   case Intrinsic::fmuladd: {
     Value *Op0 = Call->getArgOperand(0);
     Value *Op1 = Call->getArgOperand(1);
     Value *Op2 = Call->getArgOperand(2);
-    if (Value *V = simplifyFPOp({ Op0, Op1, Op2 }, {}, Q))
+    if (Value *V = simplifyFPOp({Op0, Op1, Op2}, {}, Q, fp::ebIgnore,
+                                RoundingMode::NearestTiesToEven))
       return V;
     return nullptr;
   }
@@ -5812,6 +5885,46 @@ static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) {
 
     return nullptr;
   }
+  case Intrinsic::experimental_constrained_fadd: {
+    auto *FPI = cast<ConstrainedFPIntrinsic>(Call);
+    return SimplifyFAddInst(FPI->getArgOperand(0), FPI->getArgOperand(1),
+                            FPI->getFastMathFlags(), Q,
+                            FPI->getExceptionBehavior().getValue(),
+                            FPI->getRoundingMode().getValue());
+    break;
+  }
+  case Intrinsic::experimental_constrained_fsub: {
+    auto *FPI = cast<ConstrainedFPIntrinsic>(Call);
+    return SimplifyFSubInst(FPI->getArgOperand(0), FPI->getArgOperand(1),
+                            FPI->getFastMathFlags(), Q,
+                            FPI->getExceptionBehavior().getValue(),
+                            FPI->getRoundingMode().getValue());
+    break;
+  }
+  case Intrinsic::experimental_constrained_fmul: {
+    auto *FPI = cast<ConstrainedFPIntrinsic>(Call);
+    return SimplifyFMulInst(FPI->getArgOperand(0), FPI->getArgOperand(1),
+                            FPI->getFastMathFlags(), Q,
+                            FPI->getExceptionBehavior().getValue(),
+                            FPI->getRoundingMode().getValue());
+    break;
+  }
+  case Intrinsic::experimental_constrained_fdiv: {
+    auto *FPI = cast<ConstrainedFPIntrinsic>(Call);
+    return SimplifyFDivInst(FPI->getArgOperand(0), FPI->getArgOperand(1),
+                            FPI->getFastMathFlags(), Q,
+                            FPI->getExceptionBehavior().getValue(),
+                            FPI->getRoundingMode().getValue());
+    break;
+  }
+  case Intrinsic::experimental_constrained_frem: {
+    auto *FPI = cast<ConstrainedFPIntrinsic>(Call);
+    return SimplifyFRemInst(FPI->getArgOperand(0), FPI->getArgOperand(1),
+                            FPI->getFastMathFlags(), Q,
+                            FPI->getExceptionBehavior().getValue(),
+                            FPI->getRoundingMode().getValue());
+    break;
+  }
   default:
     return nullptr;
   }

diff  --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 2ddf75229f413..31b4c0ceaa9c6 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -473,6 +473,11 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
 
       return false;
     }
+
+    if (auto *FPI = dyn_cast<ConstrainedFPIntrinsic>(I)) {
+      Optional<fp::ExceptionBehavior> ExBehavior = FPI->getExceptionBehavior();
+      return ExBehavior.getValue() != fp::ebStrict;
+    }
   }
 
   if (isAllocLikeFn(I, TLI))

diff  --git a/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll b/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll
index 1c83cc0f965cf..86789277e8ac5 100644
--- a/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll
+++ b/llvm/test/Transforms/InstSimplify/X86/fp-nan-strictfp.ll
@@ -16,8 +16,7 @@ define float @fadd_nan_op0_strict(float %x) #0 {
 
 define float @fadd_nan_op0_maytrap(float %x) #0 {
 ; CHECK-LABEL: @fadd_nan_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -25,8 +24,7 @@ define float @fadd_nan_op0_maytrap(float %x) #0 {
 
 define float @fadd_nan_op0_upward(float %x) #0 {
 ; CHECK-LABEL: @fadd_nan_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -34,8 +32,7 @@ define float @fadd_nan_op0_upward(float %x) #0 {
 
 define float @fadd_nan_op0_defaultfp(float %x) #0 {
 ; CHECK-LABEL: @fadd_nan_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -52,8 +49,7 @@ define float @fadd_nan_op1_strict(float %x) #0 {
 
 define float @fadd_nan_op1_maytrap(float %x) #0 {
 ; CHECK-LABEL: @fadd_nan_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -61,8 +57,7 @@ define float @fadd_nan_op1_maytrap(float %x) #0 {
 
 define float @fadd_nan_op1_upward(float %x) #0 {
 ; CHECK-LABEL: @fadd_nan_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -70,8 +65,7 @@ define float @fadd_nan_op1_upward(float %x) #0 {
 
 define float @fadd_nan_op1_defaultfp(float %x) #0 {
 ; CHECK-LABEL: @fadd_nan_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -92,8 +86,7 @@ define float @fsub_nan_op0_strict(float %x) {
 
 define float @fsub_nan_op0_maytrap(float %x) {
 ; CHECK-LABEL: @fsub_nan_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -101,8 +94,7 @@ define float @fsub_nan_op0_maytrap(float %x) {
 
 define float @fsub_nan_op0_upward(float %x) {
 ; CHECK-LABEL: @fsub_nan_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -110,8 +102,7 @@ define float @fsub_nan_op0_upward(float %x) {
 
 define float @fsub_nan_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fsub_nan_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -128,8 +119,7 @@ define float @fsub_nan_op1_strict(float %x) {
 
 define float @fsub_nan_op1_maytrap(float %x) {
 ; CHECK-LABEL: @fsub_nan_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -137,8 +127,7 @@ define float @fsub_nan_op1_maytrap(float %x) {
 
 define float @fsub_nan_op1_upward(float %x) {
 ; CHECK-LABEL: @fsub_nan_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -146,8 +135,7 @@ define float @fsub_nan_op1_upward(float %x) {
 
 define float @fsub_nan_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fsub_nan_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -168,8 +156,7 @@ define float @fmul_nan_op0_strict(float %x) {
 
 define float @fmul_nan_op0_maytrap(float %x) {
 ; CHECK-LABEL: @fmul_nan_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -177,8 +164,7 @@ define float @fmul_nan_op0_maytrap(float %x) {
 
 define float @fmul_nan_op0_upward(float %x) {
 ; CHECK-LABEL: @fmul_nan_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -186,8 +172,7 @@ define float @fmul_nan_op0_upward(float %x) {
 
 define float @fmul_nan_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fmul_nan_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -204,8 +189,7 @@ define float @fmul_nan_op1_strict(float %x) {
 
 define float @fmul_nan_op1_maytrap(float %x) {
 ; CHECK-LABEL: @fmul_nan_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -213,8 +197,7 @@ define float @fmul_nan_op1_maytrap(float %x) {
 
 define float @fmul_nan_op1_upward(float %x) {
 ; CHECK-LABEL: @fmul_nan_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -222,8 +205,7 @@ define float @fmul_nan_op1_upward(float %x) {
 
 define float @fmul_nan_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fmul_nan_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -244,8 +226,7 @@ define float @fdiv_nan_op0_strict(float %x) {
 
 define float @fdiv_nan_op0_maytrap(float %x) {
 ; CHECK-LABEL: @fdiv_nan_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -253,8 +234,7 @@ define float @fdiv_nan_op0_maytrap(float %x) {
 
 define float @fdiv_nan_op0_upward(float %x) {
 ; CHECK-LABEL: @fdiv_nan_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -262,8 +242,7 @@ define float @fdiv_nan_op0_upward(float %x) {
 
 define float @fdiv_nan_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fdiv_nan_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -280,8 +259,7 @@ define float @fdiv_nan_op1_strict(float %x) {
 
 define float @fdiv_nan_op1_maytrap(float %x) {
 ; CHECK-LABEL: @fdiv_nan_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -289,8 +267,7 @@ define float @fdiv_nan_op1_maytrap(float %x) {
 
 define float @fdiv_nan_op1_upward(float %x) {
 ; CHECK-LABEL: @fdiv_nan_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -298,8 +275,7 @@ define float @fdiv_nan_op1_upward(float %x) {
 
 define float @fdiv_nan_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fdiv_nan_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -320,8 +296,7 @@ define float @frem_nan_op0_strict(float %x) {
 
 define float @frem_nan_op0_maytrap(float %x) {
 ; CHECK-LABEL: @frem_nan_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -329,8 +304,7 @@ define float @frem_nan_op0_maytrap(float %x) {
 
 define float @frem_nan_op0_upward(float %x) {
 ; CHECK-LABEL: @frem_nan_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -338,8 +312,7 @@ define float @frem_nan_op0_upward(float %x) {
 
 define float @frem_nan_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @frem_nan_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float 0x7FF8000000000000, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -356,8 +329,7 @@ define float @frem_nan_op1_strict(float %x) {
 
 define float @frem_nan_op1_maytrap(float %x) {
 ; CHECK-LABEL: @frem_nan_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -365,8 +337,7 @@ define float @frem_nan_op1_maytrap(float %x) {
 
 define float @frem_nan_op1_upward(float %x) {
 ; CHECK-LABEL: @frem_nan_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -374,8 +345,7 @@ define float @frem_nan_op1_upward(float %x) {
 
 define float @frem_nan_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @frem_nan_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -396,8 +366,7 @@ define float @fma_nan_op0_strict(float %x, float %y) {
 
 define float @fma_nan_op0_maytrap(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -405,8 +374,7 @@ define float @fma_nan_op0_maytrap(float %x, float %y) {
 
 define float @fma_nan_op0_upward(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float [[X:%.*]], float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float %x, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -414,8 +382,7 @@ define float @fma_nan_op0_upward(float %x, float %y) {
 
 define float @fma_nan_op0_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float 0x7FF8000000000000, float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -432,8 +399,7 @@ define float @fma_nan_op1_strict(float %x, float %y) {
 
 define float @fma_nan_op1_maytrap(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float 0x7FF8000000000000, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float 0x7FF8000000000000, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -441,8 +407,7 @@ define float @fma_nan_op1_maytrap(float %x, float %y) {
 
 define float @fma_nan_op1_upward(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float 0x7FF8000000000000, float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float 0x7FF8000000000000, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -450,8 +415,7 @@ define float @fma_nan_op1_upward(float %x, float %y) {
 
 define float @fma_nan_op1_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float 0x7FF8000000000000, float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float 0x7FF8000000000000, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -468,8 +432,7 @@ define float @fma_nan_op2_strict(float %x, float %y) {
 
 define float @fma_nan_op2_maytrap(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op2_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float 0x7FF8000000000000, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -477,8 +440,7 @@ define float @fma_nan_op2_maytrap(float %x, float %y) {
 
 define float @fma_nan_op2_upward(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op2_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float 0x7FF8000000000000, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -486,8 +448,7 @@ define float @fma_nan_op2_upward(float %x, float %y) {
 
 define float @fma_nan_op2_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_nan_op2_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float 0x7FF8000000000000, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r

diff  --git a/llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll b/llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll
new file mode 100644
index 0000000000000..ee0a4ff390f21
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/fast-math-strictfp.ll
@@ -0,0 +1,582 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+;; x * 0 ==> 0 when no-nans and no-signed-zero
+define float @mul_zero_1(float %a) #0 {
+; CHECK-LABEL: @mul_zero_1(
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %b = call nsz nnan float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %b
+}
+
+define float @mul_zero_2(float %a) #0 {
+; CHECK-LABEL: @mul_zero_2(
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %b = call fast float @llvm.experimental.constrained.fmul.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %b
+}
+
+define <2 x float> @mul_zero_nsz_nnan_vec_undef(<2 x float> %a) #0 {
+; CHECK-LABEL: @mul_zero_nsz_nnan_vec_undef(
+; CHECK-NEXT:    ret <2 x float> zeroinitializer
+;
+  %b = call nsz nnan <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> %a, <2 x float><float 0.0, float undef>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %b
+}
+
+;; x * 0 =/=> 0 when there could be nans or -0
+define float @no_mul_zero_1(float %a) #0 {
+; CHECK-LABEL: @no_mul_zero_1(
+; CHECK-NEXT:    [[B:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    ret float [[B]]
+;
+  %b = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %b
+}
+
+define float @no_mul_zero_2(float %a) #0 {
+; CHECK-LABEL: @no_mul_zero_2(
+; CHECK-NEXT:    [[B:%.*]] = call nnan float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[B]]
+;
+  %b = call nnan float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %b
+}
+
+define float @no_mul_zero_3(float %a) #0 {
+; CHECK-LABEL: @no_mul_zero_3(
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[B]]
+;
+  %b = call float @llvm.experimental.constrained.fmul.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %b
+}
+
+; -X + X --> 0.0 (with nnan on the fadd)
+
+define float @fadd_binary_fnegx(float %x) #0 {
+; CHECK-LABEL: @fadd_binary_fnegx(
+; CHECK-NEXT:    [[NEGX:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[NEGX]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %negx = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call nnan float @llvm.experimental.constrained.fadd.f32(float %negx, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+define float @fadd_unary_fnegx(float %x) #0 {
+; CHECK-LABEL: @fadd_unary_fnegx(
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+  %negx = fneg float %x
+  %r = call nnan float @llvm.experimental.constrained.fadd.f32(float %negx, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; X + -X --> 0.0 (with nnan on the fadd)
+
+define <2 x float> @fadd_binary_fnegx_commute_vec(<2 x float> %x) #0 {
+; CHECK-LABEL: @fadd_binary_fnegx_commute_vec(
+; CHECK-NEXT:    [[NEGX:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[X]], <2 x float> [[NEGX]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %negx = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.0, float -0.0>, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %negx, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+define <2 x float> @fadd_unary_fnegx_commute_vec(<2 x float> %x) #0 {
+; CHECK-LABEL: @fadd_unary_fnegx_commute_vec(
+; CHECK-NEXT:    ret <2 x float> zeroinitializer
+;
+  %negx = fneg <2 x float> %x
+  %r = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %negx, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+define <2 x float> @fadd_fnegx_commute_vec_undef(<2 x float> %x) #0 {
+; CHECK-LABEL: @fadd_fnegx_commute_vec_undef(
+; CHECK-NEXT:    [[NEGX:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float undef, float -0.000000e+00>, <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[X]], <2 x float> [[NEGX]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %negx = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float undef, float -0.0>, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %negx, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+; https://bugs.llvm.org/show_bug.cgi?id=26958
+; https://bugs.llvm.org/show_bug.cgi?id=27151
+
+define float @fadd_binary_fneg_nan(float %x) #0 {
+; CHECK-LABEL: @fadd_binary_fneg_nan(
+; CHECK-NEXT:    [[T:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[COULD_BE_NAN:%.*]] = call ninf float @llvm.experimental.constrained.fadd.f32(float [[T]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[COULD_BE_NAN]]
+;
+  %t = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %could_be_nan = call ninf float @llvm.experimental.constrained.fadd.f32(float %t, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %could_be_nan
+}
+
+define float @fadd_unary_fneg_nan(float %x) #0 {
+; CHECK-LABEL: @fadd_unary_fneg_nan(
+; CHECK-NEXT:    [[T:%.*]] = fneg nnan float [[X:%.*]]
+; CHECK-NEXT:    [[COULD_BE_NAN:%.*]] = call ninf float @llvm.experimental.constrained.fadd.f32(float [[T]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[COULD_BE_NAN]]
+;
+  %t = fneg nnan float %x
+  %could_be_nan = call ninf float @llvm.experimental.constrained.fadd.f32(float %t, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %could_be_nan
+}
+
+define float @fadd_binary_fneg_nan_commute(float %x) #0 {
+; CHECK-LABEL: @fadd_binary_fneg_nan_commute(
+; CHECK-NEXT:    [[T:%.*]] = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[COULD_BE_NAN:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X]], float [[T]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[COULD_BE_NAN]]
+;
+  %t = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float -0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %could_be_nan = call float @llvm.experimental.constrained.fadd.f32(float %x, float %t, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %could_be_nan
+}
+
+define float @fadd_unary_fneg_nan_commute(float %x) #0 {
+; CHECK-LABEL: @fadd_unary_fneg_nan_commute(
+; CHECK-NEXT:    [[T:%.*]] = fneg nnan ninf float [[X:%.*]]
+; CHECK-NEXT:    [[COULD_BE_NAN:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X]], float [[T]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[COULD_BE_NAN]]
+;
+  %t = fneg nnan ninf float %x
+  %could_be_nan = call float @llvm.experimental.constrained.fadd.f32(float %x, float %t, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %could_be_nan
+}
+
+; X + (0.0 - X) --> 0.0 (with nnan on the fadd)
+
+define float @fadd_fsub_nnan_ninf(float %x) #0 {
+; CHECK-LABEL: @fadd_fsub_nnan_ninf(
+; CHECK-NEXT:    [[SUB:%.*]] = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[ZERO:%.*]] = call nnan ninf float @llvm.experimental.constrained.fadd.f32(float [[X]], float [[SUB]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[ZERO]]
+;
+  %sub = call nnan ninf float @llvm.experimental.constrained.fsub.f32(float 0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %zero = call nnan ninf float @llvm.experimental.constrained.fadd.f32(float %x, float %sub, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %zero
+}
+
+; (0.0 - X) + X --> 0.0 (with nnan on the fadd)
+
+define <2 x float> @fadd_fsub_nnan_ninf_commute_vec(<2 x float> %x) #0 {
+; CHECK-LABEL: @fadd_fsub_nnan_ninf_commute_vec(
+; CHECK-NEXT:    [[SUB:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[ZERO:%.*]] = call nnan ninf <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[SUB]], <2 x float> [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[ZERO]]
+;
+  %sub = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %zero = call nnan ninf <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %sub, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %zero
+}
+
+; 'ninf' is not required because 'nnan' allows us to assume
+; that X is not INF or -INF (adding opposite INFs would be NaN).
+
+define float @fadd_fsub_nnan(float %x) #0 {
+; CHECK-LABEL: @fadd_fsub_nnan(
+; CHECK-NEXT:    [[SUB:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[ZERO:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[SUB]], float [[X]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[ZERO]]
+;
+  %sub = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %zero = call nnan float @llvm.experimental.constrained.fadd.f32(float %sub, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %zero
+}
+
+; fsub nnan x, x ==> 0.0
+define float @fsub_x_x(float %a) #0 {
+; X - X ==> 0
+; CHECK-LABEL: @fsub_x_x(
+; CHECK-NEXT:    [[NO_ZERO1:%.*]] = call ninf float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[NO_ZERO2:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[NO_ZERO:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[NO_ZERO1]], float [[NO_ZERO2]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[NO_ZERO]]
+;
+  %zero1 = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+
+; Dont fold
+  %no_zero1 = call ninf float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %no_zero2 = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %no_zero = call float @llvm.experimental.constrained.fadd.f32(float %no_zero1, float %no_zero2, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+
+; Should get folded
+  %ret = call nsz float @llvm.experimental.constrained.fadd.f32(float %no_zero, float %zero1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+
+  ret float %ret
+}
+
+; fsub nsz 0.0, (fsub 0.0, X) ==> X
+define float @fsub_0_0_x(float %a) #0 {
+; CHECK-LABEL: @fsub_0_0_x(
+; CHECK-NEXT:    [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+; fsub nsz 0.0, (fneg X) ==> X
+define float @fneg_x(float %a) #0 {
+; CHECK-LABEL: @fneg_x(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %t1 = fneg float %a
+  %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+define <2 x float> @fsub_0_0_x_vec_undef1(<2 x float> %a) #0 {
+; CHECK-LABEL: @fsub_0_0_x_vec_undef1(
+; CHECK-NEXT:    [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float 0.000000e+00, float undef>, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float 0.0, float undef>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fneg_x_vec_undef1(<2 x float> %a) #0 {
+; CHECK-LABEL: @fneg_x_vec_undef1(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %t1 = fneg <2 x float> %a
+  %ret = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float 0.0, float undef>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fsub_0_0_x_vec_undef2(<2 x float> %a) #0 {
+; CHECK-LABEL: @fsub_0_0_x_vec_undef2(
+; CHECK-NEXT:    [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float undef, float -0.000000e+00>, <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> zeroinitializer, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float undef, float -0.0>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+; fadd nsz X, 0 ==> X
+
+define <2 x float> @fadd_zero_nsz_vec(<2 x float> %x) #0 {
+; CHECK-LABEL: @fadd_zero_nsz_vec(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %r = call nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+define <2 x float> @fadd_zero_nsz_vec_undef(<2 x float> %x) #0 {
+; CHECK-LABEL: @fadd_zero_nsz_vec_undef(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %r = call nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> <float 0.0, float undef>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+define float @nofold_fadd_x_0(float %a) #0 {
+; Dont fold
+; CHECK-LABEL: @nofold_fadd_x_0(
+; CHECK-NEXT:    [[NO_ZERO1:%.*]] = call ninf float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[NO_ZERO2:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[A]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[NO_ZERO:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[NO_ZERO1]], float [[NO_ZERO2]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[NO_ZERO]]
+;
+  %no_zero1 = call ninf float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %no_zero2 = call nnan float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %no_zero = call float @llvm.experimental.constrained.fadd.f32(float %no_zero1, float %no_zero2, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %no_zero
+}
+
+define float @fold_fadd_nsz_x_0(float %a) #0 {
+; CHECK-LABEL: @fold_fadd_nsz_x_0(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %add = call nsz float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %add
+}
+
+; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify.
+
+define float @fold_fadd_cannot_be_neg0_nsz_src_x_0(float %a, float %b) #0 {
+; CHECK-LABEL: @fold_fadd_cannot_be_neg0_nsz_src_x_0(
+; CHECK-NEXT:    [[NSZ:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float [[B:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[NSZ]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %nsz = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %add = call float @llvm.experimental.constrained.fadd.f32(float %nsz, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %add
+}
+
+define float @fold_fadd_cannot_be_neg0_fabs_src_x_0(float %a) #0 {
+; CHECK-LABEL: @fold_fadd_cannot_be_neg0_fabs_src_x_0(
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %fabs = call float @llvm.fabs.f32(float %a)
+  %add = call float @llvm.experimental.constrained.fadd.f32(float %fabs, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %add
+}
+
+; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify.
+
+define float @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0(float %a, float %b) #0 {
+; CHECK-LABEL: @fold_fadd_cannot_be_neg0_sqrt_nsz_src_x_0(
+; CHECK-NEXT:    [[NSZ:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float [[B:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[NSZ]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[SQRT]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %nsz = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %sqrt = call float @llvm.experimental.constrained.sqrt.f32(float %nsz, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %add = call float @llvm.experimental.constrained.fadd.f32(float %sqrt, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %add
+}
+
+; 'nsz' does not guarantee that -0.0 does not occur, so this does not simplify.
+
+define float @fold_fadd_cannot_be_neg0_canonicalize_nsz_src_x_0(float %a, float %b) #0 {
+; CHECK-LABEL: @fold_fadd_cannot_be_neg0_canonicalize_nsz_src_x_0(
+; CHECK-NEXT:    [[NSZ:%.*]] = call nsz float @llvm.experimental.constrained.fmul.f32(float [[A:%.*]], float [[B:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[NSZ]])
+; CHECK-NEXT:    [[ADD:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[CANON]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %nsz = call nsz float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %canon = call float @llvm.canonicalize.f32(float %nsz)
+  %add = call float @llvm.experimental.constrained.fadd.f32(float %canon, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %add
+}
+
+; fdiv nsz nnan 0, X ==> 0
+; 0 / X -> 0
+
+define double @fdiv_zero_by_x(double %x) #0 {
+; CHECK-LABEL: @fdiv_zero_by_x(
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+  %r = call nnan nsz double @llvm.experimental.constrained.fdiv.f64(double 0.0, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %r
+}
+
+define <2 x double> @fdiv_zero_by_x_vec_undef(<2 x double> %x) #0 {
+; CHECK-LABEL: @fdiv_zero_by_x_vec_undef(
+; CHECK-NEXT:    ret <2 x double> zeroinitializer
+;
+  %r = call nnan nsz <2 x double> @llvm.experimental.constrained.fdiv.v2f64(<2 x double> <double 0.0, double undef>, <2 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x double> %r
+}
+
+; 0 % X -> 0
+; nsz is not necessary - frem result always has the sign of the dividend
+
+define double @frem_zero_by_x(double %x) #0 {
+; CHECK-LABEL: @frem_zero_by_x(
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+  %r = call nnan double @llvm.experimental.constrained.frem.f64(double 0.0, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %r
+}
+
+define <2 x double> @frem_poszero_by_x_vec_undef(<2 x double> %x) #0 {
+; CHECK-LABEL: @frem_poszero_by_x_vec_undef(
+; CHECK-NEXT:    ret <2 x double> zeroinitializer
+;
+  %r = call nnan <2 x double> @llvm.experimental.constrained.frem.v2f64(<2 x double> <double 0.0, double undef>, <2 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x double> %r
+}
+
+; -0 % X -> -0
+; nsz is not necessary - frem result always has the sign of the dividend
+
+define double @frem_negzero_by_x(double %x) #0 {
+; CHECK-LABEL: @frem_negzero_by_x(
+; CHECK-NEXT:    ret double -0.000000e+00
+;
+  %r = call nnan double @llvm.experimental.constrained.frem.f64(double -0.0, double %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %r
+}
+
+define <2 x double> @frem_negzero_by_x_vec_undef(<2 x double> %x) #0 {
+; CHECK-LABEL: @frem_negzero_by_x_vec_undef(
+; CHECK-NEXT:    ret <2 x double> <double -0.000000e+00, double -0.000000e+00>
+;
+  %r = call nnan <2 x double> @llvm.experimental.constrained.frem.v2f64(<2 x double> <double undef, double -0.0>, <2 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x double> %r
+}
+
+define float @fdiv_self(float %f) #0 {
+; CHECK-LABEL: @fdiv_self(
+; CHECK-NEXT:    ret float 1.000000e+00
+;
+  %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %f, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define float @fdiv_self_invalid(float %f) #0 {
+; CHECK-LABEL: @fdiv_self_invalid(
+; CHECK-NEXT:    [[DIV:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[F:%.*]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %div = call float @llvm.experimental.constrained.fdiv.f32(float %f, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define float @fdiv_neg1(float %f) #0 {
+; CHECK-LABEL: @fdiv_neg1(
+; CHECK-NEXT:    [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[NEG]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %neg = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %neg, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define float @fdiv_neg2(float %f) #0 {
+; CHECK-LABEL: @fdiv_neg2(
+; CHECK-NEXT:    [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[NEG]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %neg = call fast float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %neg, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define float @fdiv_neg_invalid(float %f) #0 {
+; CHECK-LABEL: @fdiv_neg_invalid(
+; CHECK-NEXT:    [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[DIV:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[NEG]], float [[F]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %neg = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %div = call float @llvm.experimental.constrained.fdiv.f32(float %neg, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define float @fdiv_neg_swapped1(float %f) #0 {
+; CHECK-LABEL: @fdiv_neg_swapped1(
+; CHECK-NEXT:    [[NEG:%.*]] = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[F]], float [[NEG]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %neg = call fast float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %f, float %neg, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define float @fdiv_neg_swapped2(float %f) #0 {
+; CHECK-LABEL: @fdiv_neg_swapped2(
+; CHECK-NEXT:    [[NEG:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[DIV:%.*]] = call nnan float @llvm.experimental.constrained.fdiv.f32(float [[F]], float [[NEG]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[DIV]]
+;
+  %neg = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %div = call nnan float @llvm.experimental.constrained.fdiv.f32(float %f, float %neg, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %div
+}
+
+define <2 x float> @fdiv_neg_vec_undef_elt(<2 x float> %f) #0 {
+; CHECK-LABEL: @fdiv_neg_vec_undef_elt(
+; CHECK-NEXT:    [[NEG:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float 0.000000e+00, float undef>, <2 x float> [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[DIV:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> [[F]], <2 x float> [[NEG]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[DIV]]
+;
+  %neg = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float 0.000000e+00, float undef>, <2 x float> %f, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %div = call nnan <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> %f, <2 x float> %neg, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %div
+}
+
+; PR21126: http://llvm.org/bugs/show_bug.cgi?id=21126
+; With loose math, sqrt(X) * sqrt(X) is just X.
+
+declare double @llvm.sqrt.f64(double)
+
+define double @sqrt_squared(double %f) #0 {
+; CHECK-LABEL: @sqrt_squared(
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
+; CHECK-NEXT:    [[MUL:%.*]] = call reassoc nnan nsz double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+  %mul = call reassoc nnan nsz double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %mul
+}
+
+; Negative tests for the above transform: we need all 3 of those flags.
+
+define double @sqrt_squared_not_fast_enough1(double %f) #0 {
+; CHECK-LABEL: @sqrt_squared_not_fast_enough1(
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
+; CHECK-NEXT:    [[MUL:%.*]] = call nnan nsz double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+  %mul = call nnan nsz double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %mul
+}
+
+define double @sqrt_squared_not_fast_enough2(double %f) #0 {
+; CHECK-LABEL: @sqrt_squared_not_fast_enough2(
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
+; CHECK-NEXT:    [[MUL:%.*]] = call reassoc nnan double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+  %mul = call reassoc nnan double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %mul
+}
+
+define double @sqrt_squared_not_fast_enough3(double %f) #0 {
+; CHECK-LABEL: @sqrt_squared_not_fast_enough3(
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.experimental.constrained.sqrt.f64(double [[F:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore")
+; CHECK-NEXT:    [[MUL:%.*]] = call reassoc nsz double @llvm.experimental.constrained.fmul.f64(double [[SQRT]], double [[SQRT]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret double [[MUL]]
+;
+  %sqrt = call double @llvm.experimental.constrained.sqrt.f64(double %f, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+  %mul = call reassoc nsz double @llvm.experimental.constrained.fmul.f64(double %sqrt, double %sqrt, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %mul
+}
+
+declare float @llvm.fabs.f32(float)
+declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata) #0
+declare double @llvm.experimental.constrained.sqrt.f64(double, metadata, metadata) #0
+declare float @llvm.canonicalize.f32(float)
+
+declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.fmul.f32(float, float, metadata, metadata) #0
+declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0
+declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+declare <2 x double> @llvm.experimental.constrained.fdiv.v2f64(<2 x double>, <2 x double>, metadata, metadata) #0
+
+declare double @llvm.experimental.constrained.frem.f64(double, double, metadata, metadata) #0
+declare <2 x double> @llvm.experimental.constrained.frem.v2f64(<2 x double>, <2 x double>, metadata, metadata) #0
+
+attributes #0 = { strictfp }
+

diff  --git a/llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll b/llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll
new file mode 100644
index 0000000000000..802d30dd6b2e9
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/fdiv-strictfp.ll
@@ -0,0 +1,87 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define float @fdiv_constant_fold() #0 {
+; CHECK-LABEL: @fdiv_constant_fold(
+; CHECK-NEXT:    ret float 1.500000e+00
+;
+  %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+
+  ret float %f
+}
+
+define float @fdiv_constant_fold_strict() #0 {
+; CHECK-LABEL: @fdiv_constant_fold_strict(
+; CHECK-NEXT:    [[F:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 3.000000e+00, float 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    ret float [[F]]
+;
+  %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
+
+  ret float %f
+}
+
+define float @frem_constant_fold() #0 {
+; CHECK-LABEL: @frem_constant_fold(
+; CHECK-NEXT:    ret float 1.500000e+00
+;
+  %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %f
+}
+
+define float @frem_constant_fold_strict() #0 {
+; CHECK-LABEL: @frem_constant_fold_strict(
+; CHECK-NEXT:    [[F:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float 3.000000e+00, float 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[F]]
+;
+  %f = call float @llvm.experimental.constrained.fdiv.f32(float 3.0, float 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
+  ret float %f
+}
+
+define double @fmul_fdiv_common_operand(double %x, double %y) #0 {
+; CHECK-LABEL: @fmul_fdiv_common_operand(
+; CHECK-NEXT:    [[M:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[X:%.*]], double [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[D:%.*]] = call reassoc nnan double @llvm.experimental.constrained.fdiv.f64(double [[M]], double [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret double [[D]]
+;
+  %m = call double @llvm.experimental.constrained.fmul.f64(double %x, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %d = call reassoc nnan double @llvm.experimental.constrained.fdiv.f64(double %m, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %d
+}
+
+; Negative test - the fdiv must be reassociative and not allow NaNs.
+
+define double @fmul_fdiv_common_operand_too_strict(double %x, double %y) #0 {
+; CHECK-LABEL: @fmul_fdiv_common_operand_too_strict(
+; CHECK-NEXT:    [[M:%.*]] = call fast double @llvm.experimental.constrained.fmul.f64(double [[X:%.*]], double [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[D:%.*]] = call reassoc double @llvm.experimental.constrained.fdiv.f64(double [[M]], double [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret double [[D]]
+;
+  %m = call fast double @llvm.experimental.constrained.fmul.f64(double %x, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %d = call reassoc double @llvm.experimental.constrained.fdiv.f64(double %m, double %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %d
+}
+
+; Commute the fmul operands. Use a vector type to verify that works too.
+
+define <2 x float> @fmul_fdiv_common_operand_commute_vec(<2 x float> %x, <2 x float> %y) #0 {
+; CHECK-LABEL: @fmul_fdiv_common_operand_commute_vec(
+; CHECK-NEXT:    [[M:%.*]] = call <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> [[Y:%.*]], <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[D:%.*]] = call fast <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> [[M]], <2 x float> [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[D]]
+;
+  %m = call <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float> %y, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %d = call fast <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float> %m, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %d
+}
+
+declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fmul.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0
+declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fdiv.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.frem.f32(float, float, metadata, metadata) #0
+
+attributes #0 = { strictfp }
+

diff  --git a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll
new file mode 100644
index 0000000000000..f775d93e99a3c
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic-strictfp.ll
@@ -0,0 +1,538 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; fneg (fsub -0.0, X) ==> X
+define float @fsub_-0_x(float %a) #0 {
+; CHECK-LABEL: @fsub_-0_x(
+; CHECK-NEXT:    [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    [[RET:%.*]] = fneg float [[T1]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = fneg float %t1
+  ret float %ret
+}
+
+define <2 x float> @fsub_-0_x_vec(<2 x float> %a) #0 {
+; CHECK-LABEL: @fsub_-0_x_vec(
+; CHECK-NEXT:    [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = fneg <2 x float> [[T1]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float -0.0>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = fneg <2 x float> %t1
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fsub_-0_x_vec_undef_elts(<2 x float> %a) #0 {
+; CHECK-LABEL: @fsub_-0_x_vec_undef_elts(
+; CHECK-NEXT:    [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.000000e+00, float undef>, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = fneg <2 x float> [[T1]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float undef>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = fneg <2 x float> %t1
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) #0 {
+; CHECK-LABEL: @fsub_negzero_vec_undef_elts(
+; CHECK-NEXT:    [[R:%.*]] = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float undef, float -0.000000e+00>, <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %r = call nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float undef, float -0.0>, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+; fsub -0.0, (fsub -0.0, X) ==> X
+define float @fsub_-0_-0_x(float %a) #0 {
+; CHECK-LABEL: @fsub_-0_-0_x(
+; CHECK-NEXT:    [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+; fsub -0.0, (fneg X) ==> X
+define float @fneg_x(float %a) #0 {
+; CHECK-LABEL: @fneg_x(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %t1 = fneg float %a
+  %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) #0 {
+; CHECK-LABEL: @fsub_-0_-0_x_vec(
+; CHECK-NEXT:    [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float -0.0>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float -0.0>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fneg_x_vec(<2 x float> %a) #0 {
+; CHECK-LABEL: @fneg_x_vec(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %t1 = fneg <2 x float> %a
+  %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float -0.0>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) #0 {
+; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts(
+; CHECK-NEXT:    [[T1:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float undef, float -0.000000e+00>, <2 x float> [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> <float -0.000000e+00, float undef>, <2 x float> [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %t1 = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float undef, float -0.0>, <2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float undef>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+define <2 x float> @fneg_x_vec_undef_elts(<2 x float> %a) #0 {
+; CHECK-LABEL: @fneg_x_vec_undef_elts(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %t1 = fneg <2 x float> %a
+  %ret = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float><float -0.0, float undef>, <2 x float> %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+; fsub -0.0, (fsub 0.0, X) != X
+define float @fsub_-0_0_x(float %a) #0 {
+; CHECK-LABEL: @fsub_-0_0_x(
+; CHECK-NEXT:    [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+; fsub 0.0, (fsub -0.0, X) != X
+define float @fsub_0_-0_x(float %a) #0 {
+; CHECK-LABEL: @fsub_0_-0_x(
+; CHECK-NEXT:    [[T1:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[T1]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %t1 = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %ret = call float @llvm.experimental.constrained.fsub.f32(float 0.0, float %t1, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+; fsub X, 0 ==> X
+define float @fsub_x_0(float %x) #0 {
+; CHECK-LABEL: @fsub_x_0(
+; CHECK-NEXT:    ret float [[X:%.*]]
+;
+  %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) #0 {
+; CHECK-LABEL: @fsub_x_0_vec_undef(
+; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
+;
+  %r = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %x, <2 x float><float undef, float 0.0>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+; fadd X, -0 ==> X
+define float @fadd_x_n0(float %a) #0 {
+; CHECK-LABEL: @fadd_x_n0(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) #0 {
+; CHECK-LABEL: @fadd_x_n0_vec_undef_elt(
+; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
+;
+  %ret = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> <float -0.0, float undef>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+; fadd X, 0 ==> X
+define float @fadd_x_p0(float %a) #0 {
+; CHECK-LABEL: @fadd_x_p0(
+; CHECK-NEXT:    [[RET:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[RET]]
+;
+  %ret = call float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %ret
+}
+
+define <2 x float> @fadd_x_p0_vec_undef_elt(<2 x float> %a) #0 {
+; CHECK-LABEL: @fadd_x_p0_vec_undef_elt(
+; CHECK-NEXT:    [[RET:%.*]] = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> <float 0.000000e+00, float undef>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[RET]]
+;
+  %ret = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> <float 0.0, float undef>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %ret
+}
+
+; fmul X, 1.0 ==> X
+define double @fmul_X_1(double %a) #0 {
+; CHECK-LABEL: @fmul_X_1(
+; CHECK-NEXT:    ret double [[A:%.*]]
+;
+  %b = call double @llvm.experimental.constrained.fmul.f64(double 1.0, double %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret double %b
+}
+
+; Originally PR2642
+define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
+; CHECK-LABEL: @fmul_X_1_vec(
+; CHECK-NEXT:    ret <4 x float> [[X:%.*]]
+;
+  %m = call <4 x float> @llvm.experimental.constrained.fmul.v4f32(<4 x float> %x, <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0>, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <4 x float> %m
+}
+
+; fdiv X, 1.0 ==> X
+define float @fdiv_x_1(float %a) #0 {
+; CHECK-LABEL: @fdiv_x_1(
+; CHECK-NEXT:    ret float [[A:%.*]]
+;
+  %ret = call float @llvm.experimental.constrained.fdiv.f32(float %a, float 1.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+
+  ret float %ret
+}
+
+
+; The fabs can't be eliminated because llvm.experimental.constrained.sqrt.f32 may return -0 or NaN with
+; an arbitrary sign bit.
+define float @fabs_sqrt(float %a) #0 {
+; CHECK-LABEL: @fabs_sqrt(
+; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The fabs can't be eliminated because the nnan sqrt may still return -0.
+define float @fabs_sqrt_nnan(float %a) #0 {
+; CHECK-LABEL: @fabs_sqrt_nnan(
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call nnan float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The fabs can't be eliminated because the nsz sqrt may still return NaN.
+define float @fabs_sqrt_nsz(float %a) #0 {
+; CHECK-LABEL: @fabs_sqrt_nsz(
+; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call nsz float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The fabs can be eliminated because we're nsz and nnan.
+define float @fabs_sqrt_nnan_nsz(float %a) #0 {
+; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call nnan nsz float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; The second fabs can be eliminated because the operand to sqrt cannot be -0.
+define float @fabs_sqrt_nnan_fabs(float %a) #0 {
+; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
+; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[B]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %b = call float @llvm.fabs.f32(float %a)
+  %sqrt = call nnan float @llvm.experimental.constrained.sqrt.f32(float %b, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %sqrt)
+  ret float %fabs
+}
+
+; Y - (Y - X) --> X
+
+define float @fsub_fsub_common_op(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fsub_common_op(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) #0 {
+; CHECK-LABEL: @fsub_fsub_common_op_vec(
+; CHECK-NEXT:    [[S:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[Y:%.*]], <2 x float> [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[Y]], <2 x float> [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %s = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %y, <2 x float> %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %y, <2 x float> %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+; Negative test - fsub is not commutative.
+; Y - (X - Y) --> (Y - X) + Y (canonicalized)
+
+define float @fsub_fsub_wrong_common_op(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fsub_wrong_common_op(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Negative test - negated operand needed.
+; (Y - X) - Y --> -X
+
+define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Negative test - fsub is not commutative.
+; (X - Y) - Y --> ?
+
+define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; (Y + X) - Y --> X
+
+define float @fadd_fsub_common_op(float %x, float %y) #0 {
+; CHECK-LABEL: @fadd_fsub_common_op(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[A]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %a = call float @llvm.experimental.constrained.fadd.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %a, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; (X + Y) - Y --> X
+
+define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) #0 {
+; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
+; CHECK-NEXT:    [[A:%.*]] = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[A]], <2 x float> [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %a = call <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %x, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %a, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+; Negative test - negated operand needed.
+; Y - (Y + X) --> -X
+
+define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %a = call float @llvm.experimental.constrained.fadd.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Negative test - negated operand needed.
+; Y - (X + Y) --> -X
+
+define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %a = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float %y, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Y + (X - Y) --> X
+
+define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) #0 {
+; CHECK-LABEL: @fsub_fadd_common_op_vec(
+; CHECK-NEXT:    [[S:%.*]] = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[Y]], <2 x float> [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[R]]
+;
+  %s = call <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float> %x, <2 x float> %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %y, <2 x float> %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret <2 x float> %r
+}
+
+; (X - Y) + Y --> X
+
+define float @fsub_fadd_common_op_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fadd_common_op_commute(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Negative test.
+; Y + (Y - X) --> ?
+
+define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float [[Y]], float [[S]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float %y, float %s, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Negative test.
+; (Y - X) + Y --> ?
+
+define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) #0 {
+; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
+; CHECK-NEXT:    [[S:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[R:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float [[S]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %s = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %r = call reassoc nsz float @llvm.experimental.constrained.fadd.f32(float %s, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  ret float %r
+}
+
+; Originally PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
+
+define float @maxnum_with_poszero_op(float %a) #0 {
+; CHECK-LABEL: @maxnum_with_poszero_op(
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float [[A:%.*]], float 0.000000e+00, metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %max = call float @llvm.experimental.constrained.maxnum.f32(float %a, float 0.0, metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %max)
+  ret float %fabs
+}
+
+define float @maxnum_with_poszero_op_commute(float %a) #0 {
+; CHECK-LABEL: @maxnum_with_poszero_op_commute(
+; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float 0.000000e+00, float [[SQRT]], metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %sqrt = call float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %max = call float @llvm.experimental.constrained.maxnum.f32(float 0.0, float %sqrt, metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %max)
+  ret float %fabs
+}
+
+define float @maxnum_with_negzero_op(float %a) #0 {
+; CHECK-LABEL: @maxnum_with_negzero_op(
+; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float -0.000000e+00, float [[FABSA]], metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %nnan = call nnan float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabsa = call float @llvm.fabs.f32(float %nnan)
+  %max = call float @llvm.experimental.constrained.maxnum.f32(float -0.0, float %fabsa, metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %max)
+  ret float %fabs
+}
+
+define float @maxnum_with_negzero_op_commute(float %a) #0 {
+; CHECK-LABEL: @maxnum_with_negzero_op_commute(
+; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.experimental.constrained.sqrt.f32(float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float [[FABSA]], float -0.000000e+00, metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %nnan = call nnan float @llvm.experimental.constrained.sqrt.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
+  %fabsa = call float @llvm.fabs.f32(float %nnan)
+  %max = call float @llvm.experimental.constrained.maxnum.f32(float %fabsa, float -0.0, metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %max)
+  ret float %fabs
+}
+
+; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
+
+define float @maxnum_with_pos_one_op(float %a) #0 {
+; CHECK-LABEL: @maxnum_with_pos_one_op(
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.experimental.constrained.maxnum.f32(float [[A:%.*]], float 1.000000e+00, metadata !"fpexcept.ignore") #[[ATTR0]]
+; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
+; CHECK-NEXT:    ret float [[FABS]]
+;
+  %max = call float @llvm.experimental.constrained.maxnum.f32(float %a, float 1.0, metadata !"fpexcept.ignore") #0
+  %fabs = call float @llvm.fabs.f32(float %max)
+  ret float %fabs
+}
+
+declare float @llvm.fabs.f32(float)
+declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
+
+declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) #0
+declare <2 x float> @llvm.experimental.constrained.fsub.v2f32(<2 x float>, <2 x float>, metadata, metadata) #0
+
+declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) #0
+declare <4 x float> @llvm.experimental.constrained.fmul.v4f32(<4 x float>, <4 x float>, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) #0
+
+declare float @llvm.experimental.constrained.maxnum.f32(float, float, metadata) #0
+declare float @llvm.experimental.constrained.sqrt.f32(float, metadata, metadata) #0
+
+attributes #0 = { strictfp }

diff  --git a/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll b/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll
index 17a62257f30e7..065b1f6410888 100644
--- a/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll
+++ b/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll
@@ -36,8 +36,7 @@ define float @fadd_undef_op0_upward(float %x) #0 {
 
 define float @fadd_undef_op0_defaultfp(float %x) #0 {
 ; CHECK-LABEL: @fadd_undef_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -46,7 +45,7 @@ define float @fadd_undef_op0_defaultfp(float %x) #0 {
 define float @fadd_poison_op0_strict(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op0_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -54,8 +53,7 @@ define float @fadd_poison_op0_strict(float %x) #0 {
 
 define float @fadd_poison_op0_maytrap(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -63,8 +61,7 @@ define float @fadd_poison_op0_maytrap(float %x) #0 {
 
 define float @fadd_poison_op0_upward(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -72,8 +69,7 @@ define float @fadd_poison_op0_upward(float %x) #0 {
 
 define float @fadd_poison_op0_defaultfp(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -108,8 +104,7 @@ define float @fadd_undef_op1_upward(float %x) #0 {
 
 define float @fadd_undef_op1_defaultfp(float %x) #0 {
 ; CHECK-LABEL: @fadd_undef_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -118,7 +113,7 @@ define float @fadd_undef_op1_defaultfp(float %x) #0 {
 define float @fadd_poison_op1_strict(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op1_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -126,8 +121,7 @@ define float @fadd_poison_op1_strict(float %x) #0 {
 
 define float @fadd_poison_op1_maytrap(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -135,8 +129,7 @@ define float @fadd_poison_op1_maytrap(float %x) #0 {
 
 define float @fadd_poison_op1_upward(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -144,8 +137,7 @@ define float @fadd_poison_op1_upward(float %x) #0 {
 
 define float @fadd_poison_op1_defaultfp(float %x) #0 {
 ; CHECK-LABEL: @fadd_poison_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -184,8 +176,7 @@ define float @fsub_undef_op0_upward(float %x) {
 
 define float @fsub_undef_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fsub_undef_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -194,7 +185,7 @@ define float @fsub_undef_op0_defaultfp(float %x) {
 define float @fsub_poison_op0_strict(float %x) {
 ; CHECK-LABEL: @fsub_poison_op0_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -202,8 +193,7 @@ define float @fsub_poison_op0_strict(float %x) {
 
 define float @fsub_poison_op0_maytrap(float %x) {
 ; CHECK-LABEL: @fsub_poison_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -211,8 +201,7 @@ define float @fsub_poison_op0_maytrap(float %x) {
 
 define float @fsub_poison_op0_upward(float %x) {
 ; CHECK-LABEL: @fsub_poison_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -220,8 +209,7 @@ define float @fsub_poison_op0_upward(float %x) {
 
 define float @fsub_poison_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fsub_poison_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -256,8 +244,7 @@ define float @fsub_undef_op1_upward(float %x) {
 
 define float @fsub_undef_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fsub_undef_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -266,7 +253,7 @@ define float @fsub_undef_op1_defaultfp(float %x) {
 define float @fsub_poison_op1_strict(float %x) {
 ; CHECK-LABEL: @fsub_poison_op1_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -274,8 +261,7 @@ define float @fsub_poison_op1_strict(float %x) {
 
 define float @fsub_poison_op1_maytrap(float %x) {
 ; CHECK-LABEL: @fsub_poison_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -283,8 +269,7 @@ define float @fsub_poison_op1_maytrap(float %x) {
 
 define float @fsub_poison_op1_upward(float %x) {
 ; CHECK-LABEL: @fsub_poison_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -292,8 +277,7 @@ define float @fsub_poison_op1_upward(float %x) {
 
 define float @fsub_poison_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fsub_poison_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -332,8 +316,7 @@ define float @fmul_undef_op0_upward(float %x) {
 
 define float @fmul_undef_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fmul_undef_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -342,7 +325,7 @@ define float @fmul_undef_op0_defaultfp(float %x) {
 define float @fmul_poison_op0_strict(float %x) {
 ; CHECK-LABEL: @fmul_poison_op0_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -350,8 +333,7 @@ define float @fmul_poison_op0_strict(float %x) {
 
 define float @fmul_poison_op0_maytrap(float %x) {
 ; CHECK-LABEL: @fmul_poison_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -359,8 +341,7 @@ define float @fmul_poison_op0_maytrap(float %x) {
 
 define float @fmul_poison_op0_upward(float %x) {
 ; CHECK-LABEL: @fmul_poison_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -368,8 +349,7 @@ define float @fmul_poison_op0_upward(float %x) {
 
 define float @fmul_poison_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fmul_poison_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -404,8 +384,7 @@ define float @fmul_undef_op1_upward(float %x) {
 
 define float @fmul_undef_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fmul_undef_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -414,7 +393,7 @@ define float @fmul_undef_op1_defaultfp(float %x) {
 define float @fmul_poison_op1_strict(float %x) {
 ; CHECK-LABEL: @fmul_poison_op1_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -422,8 +401,7 @@ define float @fmul_poison_op1_strict(float %x) {
 
 define float @fmul_poison_op1_maytrap(float %x) {
 ; CHECK-LABEL: @fmul_poison_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -431,8 +409,7 @@ define float @fmul_poison_op1_maytrap(float %x) {
 
 define float @fmul_poison_op1_upward(float %x) {
 ; CHECK-LABEL: @fmul_poison_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -440,8 +417,7 @@ define float @fmul_poison_op1_upward(float %x) {
 
 define float @fmul_poison_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fmul_poison_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -480,8 +456,7 @@ define float @fdiv_undef_op0_upward(float %x) {
 
 define float @fdiv_undef_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fdiv_undef_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -490,7 +465,7 @@ define float @fdiv_undef_op0_defaultfp(float %x) {
 define float @fdiv_poison_op0_strict(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op0_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -498,8 +473,7 @@ define float @fdiv_poison_op0_strict(float %x) {
 
 define float @fdiv_poison_op0_maytrap(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -507,8 +481,7 @@ define float @fdiv_poison_op0_maytrap(float %x) {
 
 define float @fdiv_poison_op0_upward(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -516,8 +489,7 @@ define float @fdiv_poison_op0_upward(float %x) {
 
 define float @fdiv_poison_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -552,8 +524,7 @@ define float @fdiv_undef_op1_upward(float %x) {
 
 define float @fdiv_undef_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fdiv_undef_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -562,7 +533,7 @@ define float @fdiv_undef_op1_defaultfp(float %x) {
 define float @fdiv_poison_op1_strict(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op1_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -570,8 +541,7 @@ define float @fdiv_poison_op1_strict(float %x) {
 
 define float @fdiv_poison_op1_maytrap(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -579,8 +549,7 @@ define float @fdiv_poison_op1_maytrap(float %x) {
 
 define float @fdiv_poison_op1_upward(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -588,8 +557,7 @@ define float @fdiv_poison_op1_upward(float %x) {
 
 define float @fdiv_poison_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @fdiv_poison_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -628,8 +596,7 @@ define float @frem_undef_op0_upward(float %x) {
 
 define float @frem_undef_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @frem_undef_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float undef, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float undef, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -638,7 +605,7 @@ define float @frem_undef_op0_defaultfp(float %x) {
 define float @frem_poison_op0_strict(float %x) {
 ; CHECK-LABEL: @frem_poison_op0_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -646,8 +613,7 @@ define float @frem_poison_op0_strict(float %x) {
 
 define float @frem_poison_op0_maytrap(float %x) {
 ; CHECK-LABEL: @frem_poison_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -655,8 +621,7 @@ define float @frem_poison_op0_maytrap(float %x) {
 
 define float @frem_poison_op0_upward(float %x) {
 ; CHECK-LABEL: @frem_poison_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -664,8 +629,7 @@ define float @frem_poison_op0_upward(float %x) {
 
 define float @frem_poison_op0_defaultfp(float %x) {
 ; CHECK-LABEL: @frem_poison_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -700,8 +664,7 @@ define float @frem_undef_op1_upward(float %x) {
 
 define float @frem_undef_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @frem_undef_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -710,7 +673,7 @@ define float @frem_undef_op1_defaultfp(float %x) {
 define float @frem_poison_op1_strict(float %x) {
 ; CHECK-LABEL: @frem_poison_op1_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -718,8 +681,7 @@ define float @frem_poison_op1_strict(float %x) {
 
 define float @frem_poison_op1_maytrap(float %x) {
 ; CHECK-LABEL: @frem_poison_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -727,8 +689,7 @@ define float @frem_poison_op1_maytrap(float %x) {
 
 define float @frem_poison_op1_upward(float %x) {
 ; CHECK-LABEL: @frem_poison_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -736,8 +697,7 @@ define float @frem_poison_op1_upward(float %x) {
 
 define float @frem_poison_op1_defaultfp(float %x) {
 ; CHECK-LABEL: @frem_poison_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -776,8 +736,7 @@ define float @fma_undef_op0_upward(float %x, float %y) {
 
 define float @fma_undef_op0_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_undef_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float undef, float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float undef, float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -786,7 +745,7 @@ define float @fma_undef_op0_defaultfp(float %x, float %y) {
 define float @fma_poison_op0_strict(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op0_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -794,8 +753,7 @@ define float @fma_poison_op0_strict(float %x, float %y) {
 
 define float @fma_poison_op0_maytrap(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op0_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -803,8 +761,7 @@ define float @fma_poison_op0_maytrap(float %x, float %y) {
 
 define float @fma_poison_op0_upward(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op0_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -812,8 +769,7 @@ define float @fma_poison_op0_upward(float %x, float %y) {
 
 define float @fma_poison_op0_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op0_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -848,8 +804,7 @@ define float @fma_undef_op1_upward(float %x, float %y) {
 
 define float @fma_undef_op1_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_undef_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float undef, float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float undef, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -858,7 +813,7 @@ define float @fma_undef_op1_defaultfp(float %x, float %y) {
 define float @fma_poison_op1_strict(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op1_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -866,8 +821,7 @@ define float @fma_poison_op1_strict(float %x, float %y) {
 
 define float @fma_poison_op1_maytrap(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op1_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -875,8 +829,7 @@ define float @fma_poison_op1_maytrap(float %x, float %y) {
 
 define float @fma_poison_op1_upward(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op1_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -884,8 +837,7 @@ define float @fma_poison_op1_upward(float %x, float %y) {
 
 define float @fma_poison_op1_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op1_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -920,8 +872,7 @@ define float @fma_undef_op2_upward(float %x, float %y) {
 
 define float @fma_undef_op2_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_undef_op2_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float undef, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -930,7 +881,7 @@ define float @fma_undef_op2_defaultfp(float %x, float %y) {
 define float @fma_poison_op2_strict(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op2_strict(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
   ret float %r
@@ -938,8 +889,7 @@ define float @fma_poison_op2_strict(float %x, float %y) {
 
 define float @fma_poison_op2_maytrap(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op2_maytrap(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
   ret float %r
@@ -947,8 +897,7 @@ define float @fma_poison_op2_maytrap(float %x, float %y) {
 
 define float @fma_poison_op2_upward(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op2_upward(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.upward", metadata !"fpexcept.ignore") #0
   ret float %r
@@ -956,8 +905,7 @@ define float @fma_poison_op2_upward(float %x, float %y) {
 
 define float @fma_poison_op2_defaultfp(float %x, float %y) {
 ; CHECK-LABEL: @fma_poison_op2_defaultfp(
-; CHECK-NEXT:    [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float poison
 ;
   %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
   ret float %r


        


More information about the llvm-commits mailing list