Skip to content

Commit 6627fde

Browse files
committed
[InstCombine] add icmp <cond> (fptosi %x) -> fcmp <cond> %y optimization implementation
Add optimization test reducing unneded float-to-int cast when comparing numbers: * icmp sgt (fptosi %x), <negative> -> fcmp ogt %x, <negative> * icmp sgt (fptosi %x), <non-negative> -> fcmp oge %x, <non-negative + 1> * icmp slt (fptosi %x), <positive> -> fcmp olt %x, <positive> * icmp slt (fptosi %x), <non-positive> -> fcmp ole %x, <non-positive - 1>
1 parent 571c50c commit 6627fde

File tree

2 files changed

+101
-34
lines changed

2 files changed

+101
-34
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "InstCombineInternal.h"
1414
#include "llvm/ADT/APFloat.h"
15+
#include "llvm/ADT/APInt.h"
1516
#include "llvm/ADT/APSInt.h"
1617
#include "llvm/ADT/SetVector.h"
1718
#include "llvm/ADT/Statistic.h"
@@ -21,6 +22,7 @@
2122
#include "llvm/Analysis/InstructionSimplify.h"
2223
#include "llvm/Analysis/Utils/Local.h"
2324
#include "llvm/Analysis/VectorUtils.h"
25+
#include "llvm/IR/CmpPredicate.h"
2426
#include "llvm/IR/ConstantRange.h"
2527
#include "llvm/IR/Constants.h"
2628
#include "llvm/IR/DataLayout.h"
@@ -7611,6 +7613,85 @@ Instruction *InstCombinerImpl::foldICmpCommutative(CmpPredicate Pred,
76117613
return nullptr;
76127614
}
76137615

7616+
/// Cast integral constant (either scalar or vector) to an appropriate vector
7617+
/// one
7618+
///
7619+
/// \param C integral contsant to cast
7620+
/// \param FPType floating point type to cast to
7621+
/// \param Addend addend to add before casting
7622+
/// \param DL target data layout
7623+
///
7624+
/// \return result constant
7625+
static Constant *castIntegralConstantToFloat(Constant *C, Type *FPType,
7626+
int Addend, const DataLayout &DL) {
7627+
assert(FPType->isFPOrFPVectorTy() && "fptosi operand must have floating point type");
7628+
7629+
Constant *CWithAddend = ConstantFoldBinaryOpOperands(
7630+
Instruction::Add, C, ConstantInt::getSigned(C->getType(), Addend), DL);
7631+
if (!CWithAddend)
7632+
return nullptr;
7633+
return ConstantFoldCastOperand(Instruction::SIToFP, CWithAddend, FPType, DL);
7634+
}
7635+
7636+
/// Fold icmp (fptosi %arg) C -> fcmp $arg
7637+
/// Folds:
7638+
/// - icmp sgt %arg <negative> -> fcmp ogt %arg <negative>
7639+
/// - icmp sgt %arg <non-negative> -> fcmp oge %arg (<non-negative> + 1)
7640+
/// - icmp slt %arg <positive> -> fcmp olt %arg <positive>
7641+
/// - icmp slt %arg <non-positive> -> fcmp ole %arg (<non-positive> - 1)
7642+
///
7643+
/// \param ICmp icmp instruction
7644+
/// \param IC InstCombiner isntance
7645+
/// \param DL target data layout
7646+
///
7647+
/// \return folded instruction or nullptr, if failed to combine instructions
7648+
static Instruction *foldICmpFToSIToFCmp(ICmpInst &ICmp, InstCombiner &IC,
7649+
const DataLayout &DL) {
7650+
// Expect that canonical form: first argument is fptosi, second is constant
7651+
CmpPredicate Pred;
7652+
Value *FloatOp;
7653+
Constant *C;
7654+
if (!match(&ICmp, m_ICmp(Pred, m_FPToSI(m_Value(FloatOp)), m_ImmConstant(C))))
7655+
return nullptr;
7656+
7657+
if (Pred != ICmpInst::ICMP_SGT && Pred != ICmpInst::ICMP_SLT)
7658+
return nullptr;
7659+
7660+
FCmpInst::Predicate FCmpPredicate;
7661+
Constant *FCmpConstant{};
7662+
7663+
switch (ICmp.getPredicate()) {
7664+
case ICmpInst::ICMP_SGT:
7665+
if (match(C, m_Negative())) {
7666+
// icmp sgt %arg <negative> -> fcmp ogt %arg <negative>
7667+
FCmpPredicate = FCmpInst::FCMP_OGT;
7668+
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 0, DL);
7669+
} else if (match(C, m_NonNegative())) {
7670+
// icmp sgt %arg <non-negative> -> fcmp oge %arg (<non-negative> + 1)
7671+
FCmpPredicate = FCmpInst::FCMP_OGE;
7672+
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 1, DL);
7673+
}
7674+
break;
7675+
case ICmpInst::ICMP_SLT:
7676+
if (match(C, m_StrictlyPositive())) {
7677+
// icmp slt %arg <positive> -> fcmp olt %arg <positive>
7678+
FCmpPredicate = FCmpInst::FCMP_OLT;
7679+
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 0, DL);
7680+
} else if (match(C, m_NonPositive())) {
7681+
// icmp slt %arg <non-positive> -> fcmp ole %arg (<non-positive> - 1)
7682+
FCmpPredicate = FCmpInst::FCMP_OLE;
7683+
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), -1, DL);
7684+
}
7685+
break;
7686+
default:
7687+
llvm_unreachable("Unknown icmp comparator");
7688+
}
7689+
if (!FCmpConstant)
7690+
return nullptr;
7691+
7692+
return new FCmpInst(FCmpPredicate, FloatOp, FCmpConstant);
7693+
}
7694+
76147695
Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
76157696
bool Changed = false;
76167697
const SimplifyQuery Q = SQ.getWithInstruction(&I);
@@ -7748,6 +7829,8 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
77487829
if (Instruction *Res =
77497830
foldICmpCommutative(I.getSwappedCmpPredicate(), Op1, Op0, I))
77507831
return Res;
7832+
if (Instruction *Res = foldICmpFToSIToFCmp(I, *this, DL))
7833+
return Res;
77517834

77527835
if (I.isCommutative()) {
77537836
if (auto Pair = matchSymmetricPair(I.getOperand(0), I.getOperand(1))) {

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6059,8 +6059,7 @@ define i1 @icmp_samesign_logical_or(i32 %In) {
60596059
define i1 @float_to_int_comparing_constant1_positive1(float %arg0) {
60606060
; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_positive1(
60616061
; CHECK-SAME: float [[ARG0:%.*]]) {
6062-
; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32
6063-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], -1
6062+
; CHECK-NEXT: [[V1:%.*]] = fcmp ogt float [[ARG0]], -1.000000e+00
60646063
; CHECK-NEXT: ret i1 [[V1]]
60656064
;
60666065
%v0 = fptosi float %arg0 to i32
@@ -6072,8 +6071,7 @@ define i1 @float_to_int_comparing_constant1_positive1(float %arg0) {
60726071
define i1 @float_to_int_comparing_constant1_positive2(float %arg0) {
60736072
; CHECK-LABEL: define i1 @float_to_int_comparing_constant1_positive2(
60746073
; CHECK-SAME: float [[ARG0:%.*]]) {
6075-
; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32
6076-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], 1
6074+
; CHECK-NEXT: [[V1:%.*]] = fcmp oge float [[ARG0]], 2.000000e+00
60776075
; CHECK-NEXT: ret i1 [[V1]]
60786076
;
60796077
%v0 = fptosi float %arg0 to i32
@@ -6085,8 +6083,7 @@ define i1 @float_to_int_comparing_constant1_positive2(float %arg0) {
60856083
define i1 @float_to_int_comparing_constant2_positive1(float %arg0) {
60866084
; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_positive1(
60876085
; CHECK-SAME: float [[ARG0:%.*]]) {
6088-
; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32
6089-
; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 1
6086+
; CHECK-NEXT: [[V1:%.*]] = fcmp olt float [[ARG0]], 1.000000e+00
60906087
; CHECK-NEXT: ret i1 [[V1]]
60916088
;
60926089
%v0 = fptosi float %arg0 to i32
@@ -6098,8 +6095,7 @@ define i1 @float_to_int_comparing_constant2_positive1(float %arg0) {
60986095
define i1 @float_to_int_comparing_constant2_positive2(float %arg0) {
60996096
; CHECK-LABEL: define i1 @float_to_int_comparing_constant2_positive2(
61006097
; CHECK-SAME: float [[ARG0:%.*]]) {
6101-
; CHECK-NEXT: [[V0:%.*]] = fptosi float [[ARG0]] to i32
6102-
; CHECK-NEXT: [[V1:%.*]] = icmp slt i32 [[V0]], 0
6098+
; CHECK-NEXT: [[V1:%.*]] = fcmp ole float [[ARG0]], -1.000000e+00
61036099
; CHECK-NEXT: ret i1 [[V1]]
61046100
;
61056101
%v0 = fptosi float %arg0 to i32
@@ -6110,8 +6106,7 @@ define i1 @float_to_int_comparing_constant2_positive2(float %arg0) {
61106106
define i1 @double_to_int_comparing_constant1_positive1(double %arg0) {
61116107
; CHECK-LABEL: define i1 @double_to_int_comparing_constant1_positive1(
61126108
; CHECK-SAME: double [[ARG0:%.*]]) {
6113-
; CHECK-NEXT: [[V0:%.*]] = fptosi double [[ARG0]] to i32
6114-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], -1
6109+
; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[ARG0]], -1.000000e+00
61156110
; CHECK-NEXT: ret i1 [[V1]]
61166111
;
61176112
%v0 = fptosi double %arg0 to i32
@@ -6122,8 +6117,7 @@ define i1 @double_to_int_comparing_constant1_positive1(double %arg0) {
61226117
define i1 @double_to_int_comparing_constant1_positive2(double %arg0) {
61236118
; CHECK-LABEL: define i1 @double_to_int_comparing_constant1_positive2(
61246119
; CHECK-SAME: double [[ARG0:%.*]]) {
6125-
; CHECK-NEXT: [[V0:%.*]] = fptosi double [[ARG0]] to i32
6126-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[V0]], 1
6120+
; CHECK-NEXT: [[V1:%.*]] = fcmp oge double [[ARG0]], 2.000000e+00
61276121
; CHECK-NEXT: ret i1 [[V1]]
61286122
;
61296123
%v0 = fptosi double %arg0 to i32
@@ -6134,9 +6128,8 @@ define i1 @double_to_int_comparing_constant1_positive2(double %arg0) {
61346128
define i1 @fp16_to_int_comparing_constant2_positive1(half %arg0) {
61356129
; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_positive1(
61366130
; CHECK-SAME: half [[ARG0:%.*]]) {
6137-
; CHECK-NEXT: [[V1:%.*]] = fptosi half [[ARG0]] to i32
6138-
; CHECK-NEXT: [[V2:%.*]] = icmp slt i32 [[V1]], 1
6139-
; CHECK-NEXT: ret i1 [[V2]]
6131+
; CHECK-NEXT: [[V1:%.*]] = fcmp olt half [[ARG0]], 0xH3C00
6132+
; CHECK-NEXT: ret i1 [[V1]]
61406133
;
61416134
%v0 = fptosi half %arg0 to i32
61426135
%v1 = icmp slt i32 %v0, 1
@@ -6146,9 +6139,8 @@ define i1 @fp16_to_int_comparing_constant2_positive1(half %arg0) {
61466139
define i1 @fp16_to_int_comparing_constant2_positive2(half %arg0) {
61476140
; CHECK-LABEL: define i1 @fp16_to_int_comparing_constant2_positive2(
61486141
; CHECK-SAME: half [[ARG0:%.*]]) {
6149-
; CHECK-NEXT: [[V1:%.*]] = fptosi half [[ARG0]] to i32
6150-
; CHECK-NEXT: [[V2:%.*]] = icmp slt i32 [[V1]], 0
6151-
; CHECK-NEXT: ret i1 [[V2]]
6142+
; CHECK-NEXT: [[V1:%.*]] = fcmp ole half [[ARG0]], 0xHBC00
6143+
; CHECK-NEXT: ret i1 [[V1]]
61526144
;
61536145
%v0 = fptosi half %arg0 to i32
61546146
%v1 = icmp slt i32 %v0, 0
@@ -6202,8 +6194,7 @@ define i1 @float_to_int_comparing_constant2_negative2(float %arg0) {
62026194
define <2 x i1> @float_to_int_comparing_constant_vec_positive1(<2 x float> %arg0) {
62036195
; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive1(
62046196
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) {
6205-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32>
6206-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], splat (i32 -1)
6197+
; CHECK-NEXT: [[V1:%.*]] = fcmp ogt <2 x float> [[ARG0]], splat (float -1.000000e+00)
62076198
; CHECK-NEXT: ret <2 x i1> [[V1]]
62086199
;
62096200
%v0 = fptosi <2 x float> %arg0 to <2 x i32>
@@ -6214,8 +6205,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive1(<2 x float> %arg0
62146205
define <2 x i1> @float_to_int_comparing_constant_vec_positive2(<2 x float> %arg0) {
62156206
; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive2(
62166207
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) {
6217-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32>
6218-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], <i32 0, i32 1>
6208+
; CHECK-NEXT: [[V1:%.*]] = fcmp oge <2 x float> [[ARG0]], <float 1.000000e+00, float 2.000000e+00>
62196209
; CHECK-NEXT: ret <2 x i1> [[V1]]
62206210
;
62216211
%v0 = fptosi <2 x float> %arg0 to <2 x i32>
@@ -6227,8 +6217,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive2(<2 x float> %arg0
62276217
define <2 x i1> @float_to_int_comparing_constant_vec_positive3(<2 x float> %arg0) {
62286218
; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive3(
62296219
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) {
6230-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32>
6231-
; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], splat (i32 1)
6220+
; CHECK-NEXT: [[V1:%.*]] = fcmp olt <2 x float> [[ARG0]], splat (float 1.000000e+00)
62326221
; CHECK-NEXT: ret <2 x i1> [[V1]]
62336222
;
62346223
%v0 = fptosi <2 x float> %arg0 to <2 x i32>
@@ -6239,8 +6228,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive3(<2 x float> %arg0
62396228
define <2 x i1> @float_to_int_comparing_constant_vec_positive4(<2 x float> %arg0) {
62406229
; CHECK-LABEL: define <2 x i1> @float_to_int_comparing_constant_vec_positive4(
62416230
; CHECK-SAME: <2 x float> [[ARG0:%.*]]) {
6242-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x float> [[ARG0]] to <2 x i32>
6243-
; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], <i32 -1, i32 0>
6231+
; CHECK-NEXT: [[V1:%.*]] = fcmp ole <2 x float> [[ARG0]], <float -2.000000e+00, float -1.000000e+00>
62446232
; CHECK-NEXT: ret <2 x i1> [[V1]]
62456233
;
62466234
%v0 = fptosi <2 x float> %arg0 to <2 x i32>
@@ -6251,8 +6239,7 @@ define <2 x i1> @float_to_int_comparing_constant_vec_positive4(<2 x float> %arg0
62516239
define <2 x i1> @half_to_int_comparing_constant_vec_positive1(<2 x half> %arg0) {
62526240
; CHECK-LABEL: define <2 x i1> @half_to_int_comparing_constant_vec_positive1(
62536241
; CHECK-SAME: <2 x half> [[ARG0:%.*]]) {
6254-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x half> [[ARG0]] to <2 x i32>
6255-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], splat (i32 -1)
6242+
; CHECK-NEXT: [[V1:%.*]] = fcmp ogt <2 x half> [[ARG0]], splat (half 0xHBC00)
62566243
; CHECK-NEXT: ret <2 x i1> [[V1]]
62576244
;
62586245
%v0 = fptosi <2 x half> %arg0 to <2 x i32>
@@ -6263,8 +6250,7 @@ define <2 x i1> @half_to_int_comparing_constant_vec_positive1(<2 x half> %arg0)
62636250
define <2 x i1> @half_to_int_comparing_constant_vec_positive2(<2 x half> %arg0) {
62646251
; CHECK-LABEL: define <2 x i1> @half_to_int_comparing_constant_vec_positive2(
62656252
; CHECK-SAME: <2 x half> [[ARG0:%.*]]) {
6266-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x half> [[ARG0]] to <2 x i32>
6267-
; CHECK-NEXT: [[V1:%.*]] = icmp sgt <2 x i32> [[V0]], <i32 0, i32 1>
6253+
; CHECK-NEXT: [[V1:%.*]] = fcmp oge <2 x half> [[ARG0]], <half 0xH3C00, half 0xH4000>
62686254
; CHECK-NEXT: ret <2 x i1> [[V1]]
62696255
;
62706256
%v0 = fptosi <2 x half> %arg0 to <2 x i32>
@@ -6275,8 +6261,7 @@ define <2 x i1> @half_to_int_comparing_constant_vec_positive2(<2 x half> %arg0)
62756261
define <2 x i1> @double_to_int_comparing_constant_vec_positive3(<2 x double> %arg0) {
62766262
; CHECK-LABEL: define <2 x i1> @double_to_int_comparing_constant_vec_positive3(
62776263
; CHECK-SAME: <2 x double> [[ARG0:%.*]]) {
6278-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x double> [[ARG0]] to <2 x i32>
6279-
; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], splat (i32 1)
6264+
; CHECK-NEXT: [[V1:%.*]] = fcmp olt <2 x double> [[ARG0]], splat (double 1.000000e+00)
62806265
; CHECK-NEXT: ret <2 x i1> [[V1]]
62816266
;
62826267
%v0 = fptosi <2 x double> %arg0 to <2 x i32>
@@ -6287,8 +6272,7 @@ define <2 x i1> @double_to_int_comparing_constant_vec_positive3(<2 x double> %ar
62876272
define <2 x i1> @double_to_int_comparing_constant_vec_positive4(<2 x double> %arg0) {
62886273
; CHECK-LABEL: define <2 x i1> @double_to_int_comparing_constant_vec_positive4(
62896274
; CHECK-SAME: <2 x double> [[ARG0:%.*]]) {
6290-
; CHECK-NEXT: [[V0:%.*]] = fptosi <2 x double> [[ARG0]] to <2 x i32>
6291-
; CHECK-NEXT: [[V1:%.*]] = icmp slt <2 x i32> [[V0]], <i32 -1, i32 0>
6275+
; CHECK-NEXT: [[V1:%.*]] = fcmp ole <2 x double> [[ARG0]], <double -2.000000e+00, double -1.000000e+00>
62926276
; CHECK-NEXT: ret <2 x i1> [[V1]]
62936277
;
62946278
%v0 = fptosi <2 x double> %arg0 to <2 x i32>

0 commit comments

Comments
 (0)