Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

Rajveer100
Copy link
Member

@Rajveer100 Rajveer100 commented Sep 11, 2025

Resolves #157371

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

@Rajveer100 Rajveer100 requested a review from dtcxzyw September 11, 2025 15:26
@Rajveer100 Rajveer100 requested a review from nikic as a code owner September 11, 2025 15:26
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Sep 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2025

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Rajveer Singh Bharadwaj (Rajveer100)

Changes

Resolves #157371

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


Full diff: https://github.com/llvm/llvm-project/pull/158097.diff

3 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+24)
  • (modified) llvm/test/Transforms/InstCombine/or-fcmp.ll (+60)
  • (added) llvm/test/Transforms/InstCombine/redundant-fcmp.ll (+54)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 6e46898634070..0719932e1394d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4514,6 +4514,30 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
     if (Value *V = SimplifyAddWithRemainder(I))
       return replaceInstUsesWith(I, V);
 
+  Value *V0, *V1;
+  const APFloat *V0Op1, *V1Op1;
+  if (match(Op0, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Value(V0),
+                                m_APFloat(V0Op1))) &&
+      match(Op1, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Value(V1),
+                                m_APFloat(V1Op1)))) {
+    if (V0 == V1) {
+      if (V0Op1 > V1Op1)
+        replaceInstUsesWith(I, Op0);
+      else if (V1Op1 > V0Op1)
+        replaceInstUsesWith(I, Op1);
+    }
+  } else if (match(Op0, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Value(V0),
+                                m_APFloat(V0Op1))) &&
+      match(Op1, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Value(V1),
+                                m_APFloat(V1Op1)))) {
+    if (V0 == V1) {
+      if (V0Op1 < V1Op1)
+        replaceInstUsesWith(I, Op1);
+      else if (V1Op1 < V0Op1)
+        replaceInstUsesWith(I, Op0);
+    }
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/or-fcmp.ll b/llvm/test/Transforms/InstCombine/or-fcmp.ll
index 193fe4b5cc722..926f66f622914 100644
--- a/llvm/test/Transforms/InstCombine/or-fcmp.ll
+++ b/llvm/test/Transforms/InstCombine/or-fcmp.ll
@@ -4657,3 +4657,63 @@ define i1 @or_fcmp_reassoc4(i1 %x, double %a, double %b) {
   %retval = or i1 %cmp1, %or
   ret i1 %retval
 }
+
+define i1 @or_fcmp_redundant1(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant1(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = fcmp nsz olt double [[V0]], 1.000000e-02
+; CHECK-NEXT:    [[V2:%.*]] = fcmp nsz olt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = or i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz olt double %v0, 1.000000e-02
+  %v2 = fcmp nsz olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant2(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant2(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = fcmp nsz olt double [[V0]], 2.300000e+00
+; CHECK-NEXT:    [[V2:%.*]] = fcmp nsz olt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = or i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz olt double %v0, 2.300000e+00
+  %v2 = fcmp nsz olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant3(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant3(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = fcmp nsz ogt double [[V0]], 1.000000e-02
+; CHECK-NEXT:    [[V2:%.*]] = fcmp nsz olt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = or i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V3]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz ogt double %v0, 1.000000e-02
+  %v2 = fcmp nsz olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant4(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant4(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = fcmp nsz ogt double [[V0]], 2.300000e+00
+; CHECK-NEXT:    [[V2:%.*]] = fcmp nsz ogt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    [[V3:%.*]] = or i1 [[V1]], [[V2]]
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz ogt double %v0, 2.300000e+00
+  %v2 = fcmp nsz ogt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
diff --git a/llvm/test/Transforms/InstCombine/redundant-fcmp.ll b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
new file mode 100644
index 0000000000000..934d9e6c46507
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll
@@ -0,0 +1,54 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -O3 -S | FileCheck %s
+
+define i1 @or_fcmp_redundant1(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant1(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V2:%.*]] = fcmp nsz olt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V2]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz olt double %v0, 1.000000e-02
+  %v2 = fcmp nsz olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant2(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant2(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = fcmp nsz olt double [[V0]], 2.300000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz olt double %v0, 2.300000e+00
+  %v2 = fcmp nsz olt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant3(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant3(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V3:%.*]] = fcmp nsz ogt double [[V0]], 1.990000e+00
+; CHECK-NEXT:    ret i1 [[V3]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz ogt double %v0, 1.000000e-02
+  %v2 = fcmp nsz ogt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}
+
+define i1 @or_fcmp_redundant4(ptr %arg0) {
+; CHECK-LABEL: @or_fcmp_redundant4(
+; CHECK-NEXT:    [[V0:%.*]] = load double, ptr [[ARG0:%.*]], align 8
+; CHECK-NEXT:    [[V1:%.*]] = fcmp nsz ogt double [[V0]], 2.300000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = load double, ptr %arg0, align 8
+  %v1 = fcmp nsz ogt double %v0, 2.300000e+00
+  %v2 = fcmp nsz ogt double %v0, 1.990000e+00
+  %v3 = or i1 %v1, %v2
+  ret i1 %v3
+}

@Rajveer100 Rajveer100 added the floating-point Floating-point math label Sep 11, 2025
@dtcxzyw
Copy link
Member

dtcxzyw commented Sep 11, 2025

@zyw-bot mfuzz

@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Sep 13, 2025
@Rajveer100 Rajveer100 requested a review from dtcxzyw September 13, 2025 08:20
Copy link
Member

@XChy XChy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check !isAnd if you only fold the pattern or(fcmp, fcmp).

@XChy
Copy link
Member

XChy commented Sep 13, 2025

General proof: proof

@Rajveer100
Copy link
Member Author

Should check !isAnd if you only fold the pattern or(fcmp, fcmp).

Yeah, for the and case we just return the other op.

@Rajveer100 Rajveer100 requested a review from XChy September 13, 2025 11:21
@Rajveer100 Rajveer100 changed the title [InstCombine] Optimize redundant floating point comparisons in or inst [InstCombine] Optimize redundant floating point comparisons in or/and inst's Sep 13, 2025
Copy link

github-actions bot commented Sep 13, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

…and` inst's

Resolves llvm#157371

We can eliminate one of the `fcmp` when we have two same `olt` or `ogt`
instructions matched in `or`/`and` simplification.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
floating-point Floating-point math llvm:analysis Includes value tracking, cost tables and constant folding llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missed Optimization: redundant floating-point comparison elimination
5 participants