diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index 25fc8a00f7ddd..01e51accec9df 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -354,6 +354,7 @@ struct APFloatBase { static bool semanticsHasInf(const fltSemantics &); static bool semanticsHasNaN(const fltSemantics &); static bool isIEEELikeFP(const fltSemantics &); + static bool hasSignBitInMSB(const fltSemantics &); // Returns true if any number described by \p Src can be precisely represented // by a normal (not subnormal) value in \p Dst. diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index e058010f9d267..a7b9f259bfed5 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -125,6 +125,9 @@ struct fltSemantics { /* Whether this semantics can represent signed values */ bool hasSignedRepr = true; + + /* Whether the sign bit of this semantics is the most significant bit */ + bool hasSignBitInMSB = true; }; static constexpr fltSemantics semIEEEhalf = {15, -14, 11, 16}; @@ -144,9 +147,15 @@ static constexpr fltSemantics semFloat8E4M3B11FNUZ = { 4, -10, 4, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::NegativeZero}; static constexpr fltSemantics semFloat8E3M4 = {3, -2, 5, 8}; static constexpr fltSemantics semFloatTF32 = {127, -126, 11, 19}; -static constexpr fltSemantics semFloat8E8M0FNU = { - 127, -127, 1, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::AllOnes, - false, false}; +static constexpr fltSemantics semFloat8E8M0FNU = {127, + -127, + 1, + 8, + fltNonfiniteBehavior::NanOnly, + fltNanEncoding::AllOnes, + false, + false, + false}; static constexpr fltSemantics semFloat6E3M2FN = { 4, -2, 3, 6, fltNonfiniteBehavior::FiniteOnly}; @@ -358,6 +367,10 @@ bool APFloatBase::isIEEELikeFP(const fltSemantics &semantics) { return SemanticsToEnum(semantics) <= S_IEEEquad; } +bool APFloatBase::hasSignBitInMSB(const fltSemantics &semantics) { + return semantics.hasSignBitInMSB; +} + bool APFloatBase::isRepresentableAsNormalIn(const fltSemantics &Src, const fltSemantics &Dst) { // Exponent range must be larger. diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 6cc241781d112..61c72293dd314 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2645,7 +2645,8 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) { !Builder.GetInsertBlock()->getParent()->hasFnAttribute( Attribute::NoImplicitFloat)) { Type *EltTy = CastOp->getType()->getScalarType(); - if (EltTy->isFloatingPointTy() && EltTy->isIEEE()) { + if (EltTy->isFloatingPointTy() && + APFloat::hasSignBitInMSB(EltTy->getFltSemantics())) { Value *FAbs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, CastOp); return new BitCastInst(FAbs, I.getType()); } @@ -4057,7 +4058,8 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) { !Builder.GetInsertBlock()->getParent()->hasFnAttribute( Attribute::NoImplicitFloat)) { Type *EltTy = CastOp->getType()->getScalarType(); - if (EltTy->isFloatingPointTy() && EltTy->isIEEE()) { + if (EltTy->isFloatingPointTy() && + APFloat::hasSignBitInMSB(EltTy->getFltSemantics())) { Value *FAbs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, CastOp); Value *FNegFAbs = Builder.CreateFNeg(FAbs); return new BitCastInst(FNegFAbs, I.getType()); @@ -4859,7 +4861,8 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) { !Builder.GetInsertBlock()->getParent()->hasFnAttribute( Attribute::NoImplicitFloat)) { Type *EltTy = CastOp->getType()->getScalarType(); - if (EltTy->isFloatingPointTy() && EltTy->isIEEE()) { + if (EltTy->isFloatingPointTy() && + APFloat::hasSignBitInMSB(EltTy->getFltSemantics())) { Value *FNeg = Builder.CreateFNeg(CastOp); return new BitCastInst(FNeg, I.getType()); } diff --git a/llvm/test/Transforms/InstCombine/fabs-as-int.ll b/llvm/test/Transforms/InstCombine/fabs-as-int.ll index 9d28cae8f04d6..f0e83ca6302fe 100644 --- a/llvm/test/Transforms/InstCombine/fabs-as-int.ll +++ b/llvm/test/Transforms/InstCombine/fabs-as-int.ll @@ -289,8 +289,8 @@ define i128 @fabs_as_int_ppc_fp128_f64_mask(ppc_fp128 %x) { define i128 @fabs_as_int_ppc_fp128_f128_mask(ppc_fp128 %x) { ; CHECK-LABEL: define i128 @fabs_as_int_ppc_fp128_f128_mask ; CHECK-SAME: (ppc_fp128 [[X:%.*]]) { -; CHECK-NEXT: [[BC:%.*]] = bitcast ppc_fp128 [[X]] to i128 -; CHECK-NEXT: [[AND:%.*]] = and i128 [[BC]], 170141183460469231731687303715884105727 +; CHECK-NEXT: [[TMP1:%.*]] = call ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 [[X]]) +; CHECK-NEXT: [[AND:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128 ; CHECK-NEXT: ret i128 [[AND]] ; %bc = bitcast ppc_fp128 %x to i128 diff --git a/llvm/test/Transforms/InstCombine/fneg-as-int.ll b/llvm/test/Transforms/InstCombine/fneg-as-int.ll index f8d88b4f238f2..590aca687e5b5 100644 --- a/llvm/test/Transforms/InstCombine/fneg-as-int.ll +++ b/llvm/test/Transforms/InstCombine/fneg-as-int.ll @@ -291,8 +291,8 @@ define i128 @fneg_as_int_ppc_fp128_f64_mask(ppc_fp128 %x) { define i128 @fneg_as_int_ppc_fp128_f128_mask(ppc_fp128 %x) { ; CHECK-LABEL: define i128 @fneg_as_int_ppc_fp128_f128_mask ; CHECK-SAME: (ppc_fp128 [[X:%.*]]) { -; CHECK-NEXT: [[BC:%.*]] = bitcast ppc_fp128 [[X]] to i128 -; CHECK-NEXT: [[XOR:%.*]] = xor i128 [[BC]], -170141183460469231731687303715884105728 +; CHECK-NEXT: [[TMP1:%.*]] = fneg ppc_fp128 [[X]] +; CHECK-NEXT: [[XOR:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128 ; CHECK-NEXT: ret i128 [[XOR]] ; %bc = bitcast ppc_fp128 %x to i128 diff --git a/llvm/test/Transforms/InstCombine/fneg-fabs-as-int.ll b/llvm/test/Transforms/InstCombine/fneg-fabs-as-int.ll index 8b245bdd79299..a0894c3febc94 100644 --- a/llvm/test/Transforms/InstCombine/fneg-fabs-as-int.ll +++ b/llvm/test/Transforms/InstCombine/fneg-fabs-as-int.ll @@ -317,8 +317,9 @@ define i128 @fneg_fabs_as_int_ppc_fp128_f64_mask(ppc_fp128 %x) { define i128 @fneg_fabs_as_int_ppc_fp128_f128_mask(ppc_fp128 %x) { ; CHECK-LABEL: define i128 @fneg_fabs_as_int_ppc_fp128_f128_mask ; CHECK-SAME: (ppc_fp128 [[X:%.*]]) { -; CHECK-NEXT: [[BC:%.*]] = bitcast ppc_fp128 [[X]] to i128 -; CHECK-NEXT: [[OR:%.*]] = or i128 [[BC]], -170141183460469231731687303715884105728 +; CHECK-NEXT: [[TMP1:%.*]] = call ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 [[X]]) +; CHECK-NEXT: [[TMP2:%.*]] = fneg ppc_fp128 [[TMP1]] +; CHECK-NEXT: [[OR:%.*]] = bitcast ppc_fp128 [[TMP2]] to i128 ; CHECK-NEXT: ret i128 [[OR]] ; %bc = bitcast ppc_fp128 %x to i128 diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp index 09356191345f5..7a5fd83cd9581 100644 --- a/llvm/unittests/ADT/APFloatTest.cpp +++ b/llvm/unittests/ADT/APFloatTest.cpp @@ -8347,4 +8347,13 @@ TEST(APFloatTest, AddOrSubtractSignificand) { Helper::runTest(true, false, 3, 0x10001, false, 7, 0x100, false, 6, 0x1e00, lfLessThanHalf); } + +TEST(APFloatTest, hasSignBitInMSB) { + EXPECT_TRUE(APFloat::hasSignBitInMSB(APFloat::IEEEsingle())); + EXPECT_TRUE(APFloat::hasSignBitInMSB(APFloat::x87DoubleExtended())); + EXPECT_TRUE(APFloat::hasSignBitInMSB(APFloat::PPCDoubleDouble())); + EXPECT_TRUE(APFloat::hasSignBitInMSB(APFloat::IEEEquad())); + EXPECT_FALSE(APFloat::hasSignBitInMSB(APFloat::Float8E8M0FNU())); +} + } // namespace