[llvm] [InstCombine] Optimize FCmp with FMul operands (PR #186707)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Mar 15 14:41:42 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nalin Gabriel (nalin1o1)
<details>
<summary>Changes</summary>
Fcmp
Fixes llvm#<!-- -->186553
In situations where one of the operands of the FCmp Instruction is zero and the other operand is the result of a FMul operation with a Constant and a variable it is valid to Optimize out the constant when:
it is Non NaN and Non Zero if predicate for the fcmp instruction is EQ or NEQ (Ordered or Unordered).
it is Non NaN, Non Zero and Non Negative if the predicate for the fcmp instruction is Relational (OGT,OLT etc.)
---
Full diff: https://github.com/llvm/llvm-project/pull/186707.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+79)
- (modified) llvm/test/Transforms/InstCombine/fcmp.ll (+32)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index dc860700db91b..b41f8889e7bf8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -955,6 +955,85 @@ Instruction *InstCombinerImpl::foldICmpAddOpConst(Value *X, const APInt &C,
ConstantInt::get(X->getType(), SMax - (C - 1)));
}
+static Instruction* foldFCmpMulConst(FCmpInst &I)
+{
+ //Handling the pattern fcmp pred (fmul X, imm), 0.0.
+ auto Op0 = I.getOperand(0);
+ auto Op1 = I.getOperand(1);
+ auto Pred = I.getPredicate();
+ Value* FMulOperand1;
+ Constant* ImmediateValue;
+ /// fcmp(fmul(X,Immediate(Float), 0.0)) to fcmp(X,0.0)
+ if((match(Op0,m_c_FMul(m_Value(FMulOperand1),m_ImmConstant(ImmediateValue))) &&
+ match(Op1,m_AnyZeroFP())))
+ {
+ ConstantFP* CastedValue = dyn_cast<ConstantFP>(ImmediateValue);
+ if(CastedValue == nullptr)
+ {
+ return(nullptr);
+ }
+ if(CmpInst::isEquality(Pred))
+ {
+ if(((!CastedValue->isZero()) && (!ImmediateValue->isNaN())))
+ {
+ replaceOperand(I,0,FMulOperand1);
+ replaceOperand(I,1,ConstantFP::getZero(FMulOperand1->getType()));
+ return(&I);
+ }
+ return(nullptr);
+ }
+ else if(CmpInst::isRelational(Pred))
+ {
+ if( (!CastedValue->isZero()) && (!ImmediateValue->isNaN()) && (!CastedValue->isNegative()))
+ {
+ replaceOperand(I,0,FMulOperand1);
+ replaceOperand(I,1,ConstantFP::getZero(FMulOperand1->getType()));
+ return(&I);
+ }
+ return(nullptr);
+ }
+
+ }
+ /// fcmp(0.0,fmul(X,Immediate(Float)) to fcmp(0.0,X)
+ else if((match(Op1,m_c_FMul(m_Value(FMulOperand1),m_ImmConstant(ImmediateValue))) &&
+ match(Op0,m_AnyZeroFP())))
+ {
+ ConstantFP* CastedValue = dyn_cast<ConstantFP>(ImmediateValue);
+ if(CastedValue == nullptr)
+ {
+ return(nullptr);
+ }
+ if(CmpInst::isEquality(Pred))
+ {
+ if(((!CastedValue->isZero()) && (!ImmediateValue->isNaN())))
+ {
+ replaceOperand(I,0,FMulOperand1);
+ replaceOperand(I,1,ConstantFP::getZero(FMulOperand1->getType()));
+ Pred = CmpInst::getInversePredicate(Pred);
+ I.setPredicate(Pred);
+ return(&I);
+ }
+ return(nullptr);
+ }
+ else if(CmpInst::isRelational(Pred))
+ {
+ if( (!CastedValue->isZero()) && (!ImmediateValue->isNaN()) && (!CastedValue->isNegative()))
+ {
+ replaceOperand(I,0,FMulOperand1);
+ replaceOperand(I,1,ConstantFP::getZero(FMulOperand1->getType()));
+ Pred = CmpInst::getInversePredicate(Pred);
+ I.setPredicate(Pred);
+ return(&I);
+ }
+ return(nullptr);
+ }
+ }
+ else
+ {
+ return(nullptr);
+ }
+}
+
/// Handle "(icmp eq/ne (ashr/lshr AP2, A), AP1)" ->
/// (icmp eq/ne A, Log2(AP2/AP1)) ->
/// (icmp eq/ne A, Log2(AP2) - Log2(AP1)).
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll
index f3e242fb1b1eb..5828cebe9e02b 100644
--- a/llvm/test/Transforms/InstCombine/fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp.ll
@@ -736,6 +736,38 @@ define i1 @is_signbit_set_simplify_nan(double %x) {
ret i1 %r
}
+define i1 @fcmp_if_constant_nonzero_test1(float %x) {
+; CHECK-LABEL: @fcmp_if_constant_nonzero_test1 (
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT: ret i1 true
+;
+ %mul = fmul float %x, 4.000000e+00
+ %cmp = fcmp ogt float %mul, 0.000000e+00
+ ret i1 %cmp
+}
+
+define i1 @fcmp_if_constant_nonzero_test2(float %x) {
+; CHECK-LABEL: @fcmp_if_constant_nonzero_test2
+; CHECK-NEXT: [[MUL:%.*]] = fmul float %x,-6.0
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[MUL]],0.000000e+00
+; CHECK-NEXT: ret i1 true
+;
+ %mul = fmul float %x, -6.000000e+00
+ %cmp = fcmp ogt float 0.000000e+00, %mul
+ ret i1 %cmp
+}
+
+define i1 @fcmp_if_constant_negzero_test3(float %x) {
+; CHECK-LABEL: fcmp_if_constant_negzero_test3
+; CHECK-NEXT: [[MUL:%.*]] = fmul float %x,-0.0
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[MUL]],0.000000e+00
+; CHECK-NEXT: ret i1 false
+;
+ %mul = fmul float %x, -0.0
+ %cmp = fcmp ogt float 0.000000e+00, %mul
+ ret i1 %cmp
+}
+
define <2 x i1> @lossy_oeq(<2 x float> %x) {
; CHECK-LABEL: @lossy_oeq(
; CHECK-NEXT: ret <2 x i1> zeroinitializer
``````````
</details>
https://github.com/llvm/llvm-project/pull/186707
More information about the llvm-commits
mailing list