]> granicus.if.org Git - llvm/commitdiff
DAGCombiner: Allow negating ConstantFP after legalize
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Wed, 25 Jan 2017 04:54:34 +0000 (04:54 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Wed, 25 Jan 2017 04:54:34 +0000 (04:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293019 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/APFloat.h
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
test/CodeGen/AMDGPU/fneg-combines.ll
unittests/ADT/APFloatTest.cpp

index 5dc5870d488910a3b875b066cb33ee4da2c2900d..b8017bf5417809bcdf6326a79a2b30f199f4bc46 100644 (file)
@@ -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
index 60038e2924ca527e3bb9f6faf622559a5a1678ad..ce2e52b7128b612a7f6756a0ac7dd6ca9d739176 100644 (file)
@@ -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<ConstantFPSDNode>(Op)->getValueAPF()), VT);
+  }
   case ISD::FADD:
     // FIXME: determine better conditions for this xform.
     if (!Options->UnsafeFPMath) return 0;
index 3f9928c2b623c8438927bb51becbe5d028c801f1..74d14217e0d58d2fac82e89ca11d363b8a29e3b5 100644 (file)
@@ -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]]
index 016d73b59d10f8dbcc8aec0648be56c0d109ce21..1cd98478fad0d56f37778aeedd443154700888fb 100644 (file)
@@ -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)));