[llvm] 351a1bb - [InstCombine] Do not perform fcmp -> icmp transformation if denormal inputs may be flushed (#181899)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 20 02:51:58 PST 2026


Author: Justin Holewinski
Date: 2026-02-20T11:51:54+01:00
New Revision: 351a1bb0c525ef9e7e7e90ec37ddb2f94ef88a2b

URL: https://github.com/llvm/llvm-project/commit/351a1bb0c525ef9e7e7e90ec37ddb2f94ef88a2b
DIFF: https://github.com/llvm/llvm-project/commit/351a1bb0c525ef9e7e7e90ec37ddb2f94ef88a2b.diff

LOG: [InstCombine] Do not perform fcmp -> icmp transformation if denormal inputs may be flushed (#181899)

Commit 4827771234276 added the following transformation:

  fcmp oeq/une (bitcast X), 0.0 --> (and X, SignMaskC) ==/!= 0

This transformation is only valid if denormal inputs are preserved. If
they are flushed, the two comparisons can return different results.

---------

Co-authored-by: Justin Holewinski <jholewinski at nvidia.com>

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/fcmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index bce609275ffa9..ec6ac25bb8b9c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -8905,7 +8905,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
   // Ignore signbit of bitcasted int when comparing equality to FP 0.0:
   // fcmp oeq/une (bitcast X), 0.0 --> (and X, SignMaskC) ==/!= 0
   if (match(Op1, m_PosZeroFP()) &&
-      match(Op0, m_OneUse(m_ElementWiseBitCast(m_Value(X))))) {
+      match(Op0, m_OneUse(m_ElementWiseBitCast(m_Value(X)))) &&
+      !F.getDenormalMode(Op1->getType()->getScalarType()->getFltSemantics())
+           .inputsMayBeZero()) {
     ICmpInst::Predicate IntPred = ICmpInst::BAD_ICMP_PREDICATE;
     if (Pred == FCmpInst::FCMP_OEQ)
       IntPred = ICmpInst::ICMP_EQ;

diff  --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index 61490d120c81c..f3e242fb1b1eb 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -1285,6 +1285,58 @@ define <1 x i1> @bitcast_1vec_eq0(i32 %x) {
   ret <1 x i1> %cmp
 }
 
+; negative test - denormal inputs flushed to zero (positivezero)
+
+define i1 @bitcast_eq0_denorm_positivezero_input(i32 %x) denormal_fpenv(positivezero) {
+; CHECK-LABEL: @bitcast_eq0_denorm_positivezero_input(
+; CHECK-NEXT:    [[F:%.*]] = bitcast i32 [[X:%.*]] to float
+; CHECK-NEXT:    [[R:%.*]] = fcmp oeq float [[F]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %f = bitcast i32 %x to float
+  %r = fcmp oeq float %f, 0.0
+  ret i1 %r
+}
+
+; negative test - denormal inputs flushed to zero (positivezero), outputs are not (ieee)
+
+define i1 @bitcast_eq0_denorm_positivezero_input_ieee_output(i32 %x) denormal_fpenv(ieee|positivezero) {
+; CHECK-LABEL: @bitcast_eq0_denorm_positivezero_input_ieee_output(
+; CHECK-NEXT:    [[F:%.*]] = bitcast i32 [[X:%.*]] to float
+; CHECK-NEXT:    [[R:%.*]] = fcmp oeq float [[F]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %f = bitcast i32 %x to float
+  %r = fcmp oeq float %f, 0.0
+  ret i1 %r
+}
+
+; negative test - denormal inputs flushed to zero (preservesign)
+
+define <2 x i1> @bitcast_ne0_denorm_preservesign_input(<2 x i32> %x) denormal_fpenv(preservesign) {
+; CHECK-LABEL: @bitcast_ne0_denorm_preservesign_input(
+; CHECK-NEXT:    [[F:%.*]] = bitcast <2 x i32> [[X:%.*]] to <2 x float>
+; CHECK-NEXT:    [[R:%.*]] = fcmp une <2 x float> [[F]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %f = bitcast <2 x i32> %x to <2 x float>
+  %r = fcmp une <2 x float> %f, zeroinitializer
+  ret <2 x i1> %r
+}
+
+; negative test - denormal inputs flushed to zero (dynamic)
+
+define <2 x i1> @bitcast_ne0_denorm_dynamic_input(<2 x i32> %x) denormal_fpenv(dynamic) {
+; CHECK-LABEL: @bitcast_ne0_denorm_dynamic_input(
+; CHECK-NEXT:    [[F:%.*]] = bitcast <2 x i32> [[X:%.*]] to <2 x float>
+; CHECK-NEXT:    [[R:%.*]] = fcmp une <2 x float> [[F]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %f = bitcast <2 x i32> %x to <2 x float>
+  %r = fcmp une <2 x float> %f, zeroinitializer
+  ret <2 x i1> %r
+}
+
 ; Simplify fcmp (x + 0.0), y => fcmp x, y
 
 define i1 @fcmp_fadd_zero_ugt(float %x, float %y) {


        


More information about the llvm-commits mailing list