>From a85dde9bd3a0dab1d1c2ddf82b134137fb1cab80 Mon Sep 17 00:00:00 2001
From: Jiong Wang <jiong.wang@arm.com>
Date: Tue, 17 Jun 2014 22:23:12 +0100
Subject: [PATCH 16/19] [AArch64/GCC][17/20] New parameter 'skip_wb' for
 'aarch64_save/restore_callee_save_common'

the common reg save/restore function should skip those write-back candidate reg
if 'skip_wb' be true.

*no functional change*

2014-06-16  Jiong Wang <jiong.wang@arm.com>
	    Marcus Shawcroft  <marcus.shawcroft@arm.com>

gcc/
  * config/aarch64/aarch64.c (aarch64_save_callee_save_common): New parameter
  "skip_wb".
  (aarch64_restore_callee_save_common): Likewise.
  (aarch64_expand_prologue): Update call site.
  (aarch64_expand_epilogue): Likewise.
---
 gcc/config/aarch64/aarch64.c |   47 ++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index a6b253a..26d5fba 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2039,7 +2039,7 @@ aarch64_gen_load_pair (enum machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
 
 static void
 aarch64_save_callee_saves (enum machine_mode mode, HOST_WIDE_INT start_offset,
-			   unsigned start, unsigned limit)
+			   unsigned start, unsigned limit, bool skip_wb)
 {
   rtx insn;
   rtx (*gen_mem_ref) (enum machine_mode, rtx) = (frame_pointer_needed
@@ -2051,11 +2051,16 @@ aarch64_save_callee_saves (enum machine_mode mode, HOST_WIDE_INT start_offset,
        regno <= limit;
        regno = aarch64_next_callee_save (regno + 1, limit))
     {
-      rtx reg = gen_rtx_REG (mode, regno);
-      rtx mem;
+      rtx reg, mem;
+      HOST_WIDE_INT offset;
 
-      HOST_WIDE_INT offset = start_offset
-			     + cfun->machine->frame.reg_offset[regno];
+      if (skip_wb
+	  && (regno == cfun->machine->frame.wb_candidate1
+	      || regno == cfun->machine->frame.wb_candidate2))
+	continue;
+
+      reg = gen_rtx_REG (mode, regno);
+      offset = start_offset + cfun->machine->frame.reg_offset[regno];
       mem = gen_mem_ref (mode, plus_constant (Pmode, stack_pointer_rtx,
 					      offset));
 
@@ -2092,7 +2097,7 @@ aarch64_save_callee_saves (enum machine_mode mode, HOST_WIDE_INT start_offset,
 static void
 aarch64_restore_callee_saves (enum machine_mode mode,
 			      HOST_WIDE_INT start_offset, unsigned start,
-			      unsigned limit)
+			      unsigned limit, bool skip_wb)
 {
   rtx insn;
   rtx base_rtx = stack_pointer_rtx;
@@ -2106,9 +2111,14 @@ aarch64_restore_callee_saves (enum machine_mode mode,
        regno <= limit;
        regno = aarch64_next_callee_save (regno + 1, limit))
     {
-      rtx reg = gen_rtx_REG (mode, regno);
-      rtx mem;
+      rtx reg, mem;
 
+      if (skip_wb
+	  && (regno == cfun->machine->frame.wb_candidate1
+	      || regno == cfun->machine->frame.wb_candidate2))
+	continue;
+
+      reg = gen_rtx_REG (mode, regno);
       offset = start_offset + cfun->machine->frame.reg_offset[regno];
       mem = gen_mem_ref (mode, plus_constant (Pmode, base_rtx, offset));
 
@@ -2264,6 +2274,8 @@ aarch64_expand_prologue (void)
 
   if (offset > 0)
     {
+      bool skip_wb = false;
+
       /* Save the frame pointer and lr if the frame pointer is needed
 	 first.  Make the frame pointer point to the location of the
 	 old frame pointer on the stack.  */
@@ -2281,7 +2293,7 @@ aarch64_expand_prologue (void)
 						      GEN_INT (offset))));
 
 	      aarch64_save_callee_saves (DImode, fp_offset, R29_REGNUM,
-					 R30_REGNUM);
+					 R30_REGNUM, skip_wb);
 	    }
 	  else
 	    aarch64_pushwb_pair_reg (DImode, R29_REGNUM, R30_REGNUM, offset);
@@ -2300,7 +2312,8 @@ aarch64_expand_prologue (void)
 	  insn = emit_insn (gen_stack_tie (stack_pointer_rtx,
 					   hard_frame_pointer_rtx));
 
-	  aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R28_REGNUM);
+	  aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R28_REGNUM,
+				     skip_wb);
 	}
       else
 	{
@@ -2308,10 +2321,12 @@ aarch64_expand_prologue (void)
 					   GEN_INT (-offset)));
 	  RTX_FRAME_RELATED_P (insn) = 1;
 
-	  aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R30_REGNUM);
+	  aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R30_REGNUM,
+				     skip_wb);
 	}
 
-      aarch64_save_callee_saves (DFmode, fp_offset, V0_REGNUM, V31_REGNUM);
+      aarch64_save_callee_saves (DFmode, fp_offset, V0_REGNUM, V31_REGNUM,
+				 skip_wb);
     }
 
   /* when offset >= 512,
@@ -2336,6 +2351,7 @@ aarch64_expand_epilogue (bool for_sibcall)
   HOST_WIDE_INT fp_offset;
   rtx insn;
   rtx cfa_reg;
+  bool skip_wb = false;
 
   aarch64_layout_frame ();
 
@@ -2384,20 +2400,21 @@ aarch64_expand_epilogue (bool for_sibcall)
     }
 
   aarch64_restore_callee_saves (DFmode, frame_pointer_needed ? 0 : fp_offset,
-				V0_REGNUM, V31_REGNUM);
+				V0_REGNUM, V31_REGNUM, skip_wb);
 
   if (offset > 0)
     {
       if (frame_pointer_needed)
 	{
-	  aarch64_restore_callee_saves (DImode, 0, R0_REGNUM, R28_REGNUM);
+	  aarch64_restore_callee_saves (DImode, 0, R0_REGNUM, R28_REGNUM,
+					skip_wb);
 	  aarch64_popwb_pair_reg (DImode, R29_REGNUM, R30_REGNUM, offset,
 				  cfa_reg);
 	}
       else
 	{
 	  aarch64_restore_callee_saves (DImode, fp_offset, R0_REGNUM,
-					R30_REGNUM);
+					R30_REGNUM, skip_wb);
 	  insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
 					   GEN_INT (offset)));
 	  RTX_FRAME_RELATED_P (insn) = 1;
-- 
1.7.9.5

