Skip to content

Commit f0cea1f

Browse files
committed
[InstCombine] Move helper functions into ValueTracking
1 parent a8e88b1 commit f0cea1f

File tree

3 files changed

+131
-122
lines changed

3 files changed

+131
-122
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,13 @@ bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ);
330330
std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
331331
const SimplifyQuery &SQ);
332332

333+
/// Return true if the sign bit of result can be ignored when the result is
334+
/// zero.
335+
bool ignoreSignBitOfZero(Instruction &I);
336+
337+
/// Return true if the sign bit of result can be ignored when the result is NaN.
338+
bool ignoreSignBitOfNaN(Instruction &I);
339+
333340
/// If the specified value can be set by repeating the same byte in memory,
334341
/// return the i8 value that it is represented with. This is true for all i8
335342
/// values obviously, but is also true for i32 0, i32 -1, i16 0xF0F0, double

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6357,6 +6357,130 @@ std::optional<bool> llvm::computeKnownFPSignBit(const Value *V, unsigned Depth,
63576357
return Known.SignBit;
63586358
}
63596359

6360+
/// Return true if the sign bit of result can be ignored when the result is
6361+
/// zero.
6362+
bool llvm::ignoreSignBitOfZero(Instruction &I) {
6363+
if (auto *FPOp = dyn_cast<FPMathOperator>(&I))
6364+
if (FPOp->hasNoSignedZeros())
6365+
return true;
6366+
6367+
// Check if the sign bit is ignored by the only user.
6368+
if (!I.hasOneUse())
6369+
return false;
6370+
Instruction *User = I.user_back();
6371+
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
6372+
if (FPOp->hasNoSignedZeros())
6373+
return true;
6374+
}
6375+
6376+
switch (User->getOpcode()) {
6377+
case Instruction::FPToSI:
6378+
case Instruction::FPToUI:
6379+
return true;
6380+
case Instruction::FCmp:
6381+
// fcmp treats both positive and negative zero as equal.
6382+
return true;
6383+
case Instruction::Call:
6384+
if (auto *II = dyn_cast<IntrinsicInst>(User)) {
6385+
switch (II->getIntrinsicID()) {
6386+
case Intrinsic::fabs:
6387+
return true;
6388+
case Intrinsic::copysign:
6389+
return II->getArgOperand(0) == &I;
6390+
case Intrinsic::is_fpclass:
6391+
case Intrinsic::vp_is_fpclass: {
6392+
auto Test =
6393+
static_cast<FPClassTest>(
6394+
cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()) &
6395+
FPClassTest::fcZero;
6396+
return Test == FPClassTest::fcZero || Test == FPClassTest::fcNone;
6397+
}
6398+
default:
6399+
return false;
6400+
}
6401+
}
6402+
return false;
6403+
default:
6404+
return false;
6405+
}
6406+
}
6407+
6408+
bool llvm::ignoreSignBitOfNaN(Instruction &I) {
6409+
if (auto *FPOp = dyn_cast<FPMathOperator>(&I))
6410+
if (FPOp->hasNoNaNs())
6411+
return true;
6412+
6413+
// Check if the sign bit is ignored by the only user.
6414+
if (!I.hasOneUse())
6415+
return false;
6416+
Instruction *User = I.user_back();
6417+
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
6418+
if (FPOp->hasNoNaNs())
6419+
return true;
6420+
}
6421+
6422+
switch (User->getOpcode()) {
6423+
case Instruction::FPToSI:
6424+
case Instruction::FPToUI:
6425+
return true;
6426+
// Proper FP math operations ignore the sign bit of NaN.
6427+
case Instruction::FAdd:
6428+
case Instruction::FSub:
6429+
case Instruction::FMul:
6430+
case Instruction::FDiv:
6431+
case Instruction::FRem:
6432+
case Instruction::FPTrunc:
6433+
case Instruction::FPExt:
6434+
case Instruction::FCmp:
6435+
return true;
6436+
// Bitwise FP operations should preserve the sign bit of NaN.
6437+
case Instruction::FNeg:
6438+
case Instruction::Select:
6439+
case Instruction::PHI:
6440+
return false;
6441+
case Instruction::Ret:
6442+
return I.getFunction()->getAttributes().getRetNoFPClass() &
6443+
FPClassTest::fcNan;
6444+
case Instruction::Call:
6445+
case Instruction::Invoke: {
6446+
if (auto *II = dyn_cast<IntrinsicInst>(User)) {
6447+
switch (II->getIntrinsicID()) {
6448+
case Intrinsic::fabs:
6449+
return true;
6450+
case Intrinsic::copysign:
6451+
return II->getArgOperand(0) == &I;
6452+
// Other proper FP math intrinsics ignore the sign bit of NaN.
6453+
case Intrinsic::maxnum:
6454+
case Intrinsic::minnum:
6455+
case Intrinsic::maximum:
6456+
case Intrinsic::minimum:
6457+
case Intrinsic::maximumnum:
6458+
case Intrinsic::minimumnum:
6459+
case Intrinsic::canonicalize:
6460+
case Intrinsic::fma:
6461+
case Intrinsic::fmuladd:
6462+
case Intrinsic::sqrt:
6463+
case Intrinsic::pow:
6464+
case Intrinsic::powi:
6465+
case Intrinsic::fptoui_sat:
6466+
case Intrinsic::fptosi_sat:
6467+
case Intrinsic::is_fpclass:
6468+
case Intrinsic::vp_is_fpclass:
6469+
return true;
6470+
default:
6471+
return false;
6472+
}
6473+
}
6474+
6475+
FPClassTest NoFPClass = cast<CallBase>(User)->getParamNoFPClass(
6476+
I.uses().begin()->getOperandNo());
6477+
return NoFPClass & FPClassTest::fcNan;
6478+
}
6479+
default:
6480+
return false;
6481+
}
6482+
}
6483+
63606484
Value *llvm::isBytewiseValue(Value *V, const DataLayout &DL) {
63616485

63626486
// All byte-wide stores are splatable, even of arbitrary variables.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 0 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,128 +2773,6 @@ Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond(Value *Op,
27732773
return nullptr;
27742774
}
27752775

2776-
/// Return true if the sign bit of result can be ignored when the result is
2777-
/// zero.
2778-
static bool ignoreSignBitOfZero(Instruction &I) {
2779-
if (I.hasNoSignedZeros())
2780-
return true;
2781-
2782-
// Check if the sign bit is ignored by the only user.
2783-
if (!I.hasOneUse())
2784-
return false;
2785-
Instruction *User = I.user_back();
2786-
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
2787-
if (FPOp->hasNoSignedZeros())
2788-
return true;
2789-
}
2790-
2791-
switch (User->getOpcode()) {
2792-
case Instruction::FPToSI:
2793-
case Instruction::FPToUI:
2794-
return true;
2795-
case Instruction::FCmp:
2796-
// fcmp treats both positive and negative zero as equal.
2797-
return true;
2798-
case Instruction::Call:
2799-
if (auto *II = dyn_cast<IntrinsicInst>(User)) {
2800-
switch (II->getIntrinsicID()) {
2801-
case Intrinsic::fabs:
2802-
return true;
2803-
case Intrinsic::copysign:
2804-
return II->getArgOperand(0) == &I;
2805-
case Intrinsic::is_fpclass:
2806-
case Intrinsic::vp_is_fpclass: {
2807-
auto Test =
2808-
static_cast<FPClassTest>(
2809-
cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()) &
2810-
FPClassTest::fcZero;
2811-
return Test == FPClassTest::fcZero || Test == FPClassTest::fcNone;
2812-
}
2813-
default:
2814-
return false;
2815-
}
2816-
}
2817-
return false;
2818-
default:
2819-
return false;
2820-
}
2821-
}
2822-
2823-
/// Return true if the sign bit of result can be ignored when the result is NaN.
2824-
static bool ignoreSignBitOfNaN(Instruction &I) {
2825-
if (I.hasNoNaNs())
2826-
return true;
2827-
2828-
// Check if the sign bit is ignored by the only user.
2829-
if (!I.hasOneUse())
2830-
return false;
2831-
Instruction *User = I.user_back();
2832-
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
2833-
if (FPOp->hasNoNaNs())
2834-
return true;
2835-
}
2836-
2837-
switch (User->getOpcode()) {
2838-
case Instruction::FPToSI:
2839-
case Instruction::FPToUI:
2840-
return true;
2841-
// Proper FP math operations ignore the sign bit of NaN.
2842-
case Instruction::FAdd:
2843-
case Instruction::FSub:
2844-
case Instruction::FMul:
2845-
case Instruction::FDiv:
2846-
case Instruction::FRem:
2847-
case Instruction::FPTrunc:
2848-
case Instruction::FPExt:
2849-
case Instruction::FCmp:
2850-
return true;
2851-
// Bitwise FP operations should preserve the sign bit of NaN.
2852-
case Instruction::FNeg:
2853-
case Instruction::Select:
2854-
case Instruction::PHI:
2855-
return false;
2856-
case Instruction::Ret:
2857-
return I.getFunction()->getAttributes().getRetNoFPClass() &
2858-
FPClassTest::fcNan;
2859-
case Instruction::Call:
2860-
case Instruction::Invoke: {
2861-
if (auto *II = dyn_cast<IntrinsicInst>(User)) {
2862-
switch (II->getIntrinsicID()) {
2863-
case Intrinsic::fabs:
2864-
return true;
2865-
case Intrinsic::copysign:
2866-
return II->getArgOperand(0) == &I;
2867-
// Other proper FP math intrinsics ignore the sign bit of NaN.
2868-
case Intrinsic::maxnum:
2869-
case Intrinsic::minnum:
2870-
case Intrinsic::maximum:
2871-
case Intrinsic::minimum:
2872-
case Intrinsic::maximumnum:
2873-
case Intrinsic::minimumnum:
2874-
case Intrinsic::canonicalize:
2875-
case Intrinsic::fma:
2876-
case Intrinsic::fmuladd:
2877-
case Intrinsic::sqrt:
2878-
case Intrinsic::pow:
2879-
case Intrinsic::powi:
2880-
case Intrinsic::fptoui_sat:
2881-
case Intrinsic::fptosi_sat:
2882-
case Intrinsic::is_fpclass:
2883-
return true;
2884-
default:
2885-
return false;
2886-
}
2887-
}
2888-
2889-
FPClassTest NoFPClass = cast<CallBase>(User)->getParamNoFPClass(
2890-
I.uses().begin()->getOperandNo());
2891-
return NoFPClass & FPClassTest::fcNan;
2892-
}
2893-
default:
2894-
return false;
2895-
}
2896-
}
2897-
28982776
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
28992777
// fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work.
29002778
static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,

0 commit comments

Comments
 (0)