https://github.com/paulwalker-arm created https://github.com/llvm/llvm-project/pull/204333
This follows on from https://github.com/llvm/llvm-project/pull/198496#discussion_r3266473201 and https://github.com/llvm/llvm-project/pull/198496#discussion_r3267459947. I opted for isMinusOne() rather than isNegOne() because the former is already in use, plus I think it reads better. I haven't surfaced isPowerOf2(N) into the constant classes because I'm unsure if we really want to use it. I'll take recommendations because I didn't fancy adding functions for every number (i.e. if Half(), isTwo() ...) and yet isPowerOf2(-2), isPowerOf2(1) seems less clear than isExactValue(0.5), isExactValue(2.0). I wondered about using an enum variant of isPowerOf2(), but figured that's no better than adding dedicated functions. With +-0.0/1.0 covered there are not many uses of isExactlyValue() so perhaps it's not worth worrying about? >From 17e3058fc8ca8beb2c78d07f15080758e78a7776 Mon Sep 17 00:00:00 2001 From: Paul Walker <[email protected]> Date: Wed, 20 May 2026 14:24:56 +0000 Subject: [PATCH 1/2] [APFloat] Add is{Neg}PowerOf2(N) methods. --- llvm/include/llvm/ADT/APFloat.h | 10 ++++++++++ llvm/unittests/ADT/APFloatTest.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index b2eb5b93d5331..e791e36fcc925 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -1603,6 +1603,16 @@ class APFloat : public APFloatBase { return isNegative() ? INT_MIN : getExactLog2Abs(); } + // Returns true if this value is exactly 2^N. + LLVM_READONLY + bool isPowerOf2(int N) const { return N != INT_MIN && getExactLog2() == N; } + + // Returns true if this value is exactly -(2^N). + LLVM_READONLY + bool isNegPowerOf2(int N) const { + return N != INT_MIN && isNegative() && getExactLog2Abs() == N; + } + LLVM_ABI friend hash_code hash_value(const APFloat &Arg); friend int ilogb(const APFloat &Arg); friend APFloat scalbn(APFloat X, int Exp, roundingMode RM); diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 6841d4bcb6093..0913a44f7effb 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -9420,6 +9420,32 @@ TEST(APFloatTest, getExactLog2) { } } +TEST(APFloatTest, isPowerOf2) { + const fltSemantics &Semantics = APFloat::IEEEdouble(); + + EXPECT_TRUE(APFloat(Semantics, "1.0").isPowerOf2(0)); + EXPECT_TRUE(APFloat(Semantics, "8.0").isPowerOf2(3)); + EXPECT_TRUE(APFloat(Semantics, "0.25").isPowerOf2(-2)); + + EXPECT_FALSE(APFloat(Semantics, "3.0").isPowerOf2(1)); + EXPECT_FALSE(APFloat(Semantics, "-8.0").isPowerOf2(3)); + EXPECT_FALSE(APFloat(Semantics, "-8.0").isPowerOf2(INT_MIN)); + EXPECT_FALSE(APFloat::getZero(Semantics, false).isPowerOf2(0)); + EXPECT_FALSE(APFloat::getInf(Semantics).isPowerOf2(0)); + EXPECT_FALSE(APFloat::getNaN(Semantics, false).isPowerOf2(0)); + + EXPECT_TRUE(APFloat(Semantics, "-1.0").isNegPowerOf2(0)); + EXPECT_TRUE(APFloat(Semantics, "-8.0").isNegPowerOf2(3)); + EXPECT_TRUE(APFloat(Semantics, "-0.25").isNegPowerOf2(-2)); + + EXPECT_FALSE(APFloat(Semantics, "-3.0").isNegPowerOf2(1)); + EXPECT_FALSE(APFloat(Semantics, "8.0").isNegPowerOf2(3)); + EXPECT_FALSE(APFloat(Semantics, "8.0").isNegPowerOf2(INT_MIN)); + EXPECT_FALSE(APFloat::getZero(Semantics, false).isNegPowerOf2(0)); + EXPECT_FALSE(APFloat::getInf(Semantics).isNegPowerOf2(0)); + EXPECT_FALSE(APFloat::getNaN(Semantics, false).isNegPowerOf2(0)); +} + TEST(APFloatTest, Float8E8M0FNUGetZero) { #ifdef GTEST_HAS_DEATH_TEST #ifndef NDEBUG >From daf915a6260abd1a0a2f06b84c9e29d31b05f039 Mon Sep 17 00:00:00 2001 From: Paul Walker <[email protected]> Date: Wed, 27 May 2026 17:18:06 +0100 Subject: [PATCH 2/2] Replace instance of isExactlyValue(+/-1.0) with isOne/isMinusOne. --- clang/lib/AST/ByteCode/Floating.h | 4 +-- llvm/include/llvm/ADT/APFloat.h | 6 ++++ llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 6 ++++ llvm/include/llvm/IR/Constants.h | 6 ++++ llvm/lib/Analysis/ConstantFolding.cpp | 6 ++-- .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 2 +- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 28 +++++++++---------- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 +++--- .../lib/Target/AArch64/AArch64InstrFormats.td | 2 +- .../Target/AMDGPU/AMDGPUCodeGenPrepare.cpp | 7 ++--- llvm/lib/Target/AMDGPU/AMDGPUInstructions.td | 2 +- .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 8 +++--- llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp | 4 +-- .../Target/AMDGPU/AMDGPURegBankCombiner.cpp | 6 ++-- llvm/lib/Target/AMDGPU/R600ISelLowering.cpp | 4 +-- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 17 ++++++----- .../LoongArch/LoongArchISelLowering.cpp | 4 +-- .../Target/LoongArch/LoongArchInstrInfo.td | 2 +- llvm/lib/Target/NVPTX/NVPTXInstrInfo.td | 4 +-- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 6 ++-- llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp | 2 +- llvm/lib/Target/X86/X86InstrFragments.td | 4 +-- llvm/lib/Transforms/Scalar/Reassociate.cpp | 2 +- .../llvm-reduce/deltas/ReduceOperands.cpp | 3 +- llvm/unittests/IR/MDBuilderTest.cpp | 2 +- 25 files changed, 80 insertions(+), 65 deletions(-) diff --git a/clang/lib/AST/ByteCode/Floating.h b/clang/lib/AST/ByteCode/Floating.h index cc918dc12deb6..f848538a73b90 100644 --- a/clang/lib/AST/ByteCode/Floating.h +++ b/clang/lib/AST/ByteCode/Floating.h @@ -144,7 +144,7 @@ class Floating final { bool isZero() const { return getValue().isZero(); } bool isNonZero() const { return getValue().isNonZero(); } bool isMin() const { return getValue().isSmallest(); } - bool isMinusOne() const { return getValue().isExactlyValue(-1.0); } + bool isMinusOne() const { return getValue().isMinusOne(); } bool isNan() const { return getValue().isNaN(); } bool isSignaling() const { return getValue().isSignaling(); } bool isInf() const { return getValue().isInfinity(); } @@ -166,7 +166,7 @@ class Floating final { case llvm::APFloatBase::cmpUnordered: return ComparisonCategoryResult::Unordered; } - llvm_unreachable("Inavlid cmpResult value"); + llvm_unreachable("Invalid cmpResult value"); } static APFloat::opStatus fromIntegral(APSInt Val, diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index e791e36fcc925..32f846b9c9594 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -1613,6 +1613,12 @@ class APFloat : public APFloatBase { return N != INT_MIN && isNegative() && getExactLog2Abs() == N; } + // Returns true if this value is exactly +1.0. + LLVM_READONLY bool isOne() const { return isPowerOf2(0); } + + // Returns true if this value is exactly -1.0. + LLVM_READONLY bool isMinusOne() const { return isNegPowerOf2(0); } + LLVM_ABI friend hash_code hash_value(const APFloat &Arg); friend int ilogb(const APFloat &Arg); friend APFloat scalbn(APFloat X, int Exp, roundingMode RM); diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 6292dcd97fc8d..b280bd48c94e9 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1895,6 +1895,12 @@ class ConstantFPSDNode : public SDNode { /// Return true if the value is negative. bool isNegative() const { return Value->isNegative(); } + /// Returns true if this value is exactly +1.0. + bool isOne() const { return Value->isOne(); } + + /// Returns true if this value is exactly -1.0. + bool isMinusOne() const { return Value->isMinusOne(); } + /// We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index d1a65db0af31f..d5299aebd16fe 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -481,6 +481,12 @@ class ConstantFP final : public ConstantData { /// Return true if the value is a NaN. bool isNaN() const { return Val.isNaN(); } + /// Returns true if this value is exactly +1.0. + bool isOne() const { return Val.isOne(); } + + /// Returns true if this value is exactly -1.0. + bool isMinusOne() const { return Val.isMinusOne(); } + /// We don't rely on operator== working on double values, as it returns true /// for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 3fe78d6c4322d..92d3dadced29b 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2845,7 +2845,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, return ConstantFP::getInfinity(Ty, true); if (U.isNegative()) return ConstantFP::getNaN(Ty); - if (U.isExactlyValue(1.0)) + if (U.isOne()) return ConstantFP::getZero(Ty); return ConstantFoldFP(log, APF, Ty); case Intrinsic::log2: @@ -2853,7 +2853,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, return ConstantFP::getInfinity(Ty, true); if (U.isNegative()) return ConstantFP::getNaN(Ty); - if (U.isExactlyValue(1.0)) + if (U.isOne()) return ConstantFP::getZero(Ty); // TODO: What about hosts that lack a C99 library? return ConstantFoldFP(log2, APF, Ty); @@ -2862,7 +2862,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, return ConstantFP::getInfinity(Ty, true); if (U.isNegative()) return ConstantFP::getNaN(Ty); - if (U.isExactlyValue(1.0)) + if (U.isOne()) return ConstantFP::getZero(Ty); // TODO: What about hosts that lack a C99 library? return ConstantFoldFP(log10, APF, Ty); diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 3cc00d816c0e6..5b1f9a744514e 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -7017,7 +7017,7 @@ bool CombinerHelper::matchRepeatedFPDivisor( auto IsOne = [this](Register X) { auto N0CFP = isConstantOrConstantSplatVectorFP(*MRI.getVRegDef(X), MRI); - return N0CFP && (N0CFP->isExactlyValue(1.0) || N0CFP->isExactlyValue(-1.0)); + return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne()); }; // Skip if current node is a reciprocal/fneg-reciprocal. diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 7fdaacff0582d..05358ebea8cd9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -18781,10 +18781,10 @@ SDValue DAGCombiner::visitFMULForFMADistributiveCombine(SDNode *N) { auto FuseFADD = [&](SDValue X, SDValue Y) { if (X.getOpcode() == ISD::FADD && (Aggressive || X->hasOneUse())) { if (auto *C = isConstOrConstSplatFP(X.getOperand(1), true)) { - if (C->isExactlyValue(+1.0)) + if (C->isOne()) return DAG.getNode(PreferredFusedOpcode, SL, VT, X.getOperand(0), Y, Y); - if (C->isExactlyValue(-1.0)) + if (C->isMinusOne()) return DAG.getNode(PreferredFusedOpcode, SL, VT, X.getOperand(0), Y, DAG.getNode(ISD::FNEG, SL, VT, Y)); } @@ -18804,20 +18804,20 @@ SDValue DAGCombiner::visitFMULForFMADistributiveCombine(SDNode *N) { auto FuseFSUB = [&](SDValue X, SDValue Y) { if (X.getOpcode() == ISD::FSUB && (Aggressive || X->hasOneUse())) { if (auto *C0 = isConstOrConstSplatFP(X.getOperand(0), true)) { - if (C0->isExactlyValue(+1.0)) + if (C0->isOne()) return DAG.getNode(PreferredFusedOpcode, SL, VT, DAG.getNode(ISD::FNEG, SL, VT, X.getOperand(1)), Y, Y); - if (C0->isExactlyValue(-1.0)) + if (C0->isMinusOne()) return DAG.getNode(PreferredFusedOpcode, SL, VT, DAG.getNode(ISD::FNEG, SL, VT, X.getOperand(1)), Y, DAG.getNode(ISD::FNEG, SL, VT, Y)); } if (auto *C1 = isConstOrConstSplatFP(X.getOperand(1), true)) { - if (C1->isExactlyValue(+1.0)) + if (C1->isOne()) return DAG.getNode(PreferredFusedOpcode, SL, VT, X.getOperand(0), Y, DAG.getNode(ISD::FNEG, SL, VT, Y)); - if (C1->isExactlyValue(-1.0)) + if (C1->isMinusOne()) return DAG.getNode(PreferredFusedOpcode, SL, VT, X.getOperand(0), Y, Y); } @@ -19300,7 +19300,7 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) { return DAG.getNode(ISD::FADD, DL, VT, N0, N0); // fold (fmul X, -1.0) -> (fsub -0.0, X) - if (N1CFP && N1CFP->isExactlyValue(-1.0)) { + if (N1CFP && N1CFP->isMinusOne()) { if (!LegalOperations || TLI.isOperationLegal(ISD::FSUB, VT)) { return DAG.getNode(ISD::FSUB, DL, VT, DAG.getConstantFP(-0.0, DL, VT), N0, Flags); @@ -19356,11 +19356,11 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) { case ISD::SETUGE: case ISD::SETGT: case ISD::SETGE: - if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) && + if (TrueOpnd->isMinusOne() && FalseOpnd->isOne() && TLI.isOperationLegal(ISD::FNEG, VT)) return DAG.getNode(ISD::FNEG, DL, VT, DAG.getNode(ISD::FABS, DL, VT, X)); - if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0)) + if (TrueOpnd->isOne() && FalseOpnd->isMinusOne()) return DAG.getNode(ISD::FABS, DL, VT, X); break; @@ -19424,9 +19424,9 @@ SDValue DAGCombiner::visitFMA(SDNode *N) { } } - if (N0CFP && N0CFP->isExactlyValue(1.0)) + if (N0CFP && N0CFP->isOne()) return DAG.getNode(ISD::FADD, DL, VT, N1, N2); - if (N1CFP && N1CFP->isExactlyValue(1.0)) + if (N1CFP && N1CFP->isOne()) return DAG.getNode(ISD::FADD, DL, VT, N0, N2); // Canonicalize (fma c, x, y) -> (fma x, c, y) @@ -19456,10 +19456,10 @@ SDValue DAGCombiner::visitFMA(SDNode *N) { // (fma x, -1, y) -> (fadd (fneg x), y) if (N1CFP) { - if (N1CFP->isExactlyValue(1.0)) + if (N1CFP->isOne()) return DAG.getNode(ISD::FADD, DL, VT, N0, N2); - if (N1CFP->isExactlyValue(-1.0) && + if (N1CFP->isMinusOne() && (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))) { SDValue RHSNeg = DAG.getNode(ISD::FNEG, DL, VT, N0); AddToWorklist(RHSNeg.getNode()); @@ -19548,7 +19548,7 @@ SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) { // Skip if current node is a reciprocal/fneg-reciprocal. SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); ConstantFPSDNode *N0CFP = isConstOrConstSplatFP(N0, /* AllowUndefs */ true); - if (N0CFP && (N0CFP->isExactlyValue(1.0) || N0CFP->isExactlyValue(-1.0))) + if (N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne())) return SDValue(); // Exit early if the target does not want this transform or if there can't diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 534ba48bd5d1a..631b4d07e8004 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -11682,7 +11682,7 @@ SDValue SelectionDAG::simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y, // X * 1.0 --> X // X / 1.0 --> X if (Opcode == ISD::FMUL || Opcode == ISD::FDIV) - if (YC->getValueAPF().isExactlyValue(1.0)) + if (YC->getValueAPF().isOne()) return X; // X * 0.0 --> 0.0 @@ -13699,9 +13699,9 @@ bool SelectionDAG::isIdentityElement(unsigned Opcode, SDNodeFlags Flags, return OperandNo == 1 && ConstFP->isZero() && (Flags.hasNoSignedZeros() || !ConstFP->isNegative()); case ISD::FMUL: - return ConstFP->isExactlyValue(1.0); + return ConstFP->isOne(); case ISD::FDIV: - return OperandNo == 1 && ConstFP->isExactlyValue(1.0); + return OperandNo == 1 && ConstFP->isOne(); case ISD::FMINNUM: case ISD::FMAXNUM: { // Neutral element for fminnum is NaN, Inf or FLT_MAX, depending on FMF. @@ -13856,7 +13856,7 @@ bool llvm::isOneOrOneSplat(SDValue N, bool AllowUndefs) { bool llvm::isOneOrOneSplatFP(SDValue N, bool AllowUndefs) { ConstantFPSDNode *C = isConstOrConstSplatFP(N, AllowUndefs); - return C && C->isExactlyValue(1.0); + return C && C->isOne(); } bool llvm::isAllOnesOrAllOnesSplat(SDValue N, bool AllowUndefs) { diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index 787a11401cb6e..daf53c99988b0 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1568,7 +1568,7 @@ def fpimm_half : FPImmLeaf<fAny, [{ }]>; def fpimm_one : FPImmLeaf<fAny, [{ - return Imm.isExactlyValue(+1.0); + return Imm.isOne(); }]>; def fpimm_two : FPImmLeaf<fAny, [{ diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp index 394c2326a64ef..486b0dd62d371 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp @@ -738,7 +738,7 @@ Value *AMDGPUCodeGenPrepareImpl::optimizeWithRsq( bool IsNegative = false; // TODO: Handle other numerator values with arcp. - if (CLHS->isExactlyValue(1.0) || (IsNegative = CLHS->isExactlyValue(-1.0))) { + if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) { // Add in the sqrt flags. IRBuilder<>::FastMathFlagGuard Guard(Builder); Builder.setFastMathFlags(DivFMF | SqrtFMF); @@ -779,8 +779,7 @@ AMDGPUCodeGenPrepareImpl::optimizeWithRcp(IRBuilder<> &Builder, Value *Num, if (const ConstantFP *CLHS = dyn_cast<ConstantFP>(Num)) { bool IsNegative = false; - if (CLHS->isExactlyValue(1.0) || - (IsNegative = CLHS->isExactlyValue(-1.0))) { + if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) { Value *Src = Den; if (HasFP32DenormalFlush || FMF.approxFunc()) { @@ -843,7 +842,7 @@ Value *AMDGPUCodeGenPrepareImpl::optimizeWithFDivFast( bool NumIsOne = false; if (const ConstantFP *CNum = dyn_cast<ConstantFP>(Num)) { - if (CNum->isExactlyValue(+1.0) || CNum->isExactlyValue(-1.0)) + if (CNum->isOne() || CNum->isMinusOne()) NumIsOne = true; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td index 11d8aef61c858..2387afe1cd362 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td @@ -766,7 +766,7 @@ int BF16_NEG_ONE = 0xBF80; def CONST : Constants; def fpimm_zero : FPImmLeaf<fAny, [{ return Imm.isZero(); }]> ; -def fpimm_one : FPImmLeaf<fAny, [{ return Imm.isExactlyValue(+1.0); }]> ; +def fpimm_one : FPImmLeaf<fAny, [{ return Imm.isOne(); }]> ; def fpimm_half : FPImmLeaf<fAny, [{ return Imm.isExactlyValue(+0.5); }]> ; /* Generic helper patterns for intrinsics */ diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 65ae77cec0846..57d7d42bb5b9c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -5514,7 +5514,7 @@ bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV(MachineInstr &MI, // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp. // 1 / x -> RCP(x) - if (CLHS->isExactlyValue(1.0)) { + if (CLHS->isOne()) { B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res) .addUse(RHS) .setMIFlags(Flags); @@ -5524,7 +5524,7 @@ bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV(MachineInstr &MI, } // -1 / x -> RCP( FNEG(x) ) - if (CLHS->isExactlyValue(-1.0)) { + if (CLHS->isMinusOne()) { auto FNeg = B.buildFNeg(ResTy, RHS, Flags); B.buildIntrinsic(Intrinsic::amdgcn_rcp, Res) .addUse(FNeg.getReg(0)) @@ -5566,7 +5566,7 @@ bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV64(MachineInstr &MI, return false; const ConstantFP *CLHS = getConstantFPVRegVal(X, MRI); - bool IsNegRcp = CLHS && CLHS->isExactlyValue(-1.0); + bool IsNegRcp = CLHS && CLHS->isMinusOne(); // Pull out the negation so it folds for free into the source modifiers. if (IsNegRcp) @@ -5588,7 +5588,7 @@ bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV64(MachineInstr &MI, R = B.buildFMA(ResTy, Tmp1, R, R); // Skip the last 2 correction terms for reciprocal. - if (IsNegRcp || (CLHS && CLHS->isExactlyValue(1.0))) { + if (IsNegRcp || (CLHS && CLHS->isOne())) { B.buildCopy(Res, R); MI.eraseFromParent(); return true; diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp index 2d1cc1c0c66c0..f01487effb8ad 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -908,7 +908,7 @@ bool AMDGPULibCalls::fold_pow(FPMathOperator *FPOp, IRBuilder<> &B, replaceCall(FPOp, cnval); return true; } - if ((CF && CF->isExactlyValue(1.0)) || (CINT && ci_opr1 == 1)) { + if ((CF && CF->isOne()) || (CINT && ci_opr1 == 1)) { // pow/powr/pown(x, 1.0) = x LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << "\n"); replaceCall(FPOp, opr0); @@ -922,7 +922,7 @@ bool AMDGPULibCalls::fold_pow(FPMathOperator *FPOp, IRBuilder<> &B, replaceCall(FPOp, nval); return true; } - if ((CF && CF->isExactlyValue(-1.0)) || (CINT && ci_opr1 == -1)) { + if ((CF && CF->isMinusOne()) || (CINT && ci_opr1 == -1)) { // pow/powr/pown(x, -1.0) = 1.0/x LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1 / " << *opr0 << "\n"); Constant *cnval = ConstantFP::get(eltType, 1.0); diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp index 74184333e5b69..f9d8a09e29b0d 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp @@ -297,7 +297,7 @@ bool AMDGPURegBankCombinerImpl::matchFPMinMaxToClamp(MachineInstr &MI, if (!matchMed<GFCstOrSplatGFCstMatch>(MI, MRI, OpcodeTriple, Val, K0, K1)) return false; - if (!K0->Value.isPosZero() || !K1->Value.isExactlyValue(1.0)) + if (!K0->Value.isPosZero() || !K1->Value.isOne()) return false; // For IEEE=false perform combine only when it's safe to assume that there are @@ -596,8 +596,8 @@ bool AMDGPURegBankCombinerImpl::isClampZeroToOne(MachineInstr *K0, if (isFCst(K0) && isFCst(K1)) { const ConstantFP *KO_FPImm = K0->getOperand(1).getFPImm(); const ConstantFP *K1_FPImm = K1->getOperand(1).getFPImm(); - return (KO_FPImm->isPosZero() && K1_FPImm->isExactlyValue(1.0)) || - (KO_FPImm->isExactlyValue(1.0) && K1_FPImm->isPosZero()); + return (KO_FPImm->isPosZero() && K1_FPImm->isOne()) || + (KO_FPImm->isOne() && K1_FPImm->isPosZero()); } return false; } diff --git a/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp b/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp index ae8e73eb5f329..79ef880fb569a 100644 --- a/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp @@ -791,7 +791,7 @@ bool R600TargetLowering::isZero(SDValue Op) const { bool R600TargetLowering::isHWTrueValue(SDValue Op) const { if (ConstantFPSDNode * CFP = dyn_cast<ConstantFPSDNode>(Op)) { - return CFP->isExactlyValue(1.0); + return CFP->isOne(); } return isAllOnesConstant(Op); } @@ -1586,7 +1586,7 @@ static SDValue CompactSwizzlableVector( if (C->isZero()) { RemapSwizzle[i] = 4; // SEL_0 NewBldVec[i] = DAG.getUNDEF(MVT::f32); - } else if (C->isExactlyValue(1.0)) { + } else if (C->isOne()) { RemapSwizzle[i] = 5; // SEL_1 NewBldVec[i] = DAG.getUNDEF(MVT::f32); } diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index e22acbe288d0d..375ed3a6eb1ce 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -13274,7 +13274,7 @@ SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op, if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16) return SDValue(); - if (CLHS->isExactlyValue(1.0)) { + if (CLHS->isOne()) { // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to // the CI documentation has a worst case error of 1 ulp. // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to @@ -13291,7 +13291,7 @@ SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op, } // Same as for 1.0, but expand the sign out of the constant. - if (CLHS->isExactlyValue(-1.0)) { + if (CLHS->isMinusOne()) { // -1.0 / x -> rcp (fneg x) SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS); return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS); @@ -13323,7 +13323,7 @@ SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op, return SDValue(); const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X); - bool IsNegRcp = CLHS && CLHS->isExactlyValue(-1.0); + bool IsNegRcp = CLHS && CLHS->isMinusOne(); // Pull out the negation so it folds for free into the source modifiers. if (IsNegRcp) @@ -13343,7 +13343,7 @@ SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op, R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R); // Skip the last 2 correction terms for reciprocal. - if (IsNegRcp || (CLHS && CLHS->isExactlyValue(1.0))) + if (IsNegRcp || (CLHS && CLHS->isOne())) return R; SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R); @@ -16228,7 +16228,7 @@ SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG, // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the // hardware fmed3 behavior converting to a min. // FIXME: Should this be allowing -0.0? - if (K1->isExactlyValue(1.0) && K0->isPosZero()) + if (K1->isOne() && K0->isPosZero()) return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0)); } @@ -16426,8 +16426,8 @@ static bool isClampZeroToOne(SDValue A, SDValue B) { if (ConstantFPSDNode *CA = dyn_cast<ConstantFPSDNode>(A)) { if (ConstantFPSDNode *CB = dyn_cast<ConstantFPSDNode>(B)) { // FIXME: Should this be allowing -0.0? - return (CA->isPosZero() && CB->isExactlyValue(1.0)) || - (CA->isExactlyValue(1.0) && CB->isPosZero()); + return (CA->isPosZero() && CB->isOne()) || + (CA->isOne() && CB->isPosZero()); } } @@ -17817,8 +17817,7 @@ SDValue SITargetLowering::performFDivCombine(SDNode *N, if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) { bool IsNegative = false; - if (CLHS->isExactlyValue(1.0) || - (IsNegative = CLHS->isExactlyValue(-1.0))) { + if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) { // fdiv contract 1.0, (sqrt contract x) -> rsq // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq) if (RHS.getOpcode() == ISD::FSQRT) { diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 4e71b6d3949fb..0ad651c03abde 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -924,7 +924,7 @@ SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op, // use floating point load from the constant pool. auto Seq = LoongArchMatInt::generateInstSeq(INTVal.getSExtValue()); int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1); - if (InsNum > MaterializeFPImmInsNum && !FPVal.isExactlyValue(+1.0)) + if (InsNum > MaterializeFPImmInsNum && !FPVal.isOne()) return SDValue(); switch (VT.getSimpleVT().SimpleTy) { @@ -10419,7 +10419,7 @@ bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, return false; if (VT == MVT::f64 && !Subtarget.hasBasicD()) return false; - return (Imm.isZero() || Imm.isExactlyValue(1.0) || isFPImmVLDILegal(Imm, VT)); + return (Imm.isZero() || Imm.isOne() || isFPImmVLDILegal(Imm, VT)); } bool LoongArchTargetLowering::isCheapToSpeculateCttz(Type *) const { diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index 019539fbeab47..6aacfd8138ff5 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -579,7 +579,7 @@ def NegImm : SDNodeXForm<imm, [{ // FP immediate patterns. def fpimm0 : PatLeaf<(fpimm), [{return N->isPosZero();}]>; def fpimm0neg : PatLeaf<(fpimm), [{return N->isNegZero();}]>; -def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>; +def fpimm1 : PatLeaf<(fpimm), [{return N->isOne();}]>; // Return an immediate subtracted from 32. def ImmSubFrom32 : SDNodeXForm<imm, [{ diff --git a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td index ff3e5144c6fbe..5f1c16dc7f0fb 100644 --- a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td +++ b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td @@ -187,8 +187,8 @@ class zeroinitializer<ValueType vt> : def fpimm_pos_inf : FPImmLeaf<fAny, [{ return Imm.isPosInfinity(); }]>; def fpimm_0 : FPImmLeaf<fAny, [{ return Imm.isZero(); }]>; -def fpimm_1 : FPImmLeaf<fAny, [{ return Imm.isExactlyValue(1.0); }]>; -def fpimm_neg_1 : FPImmLeaf<fAny, [{ return Imm.isExactlyValue(-1.0); }]>; +def fpimm_1 : FPImmLeaf<fAny, [{ return Imm.isOne(); }]>; +def fpimm_neg_1 : FPImmLeaf<fAny, [{ return Imm.isMinusOne(); }]>; // Operands which can hold a Register or an Immediate. diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index c7010c95bfc07..cb7c3d823eeb5 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -10227,9 +10227,9 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const { const ConstantFPSDNode *FPTV = dyn_cast<ConstantFPSDNode>(TrueV); const ConstantFPSDNode *FPFV = dyn_cast<ConstantFPSDNode>(FalseV); if (FPTV && FPFV) { - if (FPTV->isExactlyValue(1.0) && FPFV->isPosZero()) + if (FPTV->isOne() && FPFV->isPosZero()) return DAG.getNode(ISD::SINT_TO_FP, DL, VT, CondV); - if (FPTV->isPosZero() && FPFV->isExactlyValue(1.0)) { + if (FPTV->isPosZero() && FPFV->isOne()) { SDValue XOR = DAG.getNode(ISD::XOR, DL, XLenVT, CondV, DAG.getConstant(1, DL, XLenVT)); return DAG.getNode(ISD::SINT_TO_FP, DL, VT, XOR); @@ -21779,7 +21779,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, if (N0->getOpcode() != ISD::FCOPYSIGN) return SDValue(); ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N0->getOperand(0)); - if (!C || !C->getValueAPF().isExactlyValue(+1.0)) + if (!C || !C->getValueAPF().isOne()) return SDValue(); if (VT.isVector() || !isOperationLegal(ISD::FCOPYSIGN, VT)) return SDValue(); diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp index e4af82b11e7d8..660bee0f7a2cd 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp @@ -150,7 +150,7 @@ bool SPIRVCombinerHelper::matchSelectToFaceForward(MachineInstr &MI) const { mi_match(FalseReg, MRI, m_GFMul(m_GFCstOrSplat(MulConstant), m_SpecificReg(TrueReg)))) { - if (!MulConstant || !MulConstant->Value.isExactlyValue(-1.0)) + if (!MulConstant || !MulConstant->Value.isMinusOne()) return false; } else if (!AreNegatedConstantsOrSplats(TrueReg, FalseReg)) return false; diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td index 9316360c5e02a..fb5cdb21c8d7e 100644 --- a/llvm/lib/Target/X86/X86InstrFragments.td +++ b/llvm/lib/Target/X86/X86InstrFragments.td @@ -1056,9 +1056,9 @@ def fpimmneg0 : FPImmLeaf<fAny, [{ }]>; def fpimm1 : FPImmLeaf<fAny, [{ - return Imm.isExactlyValue(+1.0); + return Imm.isOne(); }]>; def fpimmneg1 : FPImmLeaf<fAny, [{ - return Imm.isExactlyValue(-1.0); + return Imm.isMinusOne(); }]>; diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp index 1d90cd5fe87e7..636e9ccb265ca 100644 --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -2333,7 +2333,7 @@ void ReassociatePass::ReassociateExpression(BinaryOperator *I) { cast<Instruction>(I->user_back())->getOpcode() == Instruction::FAdd && isa<ConstantFP>(Ops.back().Op) && - cast<ConstantFP>(Ops.back().Op)->isExactlyValue(-1.0)) { + cast<ConstantFP>(Ops.back().Op)->isMinusOne()) { ValueEntry Tmp = Ops.pop_back_val(); Ops.insert(Ops.begin(), Tmp); } diff --git a/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp b/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp index 79272fe2eaeb7..a85131e6e01dd 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp @@ -57,8 +57,7 @@ static bool isZero(Use &Op) { static bool isZeroOrOneFP(Value *Op) { const APFloat *C; - return match(Op, m_APFloat(C)) && - ((C->isZero() && !C->isNegative()) || C->isExactlyValue(1.0)); + return match(Op, m_APFloat(C)) && (C->isPosZero() || C->isOne()); } static bool shouldReduceOperand(Use &Op) { diff --git a/llvm/unittests/IR/MDBuilderTest.cpp b/llvm/unittests/IR/MDBuilderTest.cpp index 4656c70ce9cad..a923418a05d64 100644 --- a/llvm/unittests/IR/MDBuilderTest.cpp +++ b/llvm/unittests/IR/MDBuilderTest.cpp @@ -40,7 +40,7 @@ TEST_F(MDBuilderTest, createFPMath) { EXPECT_TRUE(mdconst::hasa<ConstantFP>(Op)); ConstantFP *Val = mdconst::extract<ConstantFP>(Op); EXPECT_TRUE(Val->getType()->isFloatingPointTy()); - EXPECT_TRUE(Val->isExactlyValue(1.0)); + EXPECT_TRUE(Val->isOne()); } TEST_F(MDBuilderTest, createRangeMetadata) { MDBuilder MDHelper(Context); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
