[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