[llvm] [InstCombine] Fold comparisons of exact integer-to-FP casts (PR #228787)

Dávid Bolvanský via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 16:29:39 PDT 2026


https://github.com/davidbolvansky created https://github.com/llvm/llvm-project/pull/228787

Fold comparisons of two `uitofp` or two `sitofp` casts to integer comparisons when the floating-point significand can represent every source value exactly. Supports equality and ordering, including different integer widths and vectors.

Motivated by GraphicsMagick RGB-to-HWB conversion: the patch reduces conversion time by 9.9% on Mars image pixels and 10.4% on random pixels in an isolated kernel benchmark on Apple M1 Pro (`-O3`, no PGO).

Developed with assistance from OpenAI Codex.


>From c359c4ada80e647908fd53fba9a3c311f941a201 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sun, 4 Oct 2026 01:27:28 +0200
Subject: [PATCH 1/2] [InstCombine] Add tests for comparisons of integer-to-FP
 casts

---
 .../Transforms/InstCombine/fcmp-int-to-fp.ll  | 296 ++++++++++++++++++
 1 file changed, 296 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll

diff --git a/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll b/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll
new file mode 100644
index 000000000000000..b1594096e4640e8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll
@@ -0,0 +1,296 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+define i1 @unsigned_oeq(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_oeq(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp oeq double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_ueq(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @signed_ueq(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = sitofp i32 %b to double
+  %cmp = fcmp ueq double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_one(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_one(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp one double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_une(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @signed_une(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = sitofp i32 %b to double
+  %cmp = fcmp une double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_olt(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_olt(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp olt double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_ult(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @signed_ult(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ult double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = sitofp i32 %b to double
+  %cmp = fcmp ult double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_ole(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_ole(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ole double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp ole double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_ule(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @signed_ule(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = sitofp i32 %b to double
+  %cmp = fcmp ule double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_ogt(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_ogt(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp ogt double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_ugt(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @signed_ugt(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ugt double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = sitofp i32 %b to double
+  %cmp = fcmp ugt double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_oge(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_oge(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp oge double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_uge(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @signed_uge(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = sitofp i32 %b to double
+  %cmp = fcmp uge double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_mixed_widths(i16 %a, i32 %b) {
+; CHECK-LABEL: define i1 @unsigned_mixed_widths(
+; CHECK-SAME: i16 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i16 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i16 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp oeq double %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_mixed_widths(i8 %a, i16 %b) {
+; CHECK-LABEL: define i1 @signed_mixed_widths(
+; CHECK-SAME: i8 [[A:%.*]], i16 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i8 [[A]] to float
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i16 [[B]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i8 %a to float
+  %fb = sitofp i16 %b to float
+  %cmp = fcmp olt float %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_float_exact_boundary(i24 %a, i24 %b) {
+; CHECK-LABEL: define i1 @unsigned_float_exact_boundary(
+; CHECK-SAME: i24 [[A:%.*]], i24 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i24 [[A]] to float
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i24 [[B]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i24 %a to float
+  %fb = uitofp i24 %b to float
+  %cmp = fcmp oeq float %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_float_inexact(i25 %a, i25 %b) {
+; CHECK-LABEL: define i1 @unsigned_float_inexact(
+; CHECK-SAME: i25 [[A:%.*]], i25 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i25 [[A]] to float
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i25 [[B]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i25 %a to float
+  %fb = uitofp i25 %b to float
+  %cmp = fcmp oeq float %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_float_exact_boundary(i25 %a, i25 %b) {
+; CHECK-LABEL: define i1 @signed_float_exact_boundary(
+; CHECK-SAME: i25 [[A:%.*]], i25 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i25 [[A]] to float
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i25 [[B]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i25 %a to float
+  %fb = sitofp i25 %b to float
+  %cmp = fcmp olt float %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @signed_float_inexact(i26 %a, i26 %b) {
+; CHECK-LABEL: define i1 @signed_float_inexact(
+; CHECK-SAME: i26 [[A:%.*]], i26 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i26 [[A]] to float
+; CHECK-NEXT:    [[FB:%.*]] = sitofp i26 [[B]] to float
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i26 %a to float
+  %fb = sitofp i26 %b to float
+  %cmp = fcmp olt float %fa, %fb
+  ret i1 %cmp
+}
+
+define i1 @unsigned_double_inexact(i64 %a, i64 %b) {
+; CHECK-LABEL: define i1 @unsigned_double_inexact(
+; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp i64 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i64 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = uitofp i64 %a to double
+  %fb = uitofp i64 %b to double
+  %cmp = fcmp oeq double %fa, %fb
+  ret i1 %cmp
+}
+
+define <4 x i1> @unsigned_vector(<4 x i16> %a, <4 x i16> %b) {
+; CHECK-LABEL: define <4 x i1> @unsigned_vector(
+; CHECK-SAME: <4 x i16> [[A:%.*]], <4 x i16> [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = uitofp <4 x i16> [[A]] to <4 x float>
+; CHECK-NEXT:    [[FB:%.*]] = uitofp <4 x i16> [[B]] to <4 x float>
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule <4 x float> [[FA]], [[FB]]
+; CHECK-NEXT:    ret <4 x i1> [[CMP]]
+;
+  %fa = uitofp <4 x i16> %a to <4 x float>
+  %fb = uitofp <4 x i16> %b to <4 x float>
+  %cmp = fcmp ule <4 x float> %fa, %fb
+  ret <4 x i1> %cmp
+}
+
+define i1 @mixed_signedness(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @mixed_signedness(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
+; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[FA]], [[FB]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %fa = sitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %cmp = fcmp oeq double %fa, %fb
+  ret i1 %cmp
+}

>From d009ba3a6bfce6da66a97972e027a39003cce7d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A1vid=20Bolvansk=C3=BD?= <david.bolvansky at gmail.com>
Date: Sun, 4 Oct 2026 01:29:05 +0200
Subject: [PATCH 2/2] [InstCombine] Fold comparisons of exact integer-to-FP
 casts

---
 .../InstCombine/InstCombineCompares.cpp       | 58 +++++++++++++++
 .../InstCombine/InstCombineInternal.h         |  1 +
 .../Transforms/InstCombine/fcmp-int-to-fp.ll  | 70 +++++--------------
 3 files changed, 78 insertions(+), 51 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 289e074d289c90d..7ce1d16156f5903 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -8376,6 +8376,61 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
   return Changed ? &I : nullptr;
 }
 
+/// Compare integers directly when both integer-to-FP conversions are exact.
+Instruction *InstCombinerImpl::foldFCmpIntToFP(FCmpInst &I) {
+  Value *A, *B;
+  bool IsSigned;
+  if (match(&I, m_FCmp(m_UIToFP(m_Value(A)), m_UIToFP(m_Value(B)))))
+    IsSigned = false;
+  else if (match(&I, m_FCmp(m_SIToFP(m_Value(A)), m_SIToFP(m_Value(B)))))
+    IsSigned = true;
+  else
+    return nullptr;
+
+  unsigned Width = std::max(A->getType()->getScalarSizeInBits(),
+                            B->getType()->getScalarSizeInBits());
+  // Exact conversions preserve both equality and ordering. Account for the
+  // sign bit, which does not consume floating-point significand bits.
+  int Precision = I.getOperand(0)->getType()->getFPMantissaWidth();
+  if (Precision < 0 || Width - IsSigned > unsigned(Precision))
+    return nullptr;
+
+  ICmpInst::Predicate Pred;
+  switch (I.getPredicate()) {
+  case FCmpInst::FCMP_OEQ:
+  case FCmpInst::FCMP_UEQ:
+    Pred = ICmpInst::ICMP_EQ;
+    break;
+  case FCmpInst::FCMP_ONE:
+  case FCmpInst::FCMP_UNE:
+    Pred = ICmpInst::ICMP_NE;
+    break;
+  case FCmpInst::FCMP_OLT:
+  case FCmpInst::FCMP_ULT:
+    Pred = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
+    break;
+  case FCmpInst::FCMP_OLE:
+  case FCmpInst::FCMP_ULE:
+    Pred = IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
+    break;
+  case FCmpInst::FCMP_OGT:
+  case FCmpInst::FCMP_UGT:
+    Pred = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
+    break;
+  case FCmpInst::FCMP_OGE:
+  case FCmpInst::FCMP_UGE:
+    Pred = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
+    break;
+  default:
+    return nullptr;
+  }
+
+  Type *IntTy = A->getType()->getWithNewBitWidth(Width);
+  A = Builder.CreateIntCast(A, IntTy, IsSigned);
+  B = Builder.CreateIntCast(B, IntTy, IsSigned);
+  return new ICmpInst(Pred, A, B);
+}
+
 /// Fold fcmp ([us]itofp x, cst) if possible.
 Instruction *InstCombinerImpl::foldFCmpIntToFPConst(FCmpInst &I,
                                                     Instruction *LHSI,
@@ -9411,6 +9466,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
     }
   }
 
+  if (Instruction *R = foldFCmpIntToFP(I))
+    return R;
+
   // Handle fcmp with instruction LHS and constant RHS.
   Instruction *LHSI;
   Constant *RHSC;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 388530edc10dad8..fbd7b0ac3b8cf65 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -730,6 +730,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
                                             GetElementPtrInst *GEP,
                                             CmpInst &ICI,
                                             ConstantInt *AndCst = nullptr);
+  Instruction *foldFCmpIntToFP(FCmpInst &I);
   Instruction *foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI,
                                     Constant *RHSC);
   Instruction *foldICmpAddOpConst(Value *X, const APInt &C, CmpPredicate Pred);
diff --git a/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll b/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll
index b1594096e4640e8..1a50f328fbf0742 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-int-to-fp.ll
@@ -4,9 +4,7 @@
 define i1 @unsigned_oeq(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_oeq(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i32 %a to double
@@ -18,9 +16,7 @@ define i1 @unsigned_oeq(i32 %a, i32 %b) {
 define i1 @signed_ueq(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @signed_ueq(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ueq double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i32 %a to double
@@ -32,9 +28,7 @@ define i1 @signed_ueq(i32 %a, i32 %b) {
 define i1 @unsigned_one(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_one(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp one double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i32 %a to double
@@ -46,9 +40,7 @@ define i1 @unsigned_one(i32 %a, i32 %b) {
 define i1 @signed_une(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @signed_une(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i32 %a to double
@@ -60,9 +52,7 @@ define i1 @signed_une(i32 %a, i32 %b) {
 define i1 @unsigned_olt(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_olt(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i32 %a to double
@@ -74,9 +64,7 @@ define i1 @unsigned_olt(i32 %a, i32 %b) {
 define i1 @signed_ult(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @signed_ult(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ult double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i32 %a to double
@@ -88,9 +76,7 @@ define i1 @signed_ult(i32 %a, i32 %b) {
 define i1 @unsigned_ole(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_ole(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ole double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i32 %a to double
@@ -102,9 +88,7 @@ define i1 @unsigned_ole(i32 %a, i32 %b) {
 define i1 @signed_ule(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @signed_ule(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i32 %a to double
@@ -116,9 +100,7 @@ define i1 @signed_ule(i32 %a, i32 %b) {
 define i1 @unsigned_ogt(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_ogt(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i32 %a to double
@@ -130,9 +112,7 @@ define i1 @unsigned_ogt(i32 %a, i32 %b) {
 define i1 @signed_ugt(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @signed_ugt(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ugt double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i32 %a to double
@@ -144,9 +124,7 @@ define i1 @signed_ugt(i32 %a, i32 %b) {
 define i1 @unsigned_oge(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_oge(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i32 %a to double
@@ -158,9 +136,7 @@ define i1 @unsigned_oge(i32 %a, i32 %b) {
 define i1 @signed_uge(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @signed_uge(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i32 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge double [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i32 %a to double
@@ -172,9 +148,8 @@ define i1 @signed_uge(i32 %a, i32 %b) {
 define i1 @unsigned_mixed_widths(i16 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @unsigned_mixed_widths(
 ; CHECK-SAME: i16 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i16 [[A]] to double
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i32 [[B]] to double
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[FA]], [[FB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[A]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[B]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i16 %a to double
@@ -186,9 +161,8 @@ define i1 @unsigned_mixed_widths(i16 %a, i32 %b) {
 define i1 @signed_mixed_widths(i8 %a, i16 %b) {
 ; CHECK-LABEL: define i1 @signed_mixed_widths(
 ; CHECK-SAME: i8 [[A:%.*]], i16 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i8 [[A]] to float
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i16 [[B]] to float
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[FA]], [[FB]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[A]] to i16
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[B]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i8 %a to float
@@ -200,9 +174,7 @@ define i1 @signed_mixed_widths(i8 %a, i16 %b) {
 define i1 @unsigned_float_exact_boundary(i24 %a, i24 %b) {
 ; CHECK-LABEL: define i1 @unsigned_float_exact_boundary(
 ; CHECK-SAME: i24 [[A:%.*]], i24 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp i24 [[A]] to float
-; CHECK-NEXT:    [[FB:%.*]] = uitofp i24 [[B]] to float
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i24 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = uitofp i24 %a to float
@@ -228,9 +200,7 @@ define i1 @unsigned_float_inexact(i25 %a, i25 %b) {
 define i1 @signed_float_exact_boundary(i25 %a, i25 %b) {
 ; CHECK-LABEL: define i1 @signed_float_exact_boundary(
 ; CHECK-SAME: i25 [[A:%.*]], i25 [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = sitofp i25 [[A]] to float
-; CHECK-NEXT:    [[FB:%.*]] = sitofp i25 [[B]] to float
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i25 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %fa = sitofp i25 %a to float
@@ -270,9 +240,7 @@ define i1 @unsigned_double_inexact(i64 %a, i64 %b) {
 define <4 x i1> @unsigned_vector(<4 x i16> %a, <4 x i16> %b) {
 ; CHECK-LABEL: define <4 x i1> @unsigned_vector(
 ; CHECK-SAME: <4 x i16> [[A:%.*]], <4 x i16> [[B:%.*]]) {
-; CHECK-NEXT:    [[FA:%.*]] = uitofp <4 x i16> [[A]] to <4 x float>
-; CHECK-NEXT:    [[FB:%.*]] = uitofp <4 x i16> [[B]] to <4 x float>
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule <4 x float> [[FA]], [[FB]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule <4 x i16> [[A]], [[B]]
 ; CHECK-NEXT:    ret <4 x i1> [[CMP]]
 ;
   %fa = uitofp <4 x i16> %a to <4 x float>



More information about the llvm-commits mailing list