Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions llvm/include/llvm/IR/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,19 @@ inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) {
return V;
}

struct is_minsignedvalue {
bool isValue(const APInt &C) const { return C.isMinSignedValue(); }
};
/// Match an integer or vector with values having only high bit set
/// (0x80...).
/// For vectors, this includes constants with undefined elements.
inline cst_pred_ty<is_minsignedvalue> m_MinSignedValue() {
return cst_pred_ty<is_minsignedvalue>();
}
inline api_pred_ty<is_minsignedvalue> m_MinSignedValue(const APInt *&V) {
return V;
}

struct is_negative {
bool isValue(const APInt &C) const { return C.isNegative(); }
};
Expand Down
85 changes: 85 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "InstCombineInternal.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
Expand All @@ -21,6 +22,7 @@
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/Utils/Local.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/CmpPredicate.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
Expand Down Expand Up @@ -7611,6 +7613,87 @@ Instruction *InstCombinerImpl::foldICmpCommutative(CmpPredicate Pred,
return nullptr;
}

/// Cast integral constant (either scalar or vector) to an appropriate vector
/// one
///
/// \param C integral contsant to cast
/// \param FPType floating point type to cast to
/// \param Addend addend to add before casting
/// \param DL target data layout
///
/// \return result constant
static Constant *castIntegralConstantToFloat(Constant *C, Type *FPType,
int Addend, const DataLayout &DL) {
assert(FPType->isFPOrFPVectorTy() &&
"fptosi operand must have floating point type");

Constant *CWithAddend = ConstantFoldBinaryOpOperands(
Instruction::Add, C, ConstantInt::getSigned(C->getType(), Addend), DL);
if (!CWithAddend)
return nullptr;
return ConstantFoldCastOperand(Instruction::SIToFP, CWithAddend, FPType, DL);
}

/// Fold icmp (fptosi %arg) C -> fcmp $arg
/// Folds:
/// - icmp sgt %arg <negative> -> fcmp ogt %arg <negative>
/// - icmp sgt %arg <non-negative> -> fcmp oge %arg (<non-negative> + 1)
/// - icmp slt %arg <positive> -> fcmp olt %arg <positive>
/// - icmp slt %arg <non-positive> -> fcmp ole %arg (<non-positive> - 1)
///
/// \param ICmp icmp instruction
/// \param IC InstCombiner isntance
/// \param DL target data layout
///
/// \return folded instruction or nullptr, if failed to combine instructions
static Instruction *foldICmpFToSIToFCmp(ICmpInst &ICmp, InstCombiner &IC,
const DataLayout &DL) {
// Expect that canonical form: first argument is fptosi, second is constant
CmpPredicate Pred;
Value *FloatOp;
Constant *C;
if (!match(&ICmp, m_ICmp(Pred, m_OneUse(m_FPToSI(m_Value(FloatOp))),
m_ImmConstant(C))))
return nullptr;

if (Pred != ICmpInst::ICMP_SGT && Pred != ICmpInst::ICMP_SLT)
return nullptr;
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use default: return nullptr instead of the separate check.

Copy link
Author

Choose a reason for hiding this comment

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

I also had this thought (using pointer as boolean marker does not look pretty to me also) the change would also require adding additional else to ifs: if non-splat vector with values [1, -1] it is neither positive, non-positive, negative nor non-negative and thus neither if branch would be executed. nullptr works for that case, but default would not. Additionally, FCmpConstant checked for nullptr works when integer is failed to convert to fp number.


FCmpInst::Predicate FCmpPredicate;
Constant *FCmpConstant{};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Constant *FCmpConstant{};
Constant *FCmpConstant;

Copy link
Author

Choose a reason for hiding this comment

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

same as below


switch (ICmp.getPredicate()) {
case ICmpInst::ICMP_SGT:
if (match(C, m_Negative())) {
// icmp sgt %arg <negative> -> fcmp ogt %arg <negative>
FCmpPredicate = FCmpInst::FCMP_OGT;
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 0, DL);
} else if (match(C, m_NonNegative()) && !match(C, m_MaxSignedValue())) {
// icmp sgt %arg <non-negative> -> fcmp oge %arg (<non-negative> + 1)
FCmpPredicate = FCmpInst::FCMP_OGE;
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 1, DL);
}
break;
case ICmpInst::ICMP_SLT:
if (match(C, m_StrictlyPositive())) {
// icmp slt %arg <positive> -> fcmp olt %arg <positive>
FCmpPredicate = FCmpInst::FCMP_OLT;
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), 0, DL);
} else if (match(C, m_NonPositive()) && !match(C, m_MinSignedValue())) {
// icmp slt %arg <non-positive> -> fcmp ole %arg (<non-positive> - 1)
FCmpPredicate = FCmpInst::FCMP_OLE;
FCmpConstant = castIntegralConstantToFloat(C, FloatOp->getType(), -1, DL);
}
break;
default:
llvm_unreachable("Unknown icmp comparator");
}
if (!FCmpConstant)
return nullptr;

return new FCmpInst(FCmpPredicate, FloatOp, FCmpConstant);
}

Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
bool Changed = false;
const SimplifyQuery Q = SQ.getWithInstruction(&I);
Expand Down Expand Up @@ -7748,6 +7831,8 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
if (Instruction *Res =
foldICmpCommutative(I.getSwappedCmpPredicate(), Op1, Op0, I))
return Res;
if (Instruction *Res = foldICmpFToSIToFCmp(I, *this, DL))
return Res;

if (I.isCommutative()) {
if (auto Pair = matchSymmetricPair(I.getOperand(0), I.getOperand(1))) {
Expand Down
Loading