diff --git a/llvm/include/llvm/Analysis/ConstantFolding.h b/llvm/include/llvm/Analysis/ConstantFolding.h
--- a/llvm/include/llvm/Analysis/ConstantFolding.h
+++ b/llvm/include/llvm/Analysis/ConstantFolding.h
@@ -19,6 +19,7 @@
 #ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H
 #define LLVM_ANALYSIS_CONSTANTFOLDING_H
 
+#include "llvm/ADT/APFloat.h"
 #include <stdint.h>
 
 namespace llvm {
@@ -26,6 +27,7 @@
 template <typename T> class ArrayRef;
 class CallBase;
 class Constant;
+class ConstantFP;
 class DSOLocalEquivalent;
 class DataLayout;
 class Function;
@@ -70,11 +72,12 @@
 /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
 /// instruction (icmp/fcmp) with the specified operands.  If it fails, it
 /// returns a constant expression of the specified operands.
-///
-Constant *
-ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
-                                Constant *RHS, const DataLayout &DL,
-                                const TargetLibraryInfo *TLI = nullptr);
+/// For fcmp, denormal constant input will be folded further according to the
+/// denormal handling mode.
+Constant *ConstantFoldCompareInstOperands(
+    unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL,
+    const TargetLibraryInfo *TLI = nullptr,
+    DenormalMode::DenormalModeKind Mode = DenormalMode::IEEE);
 
 /// Attempt to constant fold a unary operation with the specified
 /// operand. If it fails, it returns a constant expression of the specified
@@ -95,6 +98,10 @@
                                      Constant *RHS, const DataLayout &DL,
                                      const Instruction *I);
 
+/// Attempt to flush float point constant according to denormal mode.
+ConstantFP *FlushFPConstant(ConstantFP *Operand,
+                            DenormalMode::DenormalModeKind Mode);
+
 /// Attempt to constant fold a select instruction with the specified
 /// operands. The constant result is returned if successful; if not, null is
 /// returned.
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -16,7 +16,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -1184,9 +1183,16 @@
     Ops.push_back(Op);
   }
 
-  if (const auto *CI = dyn_cast<CmpInst>(I))
+  if (const auto *CI = dyn_cast<CmpInst>(I)) {
+    DenormalMode::DenormalModeKind Mode = DenormalMode::IEEE;
+    if (isa<ConstantFP>(I->getOperand(0)) && I->getParent())
+      Mode =
+          I->getFunction()
+              ->getDenormalMode(I->getOperand(0)->getType()->getFltSemantics())
+              .Input;
     return ConstantFoldCompareInstOperands(CI->getPredicate(), Ops[0], Ops[1],
-                                           DL, TLI);
+                                           DL, TLI, Mode);
+  }
 
   if (const auto *LI = dyn_cast<LoadInst>(I)) {
     if (LI->isVolatile())
@@ -1216,10 +1222,9 @@
   return ConstantFoldInstOperandsImpl(I, I->getOpcode(), Ops, DL, TLI);
 }
 
-Constant *llvm::ConstantFoldCompareInstOperands(unsigned IntPredicate,
-                                                Constant *Ops0, Constant *Ops1,
-                                                const DataLayout &DL,
-                                                const TargetLibraryInfo *TLI) {
+Constant *llvm::ConstantFoldCompareInstOperands(
+    unsigned IntPredicate, Constant *Ops0, Constant *Ops1, const DataLayout &DL,
+    const TargetLibraryInfo *TLI, DenormalMode::DenormalModeKind Mode) {
   CmpInst::Predicate Predicate = (CmpInst::Predicate)IntPredicate;
   // fold: icmp (inttoptr x), null         -> icmp x, 0
   // fold: icmp null, (inttoptr x)         -> icmp 0, x
@@ -1321,6 +1326,13 @@
     return ConstantFoldCompareInstOperands(Predicate, Ops1, Ops0, DL, TLI);
   }
 
+  // Flush any denormal constant float input according to denormal handling
+  // mode.
+  if (isa<ConstantFP>(Ops0))
+    Ops0 = FlushFPConstant(cast<ConstantFP>(Ops0), Mode);
+  if (isa<ConstantFP>(Ops1))
+    Ops1 = FlushFPConstant(cast<ConstantFP>(Ops1), Mode);
+
   return ConstantExpr::getCompare(Predicate, Ops0, Ops1);
 }
 
@@ -1343,40 +1355,31 @@
 }
 
 // Check whether a constant is a floating point denormal that should be flushed
-// to zero according to the denormal handling mode set in the function
-// attributes. If so, return a zero with the correct sign, otherwise return the
-// original constant. Inputs and outputs to floating point instructions can have
-// their mode set separately, so the direction is also needed.
-Constant *FlushFPConstant(Constant *Operand, const llvm::Function *F,
-                          bool IsOutput) {
-  if (F == nullptr)
+// to zero according to the denormal handling mode. If so, return a zero with
+// the correct sign, otherwise return the original constant.
+ConstantFP *llvm::FlushFPConstant(ConstantFP *Operand,
+                                  DenormalMode::DenormalModeKind Mode) {
+  const APFloat &APF = Operand->getValueAPF();
+  Type *Ty = Operand->getType();
+  switch (Mode) {
+  default:
+    llvm_unreachable("unknown denormal mode");
     return Operand;
-  if (auto *CFP = dyn_cast<ConstantFP>(Operand)) {
-    const APFloat &APF = CFP->getValueAPF();
-    Type *Ty = CFP->getType();
-    DenormalMode DenormMode = F->getDenormalMode(Ty->getFltSemantics());
-    DenormalMode::DenormalModeKind Mode =
-        IsOutput ? DenormMode.Output : DenormMode.Input;
-    switch (Mode) {
-    default:
-      llvm_unreachable("unknown denormal mode");
-      return Operand;
-    case DenormalMode::IEEE:
-      return Operand;
-    case DenormalMode::PreserveSign:
-      if (APF.isDenormal()) {
-        return ConstantFP::get(
-            Ty->getContext(),
-            APFloat::getZero(Ty->getFltSemantics(), APF.isNegative()));
-      }
-      return Operand;
-    case DenormalMode::PositiveZero:
-      if (APF.isDenormal()) {
-        return ConstantFP::get(Ty->getContext(),
-                               APFloat::getZero(Ty->getFltSemantics(), false));
-      }
-      return Operand;
+  case DenormalMode::IEEE:
+    return Operand;
+  case DenormalMode::PreserveSign:
+    if (APF.isDenormal()) {
+      return ConstantFP::get(
+          Ty->getContext(),
+          APFloat::getZero(Ty->getFltSemantics(), APF.isNegative()));
     }
+    return Operand;
+  case DenormalMode::PositiveZero:
+    if (APF.isDenormal()) {
+      return ConstantFP::get(Ty->getContext(),
+                             APFloat::getZero(Ty->getFltSemantics(), false));
+    }
+    return Operand;
   }
   return Operand;
 }
@@ -1387,10 +1390,27 @@
   if (auto *BB = I->getParent()) {
     if (auto *F = BB->getParent()) {
       if (Instruction::isBinaryOp(Opcode)) {
-        Constant *Op0 = FlushFPConstant(LHS, F, false);
-        Constant *Op1 = FlushFPConstant(RHS, F, false);
+        Constant *Op0 =
+            isa<ConstantFP>(LHS)
+                ? FlushFPConstant(
+                      cast<ConstantFP>(LHS),
+                      F->getDenormalMode(LHS->getType()->getFltSemantics())
+                          .Input)
+                : LHS;
+        Constant *Op1 =
+            isa<ConstantFP>(RHS)
+                ? FlushFPConstant(
+                      cast<ConstantFP>(RHS),
+                      F->getDenormalMode(RHS->getType()->getFltSemantics())
+                          .Input)
+                : RHS;
         Constant *C = ConstantFoldBinaryOpOperands(Opcode, Op0, Op1, DL);
-        return FlushFPConstant(C, F, true);
+        return isa<ConstantFP>(C)
+                   ? FlushFPConstant(
+                         cast<ConstantFP>(C),
+                         F->getDenormalMode(C->getType()->getFltSemantics())
+                             .Output)
+                   : C;
       }
     }
   }
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3899,8 +3899,14 @@
   assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!");
 
   if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
-    if (Constant *CRHS = dyn_cast<Constant>(RHS))
-      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, Q.DL, Q.TLI);
+    if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
+      DenormalMode::DenormalModeKind Mode = DenormalMode::IEEE;
+      if (isa<ConstantFP>(LHS) && Q.CxtI && Q.CxtI->getParent())
+        Mode = Q.CxtI->getFunction()->getDenormalMode(
+            LHS->getType()->getFltSemantics()).Input;
+      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, Q.DL, Q.TLI,
+                                             Mode);
+    }
 
     // If we have a constant, make sure it is on the RHS.
     std::swap(LHS, RHS);
@@ -4209,9 +4215,15 @@
   if (!AllowRefinement && canCreatePoison(cast<Operator>(I)))
     return nullptr;
 
-  if (CmpInst *C = dyn_cast<CmpInst>(I))
+  if (CmpInst *C = dyn_cast<CmpInst>(I)) {
+    DenormalMode::DenormalModeKind Mode = DenormalMode::IEEE;
+    if (isa<ConstantFP>(ConstOps[0]) && C->getParent())
+      Mode = C->getFunction()
+                 ->getDenormalMode(ConstOps[0]->getType()->getFltSemantics())
+                 .Input;
     return ConstantFoldCompareInstOperands(C->getPredicate(), ConstOps[0],
-                                           ConstOps[1], Q.DL, Q.TLI);
+                                           ConstOps[1], Q.DL, Q.TLI, Mode);
+  }
 
   if (LoadInst *LI = dyn_cast<LoadInst>(I))
     if (!LI->isVolatile())
diff --git a/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll b/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
--- a/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
+++ b/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
@@ -763,7 +763,7 @@
 define i1 @fcmp_double_positive_zero() #6 {
 ; CHECK-LABEL: @fcmp_double_positive_zero(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0, 0x8000000000000
@@ -773,7 +773,7 @@
 define i1 @fcmp_float_positive_zero() #6 {
 ; CHECK-LABEL: @fcmp_float_positive_zero(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0, 0x8000000000000