From f337952e566aada34a9f6f0301dfb878d13b62ad Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 25 Jan 2017 04:54:34 +0000 Subject: [PATCH] DAGCombiner: Allow negating ConstantFP after legalize git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293019 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APFloat.h | 6 ++++++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 14 ++++++++++---- test/CodeGen/AMDGPU/fneg-combines.ll | 3 +-- unittests/ADT/APFloatTest.cpp | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 5dc5870d488..b8017bf5417 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -1313,6 +1313,12 @@ inline APFloat abs(APFloat X) { return X; } +/// \brief Returns the negated value of the argument. +inline APFloat neg(APFloat X) { + X.changeSign(); + return X; +} + /// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if /// both are not NaN. If either argument is a NaN, returns the other argument. LLVM_READONLY diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 60038e2924c..ce2e52b7128 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -607,10 +607,16 @@ static char isNegatibleForFree(SDValue Op, bool LegalOperations, switch (Op.getOpcode()) { default: return false; - case ISD::ConstantFP: - // Don't invert constant FP values after legalize. The negated constant - // isn't necessarily legal. - return LegalOperations ? 0 : 1; + case ISD::ConstantFP: { + if (!LegalOperations) + return 1; + + // Don't invert constant FP values after legalization unless the target says + // the negated constant is legal. + EVT VT = Op.getValueType(); + return TLI.isOperationLegal(ISD::ConstantFP, VT) || + TLI.isFPImmLegal(neg(cast(Op)->getValueAPF()), VT); + } case ISD::FADD: // FIXME: determine better conditions for this xform. if (!Options->UnsafeFPMath) return 0; diff --git a/test/CodeGen/AMDGPU/fneg-combines.ll b/test/CodeGen/AMDGPU/fneg-combines.ll index 3f9928c2b62..74d14217e0d 100644 --- a/test/CodeGen/AMDGPU/fneg-combines.ll +++ b/test/CodeGen/AMDGPU/fneg-combines.ll @@ -1300,8 +1300,7 @@ define void @v_fneg_mul_legacy_multi_use_fneg_x_f32(float addrspace(1)* %out, fl ; GCN-LABEL: {{^}}v_fneg_sin_f32: ; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] -; GCN: v_mov_b32_e32 [[K:v[0-9]+]], 0x3e22f983 -; GCN: v_mul_f32_e64 [[MUL:v[0-9]+]], [[K]], -[[A]] +; GCN: v_mul_f32_e32 [[MUL:v[0-9]+]], 0xbe22f983, [[A]] ; GCN: v_fract_f32_e32 [[FRACT:v[0-9]+]], [[MUL]] ; GCN: v_sin_f32_e32 [[RESULT:v[0-9]+]], [[FRACT]] ; GCN: buffer_store_dword [[RESULT]] diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 016d73b59d1..1cd98478fad 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -2830,6 +2830,28 @@ TEST(APFloatTest, abs) { EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized))); } +TEST(APFloatTest, neg) { + APFloat One = APFloat(APFloat::IEEEsingle(), "1.0"); + APFloat NegOne = APFloat(APFloat::IEEEsingle(), "-1.0"); + APFloat Zero = APFloat::getZero(APFloat::IEEEsingle(), false); + APFloat NegZero = APFloat::getZero(APFloat::IEEEsingle(), true); + APFloat Inf = APFloat::getInf(APFloat::IEEEsingle(), false); + APFloat NegInf = APFloat::getInf(APFloat::IEEEsingle(), true); + APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false); + APFloat NegQNaN = APFloat::getNaN(APFloat::IEEEsingle(), true); + + EXPECT_TRUE(NegOne.bitwiseIsEqual(neg(One))); + EXPECT_TRUE(One.bitwiseIsEqual(neg(NegOne))); + EXPECT_TRUE(NegZero.bitwiseIsEqual(neg(Zero))); + EXPECT_TRUE(Zero.bitwiseIsEqual(neg(NegZero))); + EXPECT_TRUE(NegInf.bitwiseIsEqual(neg(Inf))); + EXPECT_TRUE(Inf.bitwiseIsEqual(neg(NegInf))); + EXPECT_TRUE(NegInf.bitwiseIsEqual(neg(Inf))); + EXPECT_TRUE(Inf.bitwiseIsEqual(neg(NegInf))); + EXPECT_TRUE(NegQNaN.bitwiseIsEqual(neg(QNaN))); + EXPECT_TRUE(QNaN.bitwiseIsEqual(neg(NegQNaN))); +} + TEST(APFloatTest, ilogb) { EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false))); EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true))); -- 2.50.1