pa.c (fmpy_operands): Define.
authorJeff Law <law@gcc.gnu.org>
Wed, 3 Jul 1996 17:19:19 +0000 (11:19 -0600)
committerJeff Law <law@gcc.gnu.org>
Wed, 3 Jul 1996 17:19:19 +0000 (11:19 -0600)
        * pa.c (fmpy_operands): Define.
        (combinable_fmpy): New function.
        (combinable_fadd, combinable_fsub): Likewise.

From-SVN: r12385

gcc/config/pa/pa.c

index 42134d58a9ab60806b68c9b1d1ebaecf6b7207a1..8ddbf0e5d3059a0760589445b327dfe7cebdbaa4 100644 (file)
@@ -61,6 +61,14 @@ static int out_of_line_prologue_epilogue;
 
 static rtx find_addr_reg ();
 
+/* Kludgery.  We hold the operands to a fmpy insn here so we can
+   compare them with the operands for an fadd/fsub to determine if
+   they can be combined into a fmpyadd/fmpysub insn.
+
+   This _WILL_ disappear as the code to combine independent insns
+   matures.  */
+static rtx fmpy_operands[3];
+
 /* Keep track of the number of bytes we have output in the CODE subspaces
    during this compilation so we'll know when to emit inline long-calls.  */
 
@@ -5299,6 +5307,169 @@ following_call (insn)
   return 0;
 }
 
+/* Return nonzero if this is a floating point multiply (fmpy) which
+   could be combined with a suitable floating point add or sub insn.  */
+
+combinable_fmpy (insn)
+     rtx insn;
+{
+  rtx src, dest, pattern = PATTERN (insn);
+  enum machine_mode mode;
+
+  /* Only on 1.1 and later cpus.  */
+  if (!TARGET_SNAKE)
+    return 0;
+
+  /* Must be a (set (reg) (mult (reg) (reg))).  */
+  if (GET_CODE (pattern) != SET
+      || GET_CODE (SET_SRC (pattern)) != MULT
+      || GET_CODE (SET_DEST (pattern)) != REG)
+    return 0;
+
+  src = SET_SRC (pattern);
+  dest = SET_DEST (pattern);
+
+  /* Must be registers.  */
+  if (GET_CODE (XEXP (src, 0)) != REG
+      || GET_CODE (XEXP (src, 1)) != REG)
+    return 0;
+
+  /* Must be a floating point mode.  Must match the mode of the fmul.  */
+  mode = GET_MODE (dest);
+  if (mode != DFmode && mode != SFmode)
+    return 0;
+  /* SFmode limits the registers which can be used to the upper
+     32 32bit FP registers.  */
+  if (mode == SFmode
+      && (REGNO (dest) < 57
+         || REGNO (XEXP (src, 0)) < 57
+         || REGNO (XEXP (src, 1)) < 57))
+    return 0;
+     
+  /* Save our operands, we'll need to verify they don't conflict with
+     those in the fadd or fsub.  XXX This needs to disasppear soon.  */
+  fmpy_operands[0] = dest;
+  fmpy_operands[1] = XEXP (src, 0);
+  fmpy_operands[2] = XEXP (src, 1);
+
+  return 1;
+}
+
+/* Return nonzero if INSN is a floating point add suitable for combining
+   with the most recently examined floating point multiply.  */
+
+combinable_fadd (insn)
+     rtx insn;
+{
+  rtx src, dest, pattern = PATTERN (insn);
+  enum machine_mode mode;
+
+  /* Must be a (set (reg) (plus (reg) (reg))).  */
+  if (GET_CODE (pattern) != SET
+      || GET_CODE (SET_SRC (pattern)) != PLUS
+      || GET_CODE (SET_DEST (pattern)) != REG)
+    return 0;
+
+  src = SET_SRC (pattern);
+  dest = SET_DEST (pattern);
+
+  /* Must be registers.  */
+  if (GET_CODE (XEXP (src, 0)) != REG
+      || GET_CODE (XEXP (src, 1)) != REG)
+    return 0;
+
+  /* Must be a floating point mode.  Must match the mode of the fmul.  */
+  mode = GET_MODE (dest);
+  if (mode != DFmode && mode != SFmode)
+    return 0;
+  if (mode != GET_MODE (fmpy_operands[0]))
+    return 0;
+
+  /* SFmode limits the registers which can be used to the upper
+     32 32bit FP registers.  */
+  if (mode == SFmode
+      && (REGNO (dest) < 57
+         || REGNO (XEXP (src, 0)) < 57
+         || REGNO (XEXP (src, 1)) < 57))
+    return 0;
+     
+  /* Only 2 real operands to the addition.  One of the input operands
+     must be the same as the output operand.  */
+  if (! rtx_equal_p (dest, XEXP (src, 0))
+      && ! rtx_equal_p (dest, XEXP (src, 1)))
+    return 0;
+
+  /* Inout operand of the add can not conflict with any operands from the
+     multiply.  */
+  if (rtx_equal_p (dest, fmpy_operands[0])
+      || rtx_equal_p (dest, fmpy_operands[1])
+      || rtx_equal_p (dest, fmpy_operands[2]))
+    return 0;
+
+  /* The multiply can not feed into the addition.  */
+  if (rtx_equal_p (fmpy_operands[0], XEXP (src, 0))
+      || rtx_equal_p (fmpy_operands[0], XEXP (src, 1)))
+    return 0;
+
+  return 1;
+}
+
+/* Return nonzero if INSN is a floating point sub suitable for combining
+   with the most recently examined floating point multiply.  */
+
+combinable_fsub (insn)
+     rtx insn;
+{
+  rtx src, dest, pattern = PATTERN (insn);
+  enum machine_mode mode;
+
+  /* Must be (set (reg) (minus (reg) (reg))).  */
+  if (GET_CODE (pattern) != SET
+      || GET_CODE (SET_SRC (pattern)) != MINUS
+      || GET_CODE (SET_DEST (pattern)) != REG)
+    return 0;
+
+  src = SET_SRC (pattern);
+  dest = SET_DEST (pattern);
+
+  if (GET_CODE (XEXP (src, 0)) != REG
+      || GET_CODE (XEXP (src, 1)) != REG)
+    return 0;
+
+  /* Must be a floating point mode.  Must match the mode of the fmul.  */
+  mode = GET_MODE (dest);
+  if (mode != DFmode && mode != SFmode)
+    return 0;
+  if (mode != GET_MODE (fmpy_operands[0]))
+    return 0;
+
+  /* SFmode limits the registers which can be used to the upper
+     32 32bit FP registers.  */
+  if (mode == SFmode && (REGNO (dest) < 57 || REGNO (XEXP (src, 1)) < 57))
+    return 0;
+     
+  /* Only 2 real operands to the subtraction.  Output must be the
+     same as the first operand of the MINUS.  */
+  if (! rtx_equal_p (dest, XEXP (src, 0)))
+    return;
+
+  /* Inout operand of the sub can not conflict with any operands from the
+     multiply.  */
+  if (rtx_equal_p (dest, fmpy_operands[0])
+      || rtx_equal_p (dest, fmpy_operands[1])
+      || rtx_equal_p (dest, fmpy_operands[2]))
+    return 0;
+
+  /* The multiply can not feed into the subtraction.  */
+  if (rtx_equal_p (fmpy_operands[0], XEXP (src, 0))
+      || rtx_equal_p (fmpy_operands[0], XEXP (src, 1)))
+    return 0;
+
+  return 1;
+}
 
 /* We use this hook to perform a PA specific optimization which is difficult
    to do in earlier passes.