[llvm] 120cbbd - [InstCombine] Fold `fptrunc(x) ord/uno [ C | fptrunc(y) ]` to `x ord/uno [ C | y ]` (#185844)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 15 02:07:14 PDT 2026
Author: Kunqiu Chen
Date: 2026-04-15T17:07:08+08:00
New Revision: 120cbbd88bf6b6c723176684a12c64393abe7e95
URL: https://github.com/llvm/llvm-project/commit/120cbbd88bf6b6c723176684a12c64393abe7e95
DIFF: https://github.com/llvm/llvm-project/commit/120cbbd88bf6b6c723176684a12c64393abe7e95.diff
LOG: [InstCombine] Fold `fptrunc(x) ord/uno [ C | fptrunc(y) ]` to `x ord/uno [ C | y ]` (#185844)
Recognize TWO new patterns and fold them as follows:
```
fptrunc(x) ord/uno C --> x ord/uno 0
fptrunc(x) ord/uno fptrunc(y) --> x ord/uno y
```
Fixes #185698
Alive2: https://alive2.llvm.org/ce/z/YvXnBJ
IR diff: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/3551
CompTime impact: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/3552
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
llvm/test/Transforms/InstCombine/known-never-nan.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index eac1f585e2118..76714f0a14158 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -26,6 +26,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
@@ -8436,15 +8437,32 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
// Transform 'fptrunc(x) cmp C' to 'x cmp ext(C)' if possible.
// Patterns include:
-// fptrunc(x) < C --> x < ext(C)
-// fptrunc(x) <= C --> x <= ext(C)
-// fptrunc(x) > C --> x > ext(C)
-// fptrunc(x) >= C --> x >= ext(C)
+// fptrunc(x) < C --> x < ext(C)
+// fptrunc(x) <= C --> x <= ext(C)
+// fptrunc(x) > C --> x > ext(C)
+// fptrunc(x) >= C --> x >= ext(C)
+// fptrunc(x) ord/uno C --> x ord/uno 0
// where 'ext(C)' is the extension of 'C' to the type of 'x' with a small bias
// due to precision loss.
static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
const Constant &C) {
FCmpInst::Predicate Pred = I.getPredicate();
+ Type *DestType = FPTrunc.getOperand(0)->getType();
+
+ const APFloat *CValue;
+ // TODO: support vec
+ if (!match(&C, m_APFloat(CValue)))
+ return nullptr;
+
+ // Handle ord/uno
+ if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
+ assert(!CValue->isNaN() &&
+ "X ord/uno NaN should be folded away by simplifyFCmpInst()");
+ return new FCmpInst(Pred, FPTrunc.getOperand(0),
+ ConstantFP::getZero(DestType), "", &I);
+ }
+
+ // Handle <, >, <=, >=
bool RoundDown = false;
if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
@@ -8456,10 +8474,6 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
else
return nullptr;
- const APFloat *CValue;
- if (!match(&C, m_APFloat(CValue)))
- return nullptr;
-
if (CValue->isNaN() || CValue->isInfinity())
return nullptr;
@@ -8478,7 +8492,6 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
APFloat NextCValue = NextValue(*CValue, RoundDown);
- Type *DestType = FPTrunc.getOperand(0)->getType();
const fltSemantics &DestFltSema =
DestType->getScalarType()->getFltSemantics();
@@ -9124,6 +9137,12 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
if (match(Op1, m_FAdd(m_Value(Y), m_AnyZeroFP())))
return new FCmpInst(Pred, Op0, Y, "", &I);
+ // fcmp ord/uno (fptrunc X), (fptrunc Y) -> fcmp ord/uno X, Y
+ if ((Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) &&
+ match(Op0, m_FPTrunc(m_Value(X))) && match(Op1, m_FPTrunc(m_Value(Y))) &&
+ X->getType() == Y->getType())
+ return new FCmpInst(Pred, X, Y, "", &I);
+
if (match(Op0, m_FPExt(m_Value(X)))) {
// fcmp (fpext X), (fpext Y) -> fcmp X, Y
if (match(Op1, m_FPExt(m_Value(Y))) && X->getType() == Y->getType())
diff --git a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
index 371f9b6807fe4..d42ba952ace99 100644
--- a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
+++ b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
@@ -57,6 +57,52 @@ define i1 @fcmp_trunc_zero(double %0) {
ret i1 %result
}
+define i1 @fcmp_trunc_uno(double %0) {
+; CHECK-LABEL: define i1 @fcmp_trunc_uno(
+; CHECK-SAME: double [[TMP0:%.*]]) {
+; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno double [[TMP0]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+ %trunc = fptrunc double %0 to float
+ %result = fcmp uno float %trunc, 0.000000e+00
+ ret i1 %result
+}
+
+define i1 @fcmp_trunc_ord_inf(double %0) {
+; CHECK-LABEL: define i1 @fcmp_trunc_ord_inf(
+; CHECK-SAME: double [[TMP0:%.*]]) {
+; CHECK-NEXT: [[RESULT:%.*]] = fcmp ord double [[TMP0]], 0.000000e+00
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+ %trunc = fptrunc double %0 to float
+ %result = fcmp ord float %trunc, 0x7FF0000000000000
+ ret i1 %result
+}
+
+define i1 @fcmp_trunc_pair_uno(double %x, double %y) {
+; CHECK-LABEL: define i1 @fcmp_trunc_pair_uno(
+; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno double [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+ %tx = fptrunc double %x to float
+ %ty = fptrunc double %y to float
+ %result = fcmp uno float %tx, %ty
+ ret i1 %result
+}
+
+define i1 @fcmp_trunc_pair_ord(double %x, double %y) {
+; CHECK-LABEL: define i1 @fcmp_trunc_pair_ord(
+; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT: [[RESULT:%.*]] = fcmp ord double [[X]], [[Y]]
+; CHECK-NEXT: ret i1 [[RESULT]]
+;
+ %tx = fptrunc double %x to float
+ %ty = fptrunc double %y to float
+ %result = fcmp ord float %tx, %ty
+ ret i1 %result
+}
+
define i1 @fcmp_trunc_with_nnan(double %0) {
; CHECK-LABEL: define i1 @fcmp_trunc_with_nnan(
; CHECK-SAME: double [[TMP0:%.*]]) {
@@ -104,7 +150,7 @@ define i1 @fcmp_trunc_with_reassoc(double %0) {
define i1 @fcmp_trunc_with_fast(double %0) {
; CHECK-LABEL: define i1 @fcmp_trunc_with_fast(
; CHECK-SAME: double [[TMP0:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000
+; CHECK-NEXT: [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000
; CHECK-NEXT: ret i1 [[RESULT]]
;
%trunc = fptrunc double %0 to float
@@ -327,8 +373,7 @@ define i1 @fcmp_trunc_literal_positive_inf(double %0) {
define i1 @fcmp_trunc_literal_negative_inf(double %0) {
; CHECK-LABEL: define i1 @fcmp_trunc_literal_negative_inf(
; CHECK-SAME: double [[TMP0:%.*]]) {
-; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[TMP0]] to float
-; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno float [[TRUNC]], 0.000000e+00
+; CHECK-NEXT: [[RESULT:%.*]] = fcmp uno double [[TMP0]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RESULT]]
;
%trunc = fptrunc double %0 to float
diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll
index c4ce874029647..759cabae3d72f 100644
--- a/llvm/test/Transforms/InstCombine/known-never-nan.ll
+++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll
@@ -150,8 +150,7 @@ define i1 @fpext_maybe_nan(float %arg0) {
define i1 @fptrunc_maybe_nan(double %arg0) {
; CHECK-LABEL: @fptrunc_maybe_nan(
-; CHECK-NEXT: [[OP:%.*]] = fptrunc double [[ARG0:%.*]] to float
-; CHECK-NEXT: [[TMP:%.*]] = fcmp ord float [[OP]], 0.000000e+00
+; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[ARG0:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[TMP]]
;
%op = fptrunc double %arg0 to float
More information about the llvm-commits
mailing list