From df5aa4706ec45097a440f868ed8ce08f835b238d Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Tue, 1 Oct 2024 15:55:52 +0100 Subject: [PATCH 1/3] [KnownBits] New private helper flipSignBit --- llvm/include/llvm/Support/KnownBits.h | 3 +++ llvm/lib/Support/KnownBits.cpp | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index e4ec202f36aae..a4b554fa2a0b7 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -29,6 +29,9 @@ struct KnownBits { KnownBits(APInt Zero, APInt One) : Zero(std::move(Zero)), One(std::move(One)) {} + // Flip the range of values: [-0x80000000, 0x7FFFFFFF] <-> [0, 0xFFFFFFFF] + static KnownBits flipSignBit(const KnownBits &Val); + public: // Default construct Zero and One. KnownBits() = default; diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index 6863c5c0af5dc..da18d59696b73 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -18,6 +18,15 @@ using namespace llvm; +KnownBits KnownBits::flipSignBit(const KnownBits &Val) { + unsigned SignBitPosition = Val.getBitWidth() - 1; + APInt Zero = Val.Zero; + APInt One = Val.One; + Zero.setBitVal(SignBitPosition, Val.One[SignBitPosition]); + One.setBitVal(SignBitPosition, Val.Zero[SignBitPosition]); + return KnownBits(Zero, One); +} + static KnownBits computeForAddCarry(const KnownBits &LHS, const KnownBits &RHS, bool CarryZero, bool CarryOne) { @@ -200,16 +209,7 @@ KnownBits KnownBits::umin(const KnownBits &LHS, const KnownBits &RHS) { } KnownBits KnownBits::smax(const KnownBits &LHS, const KnownBits &RHS) { - // Flip the range of values: [-0x80000000, 0x7FFFFFFF] <-> [0, 0xFFFFFFFF] - auto Flip = [](const KnownBits &Val) { - unsigned SignBitPosition = Val.getBitWidth() - 1; - APInt Zero = Val.Zero; - APInt One = Val.One; - Zero.setBitVal(SignBitPosition, Val.One[SignBitPosition]); - One.setBitVal(SignBitPosition, Val.Zero[SignBitPosition]); - return KnownBits(Zero, One); - }; - return Flip(umax(Flip(LHS), Flip(RHS))); + return flipSignBit(umax(flipSignBit(LHS), flipSignBit(RHS))); } KnownBits KnownBits::smin(const KnownBits &LHS, const KnownBits &RHS) { From c29d49cdb340ca098f0aae2ea989171674ba70ae Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Tue, 1 Oct 2024 15:59:31 +0100 Subject: [PATCH 2/3] [KnownBits] Make `avg{Ceil,Floor}S` optimal Rewrite the signed functions in terms of the unsigned ones which are already optimal. --- llvm/lib/Support/KnownBits.cpp | 19 +++++++------------ llvm/unittests/Support/KnownBitsTest.cpp | 7 +++---- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index da18d59696b73..a7801aa950cad 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -763,11 +763,10 @@ KnownBits KnownBits::usub_sat(const KnownBits &LHS, const KnownBits &RHS) { return computeForSatAddSub(/*Add*/ false, /*Signed*/ false, LHS, RHS); } -static KnownBits avgCompute(KnownBits LHS, KnownBits RHS, bool IsCeil, - bool IsSigned) { +static KnownBits avgComputeU(KnownBits LHS, KnownBits RHS, bool IsCeil) { unsigned BitWidth = LHS.getBitWidth(); - LHS = IsSigned ? LHS.sext(BitWidth + 1) : LHS.zext(BitWidth + 1); - RHS = IsSigned ? RHS.sext(BitWidth + 1) : RHS.zext(BitWidth + 1); + LHS = LHS.zext(BitWidth + 1); + RHS = RHS.zext(BitWidth + 1); LHS = computeForAddCarry(LHS, RHS, /*CarryZero*/ !IsCeil, /*CarryOne*/ IsCeil); LHS = LHS.extractBits(BitWidth, 1); @@ -775,23 +774,19 @@ static KnownBits avgCompute(KnownBits LHS, KnownBits RHS, bool IsCeil, } KnownBits KnownBits::avgFloorS(const KnownBits &LHS, const KnownBits &RHS) { - return avgCompute(LHS, RHS, /* IsCeil */ false, - /* IsSigned */ true); + return flipSignBit(avgFloorU(flipSignBit(LHS), flipSignBit(RHS))); } KnownBits KnownBits::avgFloorU(const KnownBits &LHS, const KnownBits &RHS) { - return avgCompute(LHS, RHS, /* IsCeil */ false, - /* IsSigned */ false); + return avgComputeU(LHS, RHS, /* IsCeil */ false); } KnownBits KnownBits::avgCeilS(const KnownBits &LHS, const KnownBits &RHS) { - return avgCompute(LHS, RHS, /* IsCeil */ true, - /* IsSigned */ true); + return flipSignBit(avgCeilU(flipSignBit(LHS), flipSignBit(RHS))); } KnownBits KnownBits::avgCeilU(const KnownBits &LHS, const KnownBits &RHS) { - return avgCompute(LHS, RHS, /* IsCeil */ true, - /* IsSigned */ false); + return avgComputeU(LHS, RHS, /* IsCeil */ true); } KnownBits KnownBits::mul(const KnownBits &LHS, const KnownBits &RHS, diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index b701757aed5eb..551c1a8107494 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -521,16 +521,15 @@ TEST(KnownBitsTest, BinaryExhaustive) { [](const APInt &N1, const APInt &N2) { return APIntOps::mulhu(N1, N2); }, /*CheckOptimality=*/false); - testBinaryOpExhaustive("avgFloorS", KnownBits::avgFloorS, APIntOps::avgFloorS, - /*CheckOptimality=*/false); + testBinaryOpExhaustive("avgFloorS", KnownBits::avgFloorS, + APIntOps::avgFloorS); testBinaryOpExhaustive("avgFloorU", KnownBits::avgFloorU, APIntOps::avgFloorU); testBinaryOpExhaustive("avgCeilU", KnownBits::avgCeilU, APIntOps::avgCeilU); - testBinaryOpExhaustive("avgCeilS", KnownBits::avgCeilS, APIntOps::avgCeilS, - /*CheckOptimality=*/false); + testBinaryOpExhaustive("avgCeilS", KnownBits::avgCeilS, APIntOps::avgCeilS); } TEST(KnownBitsTest, UnaryExhaustive) { From d125c8ddf6e53db0fea400dda34b0a5e3b8612c7 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Tue, 1 Oct 2024 17:05:16 +0100 Subject: [PATCH 3/3] comments --- llvm/lib/Support/KnownBits.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index a7801aa950cad..89668af378070 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -778,7 +778,7 @@ KnownBits KnownBits::avgFloorS(const KnownBits &LHS, const KnownBits &RHS) { } KnownBits KnownBits::avgFloorU(const KnownBits &LHS, const KnownBits &RHS) { - return avgComputeU(LHS, RHS, /* IsCeil */ false); + return avgComputeU(LHS, RHS, /*IsCeil=*/false); } KnownBits KnownBits::avgCeilS(const KnownBits &LHS, const KnownBits &RHS) { @@ -786,7 +786,7 @@ KnownBits KnownBits::avgCeilS(const KnownBits &LHS, const KnownBits &RHS) { } KnownBits KnownBits::avgCeilU(const KnownBits &LHS, const KnownBits &RHS) { - return avgComputeU(LHS, RHS, /* IsCeil */ true); + return avgComputeU(LHS, RHS, /*IsCeil=*/true); } KnownBits KnownBits::mul(const KnownBits &LHS, const KnownBits &RHS,