[llvm] 08a58b2 - [InstCombine] Optimize redundant floating point comparisons in `or`/`and` inst's (#158097)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 16 08:22:15 PDT 2025


Author: Rajveer Singh Bharadwaj
Date: 2025-09-16T20:52:11+05:30
New Revision: 08a58b2cea3c11cb94b565e50a85de4d7b78fe65

URL: https://github.com/llvm/llvm-project/commit/08a58b2cea3c11cb94b565e50a85de4d7b78fe65
DIFF: https://github.com/llvm/llvm-project/commit/08a58b2cea3c11cb94b565e50a85de4d7b78fe65.diff

LOG: [InstCombine] Optimize redundant floating point comparisons in `or`/`and` inst's (#158097)

Resolves #157371

We can eliminate one of the `fcmp` when we have two same `olt` or `ogt`
instructions matched in `or`/`and` simplification.

Added: 
    llvm/test/Transforms/InstCombine/redundant-fcmp.ll

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 7bff13d59528c..100fa428cb842 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1850,6 +1850,35 @@ static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
                  : ConstantInt::getBool(LHS->getType(), !IsAnd);
   }
 
+  Value *V0;
+  const APFloat *V0Op1, *V1Op1;
+  // (fcmp olt V0, V0Op1) || (fcmp olt V0, V1Op1)
+  //                      --> fcmp olt V0, max(V0Op1, V1Op1)
+  // (fcmp ogt V0, V0Op1) || (fcmp ogt V0, V1Op1)
+  //                      --> fcmp ogt V0, max(V0Op1, V1Op1)
+  //
+  // (fcmp olt V0, V0Op1) && (fcmp olt V0, V1Op1)
+  //                      --> fcmp olt V0, min(V0Op1, V1Op1)
+  // (fcmp ogt V0, V0Op1) && (fcmp ogt V0, V1Op1)
+  //                      --> fcmp ogt V0, min(V0Op1, V1Op1)
+  if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Value(V0),
+                                m_APFloat(V0Op1))) &&
+      match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Specific(V0),
+                                m_APFloat(V1Op1)))) {
+    if (*V0Op1 > *V1Op1)
+      return IsAnd ? RHS : LHS;
+    if (*V1Op1 > *V0Op1)
+      return IsAnd ? LHS : RHS;
+  } else if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Value(V0),
+                                       m_APFloat(V0Op1))) &&
+             match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Specific(V0),
+                                       m_APFloat(V1Op1)))) {
+    if (*V0Op1 < *V1Op1)
+      return IsAnd ? RHS : LHS;
+    if (*V1Op1 < *V0Op1)
+      return IsAnd ? LHS : RHS;
+  }
+
   return nullptr;
 }
 

diff  --git a/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll b/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll
index 3059b5b445958..f76c68919d8e1 100644
--- a/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll
+++ b/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll
@@ -5,10 +5,7 @@
 define amdgpu_ps float @xor3_i1_const(float inreg %arg1, i32 inreg %arg2) {
 ; GCN-LABEL: xor3_i1_const:
 ; GCN:       ; %bb.0: ; %main_body
-; GCN-NEXT:    v_mov_b32_e32 v0, 0x42640000
-; GCN-NEXT:    v_cmp_lt_f32_e64 s[2:3], s0, 0
-; GCN-NEXT:    v_cmp_lt_f32_e32 vcc, s0, v0
-; GCN-NEXT:    s_and_b64 s[0:1], s[2:3], vcc
+; GCN-NEXT:    v_cmp_lt_f32_e64 s[0:1], s0, 0
 ; GCN-NEXT:    v_cndmask_b32_e64 v0, 1.0, 0, s[0:1]
 ; GCN-NEXT:    ; return to shader part epilog
 main_body:

diff  --git a/llvm/test/Transforms/InstCombine/redundant-fcmp.ll b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
new file mode 100644
index 0000000000000..0f5fe9fb9a1b2
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
@@ -0,0 +1,186 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @or_fcmp_redundant_or1(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or1(
+; CHECK-NEXT:    [[V2:%.*]] = fcmp olt double [[V0:%.*]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v1 = fcmp olt double %v0, 1.000000e-02
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_or2(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or2(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp olt double [[V0:%.*]], 2.300000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v1 = fcmp olt double %v0, 2.300000e+00
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_or3(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or3(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v1 = fcmp ogt double %v0, 1.000000e-02
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_or4(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or4(
+; CHECK-NEXT:    [[V2:%.*]] = fcmp ogt double [[V0:%.*]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v1 = fcmp ogt double %v0, 2.300000e+00
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_or_neg1(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or_neg1(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    [[V2:%.*]] = fcmp ogt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = or i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V3]]
+;
+  %v1 = fcmp olt double %v0, 1.000000e-02
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_or_neg2(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_or_neg2(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    [[V2:%.*]] = fcmp olt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = or i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V3]]
+;
+  %v1 = fcmp ogt double %v0, 1.000000e-02
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_and1(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and1(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v1 = fcmp olt double %v0, 1.000000e-02
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = and i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_and2(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and2(
+; CHECK-NEXT:    [[V2:%.*]] = fcmp olt double [[V0:%.*]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v1 = fcmp olt double %v0, 2.300000e+00
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = and i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_and3(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and3(
+; CHECK-NEXT:    [[V2:%.*]] = fcmp ogt double [[V0:%.*]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v1 = fcmp ogt double %v0, 1.000000e-02
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = and i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_and4(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and4(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 2.300000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v1 = fcmp ogt double %v0, 2.300000e+00
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = and i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_and_neg1(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and_neg1(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    [[V2:%.*]] = fcmp ogt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = and i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V3]]
+;
+  %v1 = fcmp olt double %v0, 1.000000e-02
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = and i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_and_neg2(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_and_neg2(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    [[V2:%.*]] = fcmp olt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = and i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V3]]
+;
+  %v1 = fcmp ogt double %v0, 1.000000e-02
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = and i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_select_or1(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_select_or1(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v1 = fcmp olt double %v0, 1.000000e-02
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = select i1 %v1, i1 %v2, i1 false
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_select_or2(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_select_or2(
+; CHECK-NEXT:    [[V2:%.*]] = fcmp ogt double [[V0:%.*]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v1 = fcmp ogt double %v0, 1.000000e-02
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = select i1 %v1, i1 %v2, i1 false
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_select_and1(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_select_and1(
+; CHECK-NEXT:    [[V2:%.*]] = fcmp olt double [[V0:%.*]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v1 = fcmp olt double %v0, 1.000000e-02
+  %v2 = fcmp olt double %v0, 1.990000e+00
+  %v3 = select i1 %v1, i1 true, i1 %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant_select_and2(double %v0) {
+; CHECK-LABEL: @or_fcmp_redundant_select_and2(
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v1 = fcmp ogt double %v0, 1.000000e-02
+  %v2 = fcmp ogt double %v0, 1.990000e+00
+  %v3 = select i1 %v1, i1 true, i1 %v2
+  ret i1 %v3
+}


        


More information about the llvm-commits mailing list