[llvm] 758de0e - [InstructionSimplify] handle denormal input for fcmp

Chen Zheng via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 1 01:07:06 PDT 2022


Author: Chen Zheng
Date: 2022-07-01T03:51:28-04:00
New Revision: 758de0e931f47f5953738c6c8c102df1ce72778b

URL: https://github.com/llvm/llvm-project/commit/758de0e931f47f5953738c6c8c102df1ce72778b
DIFF: https://github.com/llvm/llvm-project/commit/758de0e931f47f5953738c6c8c102df1ce72778b.diff

LOG: [InstructionSimplify] handle denormal input for fcmp

Handle denormal constant input for fcmp instructions based on the
denormal handling mode.

Reviewed By: spatel, dcandler

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

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ConstantFolding.h
    llvm/lib/Analysis/ConstantFolding.cpp
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ConstantFolding.h b/llvm/include/llvm/Analysis/ConstantFolding.h
index 4a2bd2945b5a2..23ec7d6b70ec4 100644
--- a/llvm/include/llvm/Analysis/ConstantFolding.h
+++ b/llvm/include/llvm/Analysis/ConstantFolding.h
@@ -67,14 +67,13 @@ Constant *ConstantFoldInstOperands(Instruction *I, ArrayRef<Constant *> Ops,
                                    const DataLayout &DL,
                                    const TargetLibraryInfo *TLI = nullptr);
 
-/// 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);
+/// 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.
+/// Denormal inputs may be flushed based on the denormal handling mode.
+Constant *ConstantFoldCompareInstOperands(
+    unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL,
+    const TargetLibraryInfo *TLI = nullptr, const Instruction *I = nullptr);
 
 /// Attempt to constant fold a unary operation with the specified
 /// operand. If it fails, it returns a constant expression of the specified
@@ -95,6 +94,14 @@ Constant *ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS,
                                      Constant *RHS, const DataLayout &DL,
                                      const Instruction *I);
 
+/// Attempt to flush float point constant according to denormal mode set in the
+/// instruction's parent 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 Instruction *I,
+                          bool IsOutput);
+
 /// 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
index b2b071cc662e0..a810418450520 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1071,9 +1071,11 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
   switch (Opcode) {
   default: return nullptr;
   case Instruction::ICmp:
-  case Instruction::FCmp:
-    return ConstantFoldCompareInstOperands(
-        cast<CmpInst>(InstOrCE)->getPredicate(), Ops[0], Ops[1], DL, TLI);
+  case Instruction::FCmp: {
+    auto *C = cast<CmpInst>(InstOrCE);
+    return ConstantFoldCompareInstOperands(C->getPredicate(), Ops[0], Ops[1],
+                                           DL, TLI, C);
+  }
   case Instruction::Freeze:
     return isGuaranteedNotToBeUndefOrPoison(Ops[0]) ? Ops[0] : nullptr;
   case Instruction::Call:
@@ -1210,10 +1212,9 @@ Constant *llvm::ConstantFoldInstOperands(Instruction *I,
   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, const Instruction *I) {
   CmpInst::Predicate Predicate = (CmpInst::Predicate)IntPredicate;
   // fold: icmp (inttoptr x), null         -> icmp x, 0
   // fold: icmp null, (inttoptr x)         -> icmp 0, x
@@ -1315,6 +1316,11 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned IntPredicate,
     return ConstantFoldCompareInstOperands(Predicate, Ops1, Ops0, DL, TLI);
   }
 
+  // Flush any denormal constant float input according to denormal handling
+  // mode.
+  Ops0 = FlushFPConstant(Ops0, I, /* IsOutput */ false);
+  Ops1 = FlushFPConstant(Ops1, I, /* IsOutput */ false);
+
   return ConstantExpr::getCompare(Predicate, Ops0, Ops1);
 }
 
@@ -1336,41 +1342,40 @@ Constant *llvm::ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
   return ConstantExpr::get(Opcode, LHS, RHS);
 }
 
-// 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)
+Constant *llvm::FlushFPConstant(Constant *Operand, const Instruction *I,
+                                bool IsOutput) {
+  if (!I || !I->getParent() || !I->getFunction())
     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;
+
+  ConstantFP *CFP = dyn_cast<ConstantFP>(Operand);
+  if (!CFP)
+    return Operand;
+
+  const APFloat &APF = CFP->getValueAPF();
+  Type *Ty = CFP->getType();
+  DenormalMode DenormMode =
+      I->getFunction()->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;
   }
   return Operand;
 }
@@ -1378,15 +1383,16 @@ Constant *FlushFPConstant(Constant *Operand, const llvm::Function *F,
 Constant *llvm::ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS,
                                            Constant *RHS, const DataLayout &DL,
                                            const Instruction *I) {
-  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 *C = ConstantFoldBinaryOpOperands(Opcode, Op0, Op1, DL);
-        return FlushFPConstant(C, F, true);
-      }
-    }
+  if (Instruction::isBinaryOp(Opcode)) {
+    // Flush denormal inputs if needed.
+    Constant *Op0 = FlushFPConstant(LHS, I, /* IsOutput */ false);
+    Constant *Op1 = FlushFPConstant(RHS, I, /* IsOutput */ false);
+
+    // Calculate constant result.
+    Constant *C = ConstantFoldBinaryOpOperands(Opcode, Op0, Op1, DL);
+
+    // Flush denormal output if needed.
+    return FlushFPConstant(C, I, /* IsOutput */ true);
   }
   // If instruction lacks a parent/function and the denormal mode cannot be
   // determined, use the default (IEEE).

diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index f8a6624c76054..013e4d6489fa8 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3900,7 +3900,8 @@ static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
 
   if (Constant *CLHS = dyn_cast<Constant>(LHS)) {
     if (Constant *CRHS = dyn_cast<Constant>(RHS))
-      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, Q.DL, Q.TLI);
+      return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, Q.DL, Q.TLI,
+                                             Q.CxtI);
 
     // If we have a constant, make sure it is on the RHS.
     std::swap(LHS, RHS);

diff  --git a/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll b/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
index 5d57e9f399c95..b973c9b4ecac1 100644
--- a/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
+++ b/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
@@ -763,7 +763,7 @@ entry:
 define i1 @fcmp_double_pz_in_pz_out() #6 {
 ; CHECK-LABEL: @fcmp_double_pz_in_pz_out(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0008000000000000, 0x0
@@ -773,7 +773,7 @@ entry:
 define i1 @fcmp_float_pz_in_pz_out() #6 {
 ; CHECK-LABEL: @fcmp_float_pz_in_pz_out(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une float 0x3800000000000000, 0x0
@@ -783,7 +783,7 @@ entry:
 define i1 @fcmp_double_ps_in_ps_out() #7 {
 ; CHECK-LABEL: @fcmp_double_ps_in_ps_out(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0008000000000000, 0x0
@@ -793,7 +793,7 @@ entry:
 define i1 @fcmp_float_ps_in_ps_out() #7 {
 ; CHECK-LABEL: @fcmp_float_ps_in_ps_out(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une float 0x3800000000000000, 0x0
@@ -823,7 +823,7 @@ entry:
 define i1 @fcmp_double_ieee_out_pz_in() #3 {
 ; CHECK-LABEL: @fcmp_double_ieee_out_pz_in(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0008000000000000, 0x0
@@ -833,7 +833,7 @@ entry:
 define i1 @fcmp_double_ieee_out_ps_in() #4 {
 ; CHECK-LABEL: @fcmp_double_ieee_out_ps_in(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0008000000000000, 0x0
@@ -853,7 +853,7 @@ entry:
 define i1 @fcmp_double_two_denormal_ins() #6 {
 ; CHECK-LABEL: @fcmp_double_two_denormal_ins(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp une double 0x0008100000000000, 0x0008000000000000
@@ -903,7 +903,7 @@ entry:
 define i1 @fcmp_double_ps_in_ps_out_oeq() #6 {
 ; CHECK-LABEL: @fcmp_double_ps_in_ps_out_oeq(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %cmp = fcmp oeq double 0x0008100000000000, 0x0008000000000000
@@ -923,7 +923,7 @@ entry:
 define i1 @fcmp_double_ps_in_ps_out_one() #6 {
 ; CHECK-LABEL: @fcmp_double_ps_in_ps_out_one(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp one double 0x0008100000000000, 0x0008000000000000
@@ -983,7 +983,7 @@ entry:
 define i1 @fcmp_double_pz_in_pz_out_ugt() #7 {
 ; CHECK-LABEL: @fcmp_double_pz_in_pz_out_ugt(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %cmp = fcmp ugt double 0x0008000000000000, 0x0
@@ -1043,7 +1043,7 @@ entry:
 define i1 @fcmp_double_pz_in_pz_out_ule() #7 {
 ; CHECK-LABEL: @fcmp_double_pz_in_pz_out_ule(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %cmp = fcmp ule double 0x0008000000000000, 0x0


        


More information about the llvm-commits mailing list