[llvm] [InstCombine] Fold comparisons of normalized integer conversions (PR #228791)
Dávid Bolvanský via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 17:23:01 PDT 2026
https://github.com/davidbolvansky created https://github.com/llvm/llvm-project/pull/228791
Fold comparisons of integer-to-FP conversions divided by the same positive constant, including select and min/max trees, when the normalization is provably order-preserving. The fold rejects inexact conversions and possible overflow or underflow, and bounds the expression walk.
Motivated by GraphicsMagick `TransformHSL`: Q16 RGB values are normalized by 65535 before min/max and equality comparisons. These comparisons can use the original integers; this patch removes nine floating-point comparisons in the extracted kernel. Runtime improvement has not yet been measured.
Developed with assistance from OpenAI Codex.
>From daf25cf1c3f6709e442ac13e891864244b9fbbc4 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 02:20:36 +0200
Subject: [PATCH 1/2] [InstCombine] Add tests for comparisons of normalized
integers
---
.../InstCombine/fcmp-normalized-int.ll | 223 ++++++++++++++++++
1 file changed, 223 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll
diff --git a/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll b/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll
new file mode 100644
index 0000000000000..dea130890801c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll
@@ -0,0 +1,223 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @unsigned_lt(i16 %x, i16 %y) {
+; CHECK-LABEL: @unsigned_lt(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %na = fdiv double %a, 65535.0
+ %nb = fdiv double %b, 65535.0
+ %cmp = fcmp olt double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @signed_ge(i16 %x, i16 %y) {
+; CHECK-LABEL: @signed_ge(
+; CHECK-NEXT: [[A:%.*]] = sitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = sitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp uge double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = sitofp i16 %x to double
+ %b = sitofp i16 %y to double
+ %na = fdiv double %a, 65535.0
+ %nb = fdiv double %b, 65535.0
+ %cmp = fcmp uge double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @unsigned_eq(i16 %x, i16 %y) {
+; CHECK-LABEL: @unsigned_eq(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %na = fdiv double %a, 65535.0
+ %nb = fdiv double %b, 65535.0
+ %cmp = fcmp ueq double %na, %nb
+ ret i1 %cmp
+}
+
+define <2 x i1> @vector_lt(<2 x i16> %x, <2 x i16> %y) {
+; CHECK-LABEL: @vector_lt(
+; CHECK-NEXT: [[A:%.*]] = uitofp <2 x i16> [[X:%.*]] to <2 x double>
+; CHECK-NEXT: [[B:%.*]] = uitofp <2 x i16> [[Y:%.*]] to <2 x double>
+; CHECK-NEXT: [[NA:%.*]] = fdiv <2 x double> [[A]], splat (double 6.553500e+04)
+; CHECK-NEXT: [[NB:%.*]] = fdiv <2 x double> [[B]], splat (double 6.553500e+04)
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x double> [[NA]], [[NB]]
+; CHECK-NEXT: ret <2 x i1> [[CMP]]
+;
+ %a = uitofp <2 x i16> %x to <2 x double>
+ %b = uitofp <2 x i16> %y to <2 x double>
+ %na = fdiv <2 x double> %a, <double 65535.0, double 65535.0>
+ %nb = fdiv <2 x double> %b, <double 65535.0, double 65535.0>
+ %cmp = fcmp olt <2 x double> %na, %nb
+ ret <2 x i1> %cmp
+}
+
+define i1 @different_divisors(i16 %x, i16 %y) {
+; CHECK-LABEL: @different_divisors(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fmul nnan double [[B]], f0x3EF0000000000000
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %na = fdiv double %a, 65535.0
+ %nb = fdiv double %b, 65536.0
+ %cmp = fcmp olt double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @negative_divisor(i16 %x, i16 %y) {
+; CHECK-LABEL: @negative_divisor(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], -6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], -6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %na = fdiv double %a, -65535.0
+ %nb = fdiv double %b, -65535.0
+ %cmp = fcmp olt double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @insufficient_precision(i32 %x, i32 %y) {
+; CHECK-LABEL: @insufficient_precision(
+; CHECK-NEXT: [[A:%.*]] = uitofp i32 [[X:%.*]] to float
+; CHECK-NEXT: [[B:%.*]] = uitofp i32 [[Y:%.*]] to float
+; CHECK-NEXT: [[NA:%.*]] = fdiv float [[A]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv float [[B]], 6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i32 %x to float
+ %b = uitofp i32 %y to float
+ %na = fdiv float %a, 65535.0
+ %nb = fdiv float %b, 65535.0
+ %cmp = fcmp olt float %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @underflow(i16 %x, i16 %y) {
+; CHECK-LABEL: @underflow(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], f0x7FEFFFFFFFFFFFFF
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], f0x7FEFFFFFFFFFFFFF
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %na = fdiv double %a, 0x7FEFFFFFFFFFFFFF
+ %nb = fdiv double %b, 0x7FEFFFFFFFFFFFFF
+ %cmp = fcmp olt double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @overflow(i16 %x, i16 %y) {
+; CHECK-LABEL: @overflow(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fmul nnan double [[A]], f0x7FD0000000000000
+; CHECK-NEXT: [[NB:%.*]] = fmul nnan double [[B]], f0x7FD0000000000000
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %na = fdiv double %a, 0x0010000000000000
+ %nb = fdiv double %b, 0x0010000000000000
+ %cmp = fcmp olt double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @select_normalized(i16 %x, i16 %y, i16 %z, i1 %c) {
+; CHECK-LABEL: @select_normalized(
+; CHECK-NEXT: [[D:%.*]] = uitofp i16 [[Z:%.*]] to double
+; CHECK-NEXT: [[ND:%.*]] = fdiv double [[D]], 6.553500e+04
+; CHECK-NEXT: [[S_V_V:%.*]] = select i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]
+; CHECK-NEXT: [[S_V:%.*]] = uitofp i16 [[S_V_V]] to double
+; CHECK-NEXT: [[S:%.*]] = fdiv double [[S_V]], 6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[S]], [[ND]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %d = uitofp i16 %z to double
+ %na = fdiv double %a, 65535.0
+ %nb = fdiv double %b, 65535.0
+ %nd = fdiv double %d, 65535.0
+ %s = select i1 %c, double %na, double %nb
+ %cmp = fcmp ogt double %s, %nd
+ ret i1 %cmp
+}
+
+define i1 @normalize_minmax(i16 %x, i16 %y, i16 %z) {
+; CHECK-LABEL: @normalize_minmax(
+; CHECK-NEXT: [[A:%.*]] = sitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = sitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[D:%.*]] = sitofp i16 [[Z:%.*]] to double
+; CHECK-NEXT: [[LO:%.*]] = call double @llvm.minnum.f64(double [[A]], double [[B]])
+; CHECK-NEXT: [[HI:%.*]] = call double @llvm.maxnum.f64(double [[A]], double [[D]])
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[LO]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[HI]], 6.553500e+04
+; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = sitofp i16 %x to double
+ %b = sitofp i16 %y to double
+ %d = sitofp i16 %z to double
+ %lo = call double @llvm.minnum.f64(double %a, double %b)
+ %hi = call double @llvm.maxnum.f64(double %a, double %d)
+ %na = fdiv double %lo, 65535.0
+ %nb = fdiv double %hi, 65535.0
+ %cmp = fcmp olt double %na, %nb
+ ret i1 %cmp
+}
+
+define i1 @mixed_normalized(i16 %x, i16 %y, i16 %z, i1 %c) {
+; CHECK-LABEL: @mixed_normalized(
+; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
+; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
+; CHECK-NEXT: [[D:%.*]] = uitofp i16 [[Z:%.*]] to double
+; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
+; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
+; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], double [[NA]], double [[D]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[S]], [[NB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %a = uitofp i16 %x to double
+ %b = uitofp i16 %y to double
+ %d = uitofp i16 %z to double
+ %na = fdiv double %a, 65535.0
+ %nb = fdiv double %b, 65535.0
+ %s = select i1 %c, double %na, double %d
+ %cmp = fcmp ogt double %s, %nb
+ ret i1 %cmp
+}
+
+declare double @llvm.minnum.f64(double, double)
+declare double @llvm.maxnum.f64(double, double)
>From 7f2ba971490e8c4eb89f6493259b8db0b457a1e3 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 02:22:14 +0200
Subject: [PATCH 2/2] [InstCombine] Fold comparisons of normalized integer
conversions
---
.../InstCombine/InstCombineCompares.cpp | 148 ++++++++++++++++++
.../InstCombine/fcmp-normalized-int.ll | 41 +----
2 files changed, 156 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 289e074d289c9..9dfd3891ed7f6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -39,6 +39,151 @@ using namespace PatternMatch;
#define DEBUG_TYPE "instcombine"
+namespace {
+
+// Recover integer operands from a bounded tree of normalized conversions.
+// The normalization must preserve the order of every representable input.
+class NormalizedIntCompare {
+ const APFloat *Divisor = nullptr;
+ Type *IntTy = nullptr;
+ unsigned CastOpcode = 0;
+ unsigned NumVisited = 0;
+ SmallDenseMap<Value *, Value *, 16> IntegerValues;
+
+ static std::optional<bool> isMinimum(Value *V) {
+ auto *II = dyn_cast<IntrinsicInst>(V);
+ if (!II)
+ return std::nullopt;
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::minnum:
+ case Intrinsic::minimum:
+ case Intrinsic::minimumnum:
+ return true;
+ case Intrinsic::maxnum:
+ case Intrinsic::maximum:
+ case Intrinsic::maximumnum:
+ return false;
+ default:
+ return std::nullopt;
+ }
+ }
+
+ bool analyze(Value *V, bool IsNormalized = false, unsigned Depth = 0) {
+ if (Depth == 8 || ++NumVisited > 32)
+ return false;
+
+ Value *X;
+ const APFloat *C;
+ if (match(V, m_FDiv(m_Value(X), m_APFloat(C)))) {
+ if (IsNormalized || !C->isFinite() || C->isNegative() || C->isZero() ||
+ (Divisor && !Divisor->bitwiseIsEqual(*C)))
+ return false;
+ Divisor = C;
+ return analyze(X, true, Depth + 1);
+ }
+ if (auto *SI = dyn_cast<SelectInst>(V))
+ return analyze(SI->getTrueValue(), IsNormalized, Depth + 1) &&
+ analyze(SI->getFalseValue(), IsNormalized, Depth + 1);
+ if (isMinimum(V)) {
+ auto *II = cast<IntrinsicInst>(V);
+ return analyze(II->getArgOperand(0), IsNormalized, Depth + 1) &&
+ analyze(II->getArgOperand(1), IsNormalized, Depth + 1);
+ }
+ auto *CI = dyn_cast<CastInst>(V);
+ if (!IsNormalized || !CI ||
+ (CI->getOpcode() != Instruction::UIToFP &&
+ CI->getOpcode() != Instruction::SIToFP) ||
+ (CastOpcode && CastOpcode != CI->getOpcode()))
+ return false;
+ CastOpcode = CI->getOpcode();
+ Type *Ty = CI->getOperand(0)->getType();
+ if (!IntTy || Ty->getScalarSizeInBits() > IntTy->getScalarSizeInBits())
+ IntTy = Ty;
+ return true;
+ }
+
+ Value *build(Value *V, IRBuilderBase &Builder) {
+ if (Value *Cached = IntegerValues.lookup(V))
+ return Cached;
+ Value *Result;
+ if (auto *SI = dyn_cast<SelectInst>(V)) {
+ Result = Builder.CreateSelect(SI->getCondition(),
+ build(SI->getTrueValue(), Builder),
+ build(SI->getFalseValue(), Builder));
+ } else if (auto IsMin = isMinimum(V)) {
+ auto *II = cast<IntrinsicInst>(V);
+ bool IsSigned = CastOpcode == Instruction::SIToFP;
+ Intrinsic::ID ID = *IsMin
+ ? (IsSigned ? Intrinsic::smin : Intrinsic::umin)
+ : (IsSigned ? Intrinsic::smax : Intrinsic::umax);
+ Result = Builder.CreateBinaryIntrinsic(
+ ID, build(II->getArgOperand(0), Builder),
+ build(II->getArgOperand(1), Builder));
+ } else {
+ auto *I = cast<Instruction>(V);
+ Result = I->getOpcode() == Instruction::FDiv
+ ? build(I->getOperand(0), Builder)
+ : Builder.CreateIntCast(I->getOperand(0), IntTy,
+ CastOpcode == Instruction::SIToFP);
+ }
+ IntegerValues[V] = Result;
+ return Result;
+ }
+
+public:
+ Instruction *fold(FCmpInst &I, IRBuilderBase &Builder) {
+ int Precision = I.getOperand(0)->getType()->getFPMantissaWidth();
+ if (Precision < 0 || !analyze(I.getOperand(0)) || !analyze(I.getOperand(1)))
+ return nullptr;
+ bool IsSigned = CastOpcode == Instruction::SIToFP;
+ unsigned MagnitudeBits = IntTy->getScalarSizeInBits() - IsSigned;
+ // Leave two bits of precision so the rounding errors of two quotients
+ // cannot bridge the distance between adjacent integer inputs.
+ if (MagnitudeBits + 2 > unsigned(Precision))
+ return nullptr;
+ APFloat Min = APFloat::getOne(Divisor->getSemantics());
+ APFloat Max = scalbn(Min, MagnitudeBits, APFloat::rmTowardPositive);
+ Min.divide(*Divisor, APFloat::rmTowardZero);
+ Max.divide(*Divisor, APFloat::rmTowardPositive);
+ if (!Min.isNormal() || !Max.isNormal())
+ return nullptr;
+
+ CmpInst::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;
+ }
+ return new ICmpInst(Pred, build(I.getOperand(0), Builder),
+ build(I.getOperand(1), Builder));
+ }
+};
+
+} // namespace
+
// How many times is a select replaced by one of its operands?
STATISTIC(NumSel, "Number of select opts");
@@ -9411,6 +9556,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
}
}
+ if (Instruction *V = NormalizedIntCompare().fold(I, Builder))
+ return V;
+
// Handle fcmp with instruction LHS and constant RHS.
Instruction *LHSI;
Constant *RHSC;
diff --git a/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll b/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll
index dea130890801c..32f5adb38e904 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-normalized-int.ll
@@ -3,11 +3,7 @@
define i1 @unsigned_lt(i16 %x, i16 %y) {
; CHECK-LABEL: @unsigned_lt(
-; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
-; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
-; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
-; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = uitofp i16 %x to double
@@ -20,11 +16,7 @@ define i1 @unsigned_lt(i16 %x, i16 %y) {
define i1 @signed_ge(i16 %x, i16 %y) {
; CHECK-LABEL: @signed_ge(
-; CHECK-NEXT: [[A:%.*]] = sitofp i16 [[X:%.*]] to double
-; CHECK-NEXT: [[B:%.*]] = sitofp i16 [[Y:%.*]] to double
-; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
-; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
-; CHECK-NEXT: [[CMP:%.*]] = fcmp uge double [[NA]], [[NB]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = sitofp i16 %x to double
@@ -37,11 +29,7 @@ define i1 @signed_ge(i16 %x, i16 %y) {
define i1 @unsigned_eq(i16 %x, i16 %y) {
; CHECK-LABEL: @unsigned_eq(
-; CHECK-NEXT: [[A:%.*]] = uitofp i16 [[X:%.*]] to double
-; CHECK-NEXT: [[B:%.*]] = uitofp i16 [[Y:%.*]] to double
-; CHECK-NEXT: [[NA:%.*]] = fdiv double [[A]], 6.553500e+04
-; CHECK-NEXT: [[NB:%.*]] = fdiv double [[B]], 6.553500e+04
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[NA]], [[NB]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = uitofp i16 %x to double
@@ -54,11 +42,7 @@ define i1 @unsigned_eq(i16 %x, i16 %y) {
define <2 x i1> @vector_lt(<2 x i16> %x, <2 x i16> %y) {
; CHECK-LABEL: @vector_lt(
-; CHECK-NEXT: [[A:%.*]] = uitofp <2 x i16> [[X:%.*]] to <2 x double>
-; CHECK-NEXT: [[B:%.*]] = uitofp <2 x i16> [[Y:%.*]] to <2 x double>
-; CHECK-NEXT: [[NA:%.*]] = fdiv <2 x double> [[A]], splat (double 6.553500e+04)
-; CHECK-NEXT: [[NB:%.*]] = fdiv <2 x double> [[B]], splat (double 6.553500e+04)
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x double> [[NA]], [[NB]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i16> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%a = uitofp <2 x i16> %x to <2 x double>
@@ -156,12 +140,8 @@ define i1 @overflow(i16 %x, i16 %y) {
define i1 @select_normalized(i16 %x, i16 %y, i16 %z, i1 %c) {
; CHECK-LABEL: @select_normalized(
-; CHECK-NEXT: [[D:%.*]] = uitofp i16 [[Z:%.*]] to double
-; CHECK-NEXT: [[ND:%.*]] = fdiv double [[D]], 6.553500e+04
; CHECK-NEXT: [[S_V_V:%.*]] = select i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]
-; CHECK-NEXT: [[S_V:%.*]] = uitofp i16 [[S_V_V]] to double
-; CHECK-NEXT: [[S:%.*]] = fdiv double [[S_V]], 6.553500e+04
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[S]], [[ND]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[S_V_V]], [[Z:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = uitofp i16 %x to double
@@ -177,14 +157,9 @@ define i1 @select_normalized(i16 %x, i16 %y, i16 %z, i1 %c) {
define i1 @normalize_minmax(i16 %x, i16 %y, i16 %z) {
; CHECK-LABEL: @normalize_minmax(
-; CHECK-NEXT: [[A:%.*]] = sitofp i16 [[X:%.*]] to double
-; CHECK-NEXT: [[B:%.*]] = sitofp i16 [[Y:%.*]] to double
-; CHECK-NEXT: [[D:%.*]] = sitofp i16 [[Z:%.*]] to double
-; CHECK-NEXT: [[LO:%.*]] = call double @llvm.minnum.f64(double [[A]], double [[B]])
-; CHECK-NEXT: [[HI:%.*]] = call double @llvm.maxnum.f64(double [[A]], double [[D]])
-; CHECK-NEXT: [[NA:%.*]] = fdiv double [[LO]], 6.553500e+04
-; CHECK-NEXT: [[NB:%.*]] = fdiv double [[HI]], 6.553500e+04
-; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[NA]], [[NB]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.smin.i16(i16 [[X:%.*]], i16 [[Y:%.*]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.smax.i16(i16 [[X]], i16 [[Z:%.*]])
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = sitofp i16 %x to double
More information about the llvm-commits
mailing list