rs6000: Make copysign (x, -1) back to -abs (x) for IEEE128 float [PR112606]

Message ID b4bc12b8-2d66-3227-6101-bbb0bcb1e3b1@linux.ibm.com
State Accepted
Headers
Series rs6000: Make copysign (x, -1) back to -abs (x) for IEEE128 float [PR112606] |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Kewen.Lin Jan. 8, 2024, 2:35 a.m. UTC
  Hi,

I noticed that commit r14-6192 can't help PR112606 #c3 as
it only takes care of SF/DF but TF/KF can still suffer the
issue.  Similar to commit r14-6192, this patch is to take
care of copysign<mode>3 with IEEE128 as well.

Bootstrapped and regtested on powerpc64-linux-gnu P8/P9
and powerpc64le-linux-gnu P9 and P10.

I'm going to push this soon.

BR,
Kewen
-----
	PR target/112606

gcc/ChangeLog:

	* config/rs6000/rs6000.md (copysign<mode>3 IEEE128): Change predicate
	of the last argument from altivec_register_operand to any_operand.  If
	operands[2] is CONST_DOUBLE, emit abs or neg abs depending on its sign
	otherwise if it doesn't satisfy altivec_register_operand, force it to
	REG using copy_to_mode_reg.
---
 gcc/config/rs6000/rs6000.md | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

--
2.42.0
  

Patch

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index c880cec33a2..bc8bc6ab060 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -15020,9 +15020,27 @@  (define_insn "sqrt<mode>2"
 (define_expand "copysign<mode>3"
   [(use (match_operand:IEEE128 0 "altivec_register_operand"))
    (use (match_operand:IEEE128 1 "altivec_register_operand"))
-   (use (match_operand:IEEE128 2 "altivec_register_operand"))]
+   (use (match_operand:IEEE128 2 "any_operand"))]
   "FLOAT128_IEEE_P (<MODE>mode)"
 {
+  /* Middle-end canonicalizes -fabs (x) to copysign (x, -1),
+     but PowerPC prefers -fabs (x).  */
+  if (CONST_DOUBLE_AS_FLOAT_P (operands[2]))
+    {
+      if (real_isneg (CONST_DOUBLE_REAL_VALUE (operands[2])))
+	{
+	  rtx abs_res = gen_reg_rtx (<MODE>mode);
+	  emit_insn (gen_abs<mode>2 (abs_res, operands[1]));
+	  emit_insn (gen_neg<mode>2 (operands[0], abs_res));
+	}
+      else
+	emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
+      DONE;
+    }
+
+  if (!altivec_register_operand (operands[2], <MODE>mode))
+    operands[2] = copy_to_mode_reg (<MODE>mode, operands[2]);
+
   if (TARGET_FLOAT128_HW)
     emit_insn (gen_copysign<mode>3_hard (operands[0], operands[1],
 					 operands[2]));