diff mbox

[5/9] Add patterns and predicates foutline-msabi-xlouges

Message ID 20161115200700.10792-5-daniel.santos@pobox.com
State New
Headers show

Commit Message

Daniel Santos Nov. 15, 2016, 8:06 p.m. UTC
Adds the predicates save_multiple and restore_multiple to predicates.md,
which are used by following patterns in sse.md:

* save_multiple - insn that calls a save stub
* save_multiple_realign - insn that calls a save stub and also manages
  a realign and hard frame pointer
* restore_multiple - call_insn that calls a save stub and returns to the
  function to allow a sibling call (which should typically offer better
  optimization than the restore stub as the tail call)
* restore_multiple_and_return - a jump_insn that is the return from
  a function (tail call)
---
 gcc/config/i386/predicates.md | 148 ++++++++++++++++++++++++++++++++++++++++++
 gcc/config/i386/sse.md        |  56 ++++++++++++++++
 2 files changed, 204 insertions(+)

Comments

Daniel Santos Nov. 15, 2016, 9:10 p.m. UTC | #1
On 11/15/2016 02:06 PM, Daniel Santos wrote:
> +;; Save multiple registers out-of-line after realignment
> +(define_insn "save_multiple_realign<mode>"
> +  [(match_parallel 0 "save_multiple"
> +    [(use (match_operand:P 1 "symbol_operand"))
> +     (set (reg:P SP_REG) (plus:P (reg:P AX_REG)
> +	  (match_operand:DI 2 "const_int_operand")))
> +    ])]
> +  "TARGET_SSE && TARGET_64BIT"
> +  "leaq\t%c2(%%rax),%%rsp;\n\tcall\t%P1")

This pattern was included by mistake (it's incorrect and improperly 
documented). This is supposed to be the pattern that manages the enter 
and realignment in the special optimization case of all 17 registers 
being clobbered and I can do the enter, stack realignment and allocation 
in savms64f.S just prior to the symbol __savms64f_17. Please ignore it 
for now.

Daniel
diff mbox

Patch

diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 219674e..f50bba9a 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1663,3 +1663,151 @@ 
   (ior (match_operand 0 "register_operand")
        (and (match_code "const_int")
 	    (match_test "op == constm1_rtx"))))
+
+;; Return true if:
+;; * first op is a symbol reference,
+;; * >= 14 operands, and
+;; * operands 2 to end save a register to a memory location that's an
+(define_predicate "save_multiple"
+  (match_code "parallel")
+{
+  const unsigned nregs = XVECLEN (op, 0);
+  rtx head = XVECEXP (op, 0, 0);
+  unsigned i;
+
+  if (GET_CODE (head) != USE)
+    return false;
+  else
+    {
+      rtx op0 = XEXP (head, 0);
+      if (op0 == NULL_RTX || GET_CODE (op0) != SYMBOL_REF)
+	return false;
+    }
+
+  if (nregs < 14)
+    return false;
+
+  for (i = 2; i < nregs; i++)
+    {
+      rtx e, src, dest;
+
+      e = XVECEXP (op, 0, i);
+
+      switch (GET_CODE (e))
+	{
+	  case SET:
+	    src  = SET_SRC (e);
+	    dest = SET_DEST (e);
+
+	    /* storing a register to memory.  */
+	    if (GET_CODE (src) == REG && GET_CODE (dest) == MEM)
+	      {
+		rtx addr = XEXP (dest, 0);
+
+		/* Good if dest address is in RAX.  */
+		if (GET_CODE (addr) == REG
+		    && REGNO (addr) == AX_REG)
+		  continue;
+
+		/* Good if dest address is offset of RAX.  */
+		if (GET_CODE (addr) == PLUS
+		    && GET_CODE (XEXP (addr, 0)) == REG
+		    && REGNO (XEXP (addr, 0)) == AX_REG)
+		  continue;
+	      }
+	    break;
+
+	  default:
+	    break;
+	}
+	return false;
+    }
+  return true;
+})
+
+;; Return true if:
+;; * first op is (return) or a a use (symbol reference),
+;; * >= 14 operands, and
+;; * operands 2 to end are one of:
+;;   - restoring a register from a memory location that's an offset of RSI.
+;;   - clobbering a reg
+;;   - adjusting SP
+(define_predicate "restore_multiple"
+  (match_code "parallel")
+{
+  const unsigned nregs = XVECLEN (op, 0);
+  rtx head = XVECEXP (op, 0, 0);
+  unsigned i;
+
+  switch (GET_CODE (head))
+    {
+      case RETURN:
+	i = 3;
+	break;
+
+      case USE:
+      {
+	rtx op0 = XEXP (head, 0);
+
+	if (op0 == NULL_RTX || GET_CODE (op0) != SYMBOL_REF)
+	  return false;
+
+	i = 1;
+	break;
+      }
+
+      default:
+	return false;
+    }
+
+  if (nregs < i + 12)
+    return false;
+
+  for (; i < nregs; i++)
+    {
+      rtx e, src, dest;
+
+      e = XVECEXP (op, 0, i);
+
+      switch (GET_CODE (e))
+	{
+	  case CLOBBER:
+	    continue;
+
+	  case SET:
+	    src  = SET_SRC (e);
+	    dest = SET_DEST (e);
+
+	    /* restoring a register from memory.  */
+	    if (GET_CODE (src) == MEM && GET_CODE (dest) == REG)
+	      {
+		rtx addr = XEXP (src, 0);
+
+		/* Good if src address is in RSI.  */
+		if (GET_CODE (addr) == REG
+		    && REGNO (addr) == SI_REG)
+		  continue;
+
+		/* Good if src address is offset of RSI.  */
+		if (GET_CODE (addr) == PLUS
+		    && GET_CODE (XEXP (addr, 0)) == REG
+		    && REGNO (XEXP (addr, 0)) == SI_REG)
+		  continue;
+
+		/* Good if adjusting stack pointer.  */
+		if (GET_CODE (dest) == REG
+		    && REGNO (dest) == SP_REG
+		    && GET_CODE (src) == PLUS
+		    && GET_CODE (XEXP (src, 0)) == REG
+		    && REGNO (XEXP (src, 0)) == SP_REG)
+		  continue;
+	      }
+	    break;
+
+	  default:
+	    break;
+	}
+	return false;
+    }
+  return true;
+})
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 14fcd67..b9dac15 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -19397,3 +19397,59 @@ 
   [(set_attr "type" "sselog")
    (set_attr "prefix" "evex")
    (set_attr "mode" "<sseinsnmode>")])
+
+;; Save multiple registers out-of-line
+(define_insn "save_multiple<mode>"
+  [(match_parallel 0 "save_multiple"
+    [(use (match_operand:P 1 "symbol_operand"))
+     (const_int 0)
+    ])]
+  "TARGET_SSE && TARGET_64BIT"
+  "call\t%P1")
+
+;; Save multiple registers out-of-line after realignment
+(define_insn "save_multiple_realign<mode>"
+  [(match_parallel 0 "save_multiple"
+    [(use (match_operand:P 1 "symbol_operand"))
+     (set (reg:P SP_REG) (plus:P (reg:P AX_REG)
+	  (match_operand:DI 2 "const_int_operand")))
+    ])]
+  "TARGET_SSE && TARGET_64BIT"
+  "leaq\t%c2(%%rax),%%rsp;\n\tcall\t%P1")
+
+;; Save multiple registers out-of-line after realignment
+(define_insn "save_multiple_realign_enter<mode>"
+  [(match_parallel 0 "save_multiple"
+    [(use (match_operand:P 1 "symbol_operand"))
+     (const_int 1)
+    ])]
+  "TARGET_SSE && TARGET_64BIT"
+  "call\t%P1")
+
+;; Restore multiple registers out-of-line
+(define_insn "restore_multiple<mode>"
+  [(match_parallel 0 "restore_multiple"
+    [(use (match_operand:P 1 "symbol_operand"))])]
+  "TARGET_SSE && TARGET_64BIT"
+  "call\t%P1")
+
+;; Restore multiple registers out-of-line and return
+(define_insn "restore_multiple_and_return<mode>"
+  [(match_parallel 0 "restore_multiple"
+    [(return)
+     (use (match_operand:P 1 "symbol_operand"))
+     (set (reg:DI R10_REG) (plus:DI (reg:DI SI_REG)
+	  (match_operand:DI 2 "const_int_operand")))
+    ])]
+  "TARGET_SSE && TARGET_64BIT"
+  "leaq\t%c2(%%rsi),%%r10;\n\tjmp\t%P1")
+
+;; Restore multiple registers out-of-line and return
+(define_insn "restore_multiple_leave_return<mode>"
+  [(match_parallel 0 "restore_multiple"
+    [(return)
+     (use (match_operand:P 1 "symbol_operand"))
+     (const_int 0)
+    ])]
+  "TARGET_SSE && TARGET_64BIT"
+  "jmp\t%P1")