Blame SOURCES/gcc48-aarch64-unwind-opt.patch

d8d6ff
2014-08-08  Richard Henderson  <rth@redhat.com>
d8d6ff
d8d6ff
	* config/aarch64/aarch64.c (aarch64_save_or_restore_fprs): Add
d8d6ff
	cfi_ops argument, for restore put REG_CFA_RESTORE notes into
d8d6ff
	*cfi_ops rather than on individual insns.  Cleanup.
d8d6ff
	(aarch64_save_or_restore_callee_save_registers): Likewise.
d8d6ff
	(aarch64_expand_prologue): Adjust caller.
d8d6ff
	(aarch64_expand_epilogue): Likewise.  Cleanup.  Emit queued cfi_ops
d8d6ff
	on the stack restore insn.
d8d6ff
d8d6ff
--- gcc/config/aarch64/aarch64.c	2014-07-15 02:27:16.000000000 -0700
d8d6ff
+++ gcc/config/aarch64/aarch64.c	2014-08-21 12:52:44.190455860 -0700
d8d6ff
@@ -1603,24 +1603,23 @@ aarch64_register_saved_on_entry (int reg
d8d6ff
 
d8d6ff
 static void
d8d6ff
 aarch64_save_or_restore_fprs (int start_offset, int increment,
d8d6ff
-			      bool restore, rtx base_rtx)
d8d6ff
-
d8d6ff
+			      bool restore, rtx base_rtx, rtx *cfi_ops)
d8d6ff
 {
d8d6ff
   unsigned regno;
d8d6ff
   unsigned regno2;
d8d6ff
   rtx insn;
d8d6ff
   rtx (*gen_mem_ref)(enum machine_mode, rtx) = (frame_pointer_needed)? gen_frame_mem : gen_rtx_MEM;
d8d6ff
 
d8d6ff
-
d8d6ff
   for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
d8d6ff
     {
d8d6ff
       if (aarch64_register_saved_on_entry (regno))
d8d6ff
 	{
d8d6ff
-	  rtx mem;
d8d6ff
+	  rtx mem, reg1;
d8d6ff
 	  mem = gen_mem_ref (DFmode,
d8d6ff
 			     plus_constant (Pmode,
d8d6ff
 					    base_rtx,
d8d6ff
 					    start_offset));
d8d6ff
+	  reg1 = gen_rtx_REG (DFmode, regno);
d8d6ff
 
d8d6ff
 	  for (regno2 = regno + 1;
d8d6ff
 	       regno2 <= V31_REGNUM
d8d6ff
@@ -1632,54 +1631,51 @@ aarch64_save_or_restore_fprs (int start_
d8d6ff
 	  if (regno2 <= V31_REGNUM &&
d8d6ff
 	      aarch64_register_saved_on_entry (regno2))
d8d6ff
 	    {
d8d6ff
-	      rtx mem2;
d8d6ff
+	      rtx mem2, reg2;
d8d6ff
 	      /* Next highest register to be saved.  */
d8d6ff
 	      mem2 = gen_mem_ref (DFmode,
d8d6ff
 				  plus_constant
d8d6ff
 				  (Pmode,
d8d6ff
 				   base_rtx,
d8d6ff
 				   start_offset + increment));
d8d6ff
+	      reg2 = gen_rtx_REG (DFmode, regno2);
d8d6ff
+
d8d6ff
 	      if (restore == false)
d8d6ff
 		{
d8d6ff
-		  insn = emit_insn
d8d6ff
-		    ( gen_store_pairdf (mem, gen_rtx_REG (DFmode, regno),
d8d6ff
-					mem2, gen_rtx_REG (DFmode, regno2)));
d8d6ff
-
d8d6ff
+		  insn = emit_insn (gen_store_pairdf (mem, reg1, mem2, reg2));
d8d6ff
+		  /* The first part of a frame-related parallel insn
d8d6ff
+		     is always assumed to be relevant to the frame
d8d6ff
+		     calculations; subsequent parts, are only
d8d6ff
+		     frame-related if explicitly marked.  */
d8d6ff
+		  RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
d8d6ff
+		  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
 		}
d8d6ff
 	      else
d8d6ff
 		{
d8d6ff
-		  insn = emit_insn
d8d6ff
-		    ( gen_load_pairdf (gen_rtx_REG (DFmode, regno), mem,
d8d6ff
-				       gen_rtx_REG (DFmode, regno2), mem2));
d8d6ff
-
d8d6ff
-		  add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DFmode, regno));
d8d6ff
-		  add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DFmode, regno2));
d8d6ff
+		  emit_insn (gen_load_pairdf (reg1, mem, reg2, mem2));
d8d6ff
+		  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg1, *cfi_ops);
d8d6ff
+		  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg2, *cfi_ops);
d8d6ff
 		}
d8d6ff
 
d8d6ff
-		  /* The first part of a frame-related parallel insn
d8d6ff
-		     is always assumed to be relevant to the frame
d8d6ff
-		     calculations; subsequent parts, are only
d8d6ff
-		     frame-related if explicitly marked.  */
d8d6ff
-	      RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0,
d8d6ff
-					    1)) = 1;
d8d6ff
 	      regno = regno2;
d8d6ff
 	      start_offset += increment * 2;
d8d6ff
 	    }
d8d6ff
 	  else
d8d6ff
 	    {
d8d6ff
 	      if (restore == false)
d8d6ff
-		insn = emit_move_insn (mem, gen_rtx_REG (DFmode, regno));
d8d6ff
+		{
d8d6ff
+		  insn = emit_move_insn (mem, reg1);
d8d6ff
+		  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
+		}
d8d6ff
 	      else
d8d6ff
 		{
d8d6ff
-		  insn = emit_move_insn (gen_rtx_REG (DFmode, regno), mem);
d8d6ff
-		  add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DImode, regno));
d8d6ff
+		  emit_move_insn (reg1, mem);
d8d6ff
+		  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg1, *cfi_ops);
d8d6ff
 		}
d8d6ff
 	      start_offset += increment;
d8d6ff
 	    }
d8d6ff
-	  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
 	}
d8d6ff
     }
d8d6ff
-
d8d6ff
 }
d8d6ff
 
d8d6ff
 
d8d6ff
@@ -1687,13 +1683,14 @@ aarch64_save_or_restore_fprs (int start_
d8d6ff
    restore's have to happen.  */
d8d6ff
 static void
d8d6ff
 aarch64_save_or_restore_callee_save_registers (HOST_WIDE_INT offset,
d8d6ff
-					    bool restore)
d8d6ff
+					       bool restore, rtx *cfi_ops)
d8d6ff
 {
d8d6ff
   rtx insn;
d8d6ff
   rtx base_rtx = stack_pointer_rtx;
d8d6ff
   HOST_WIDE_INT start_offset = offset;
d8d6ff
   HOST_WIDE_INT increment = UNITS_PER_WORD;
d8d6ff
-  rtx (*gen_mem_ref)(enum machine_mode, rtx) = (frame_pointer_needed)? gen_frame_mem : gen_rtx_MEM;
d8d6ff
+  rtx (*gen_mem_ref)(enum machine_mode, rtx)
d8d6ff
+    = (frame_pointer_needed)? gen_frame_mem : gen_rtx_MEM;
d8d6ff
   unsigned limit = (frame_pointer_needed)? R28_REGNUM: R30_REGNUM;
d8d6ff
   unsigned regno;
d8d6ff
   unsigned regno2;
d8d6ff
@@ -1702,11 +1699,13 @@ aarch64_save_or_restore_callee_save_regi
d8d6ff
     {
d8d6ff
       if (aarch64_register_saved_on_entry (regno))
d8d6ff
 	{
d8d6ff
-	  rtx mem;
d8d6ff
+	  rtx mem, reg1;
d8d6ff
+
d8d6ff
 	  mem = gen_mem_ref (Pmode,
d8d6ff
 			     plus_constant (Pmode,
d8d6ff
 					    base_rtx,
d8d6ff
 					    start_offset));
d8d6ff
+	  reg1 = gen_rtx_REG (DImode, regno);
d8d6ff
 
d8d6ff
 	  for (regno2 = regno + 1;
d8d6ff
 	       regno2 <= limit
d8d6ff
@@ -1718,56 +1717,54 @@ aarch64_save_or_restore_callee_save_regi
d8d6ff
 	  if (regno2 <= limit &&
d8d6ff
 	      aarch64_register_saved_on_entry (regno2))
d8d6ff
 	    {
d8d6ff
-	      rtx mem2;
d8d6ff
+	      rtx mem2, reg2;
d8d6ff
 	      /* Next highest register to be saved.  */
d8d6ff
 	      mem2 = gen_mem_ref (Pmode,
d8d6ff
 				  plus_constant
d8d6ff
 				  (Pmode,
d8d6ff
 				   base_rtx,
d8d6ff
 				   start_offset + increment));
d8d6ff
+	      reg2 = gen_rtx_REG (DImode, regno2);
d8d6ff
+
d8d6ff
 	      if (restore == false)
d8d6ff
 		{
d8d6ff
-		  insn = emit_insn
d8d6ff
-		    ( gen_store_pairdi (mem, gen_rtx_REG (DImode, regno),
d8d6ff
-					mem2, gen_rtx_REG (DImode, regno2)));
d8d6ff
-
d8d6ff
+		  insn = emit_insn (gen_store_pairdi (mem, reg1, mem2, reg2));
d8d6ff
+		  /* The first part of a frame-related parallel insn
d8d6ff
+		     is always assumed to be relevant to the frame
d8d6ff
+		     calculations; subsequent parts, are only
d8d6ff
+		     frame-related if explicitly marked.  */
d8d6ff
+		  RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
d8d6ff
+	  	  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
 		}
d8d6ff
 	      else
d8d6ff
 		{
d8d6ff
-		  insn = emit_insn
d8d6ff
-		    ( gen_load_pairdi (gen_rtx_REG (DImode, regno), mem,
d8d6ff
-				     gen_rtx_REG (DImode, regno2), mem2));
d8d6ff
-
d8d6ff
-		  add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DImode, regno));
d8d6ff
-		  add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DImode, regno2));
d8d6ff
+		  emit_insn (gen_load_pairdi (reg1, mem, reg2, mem2));
d8d6ff
+		  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg1, *cfi_ops);
d8d6ff
+		  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg2, *cfi_ops);
d8d6ff
 		}
d8d6ff
 
d8d6ff
-		  /* The first part of a frame-related parallel insn
d8d6ff
-		     is always assumed to be relevant to the frame
d8d6ff
-		     calculations; subsequent parts, are only
d8d6ff
-		     frame-related if explicitly marked.  */
d8d6ff
-	      RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0,
d8d6ff
-					    1)) = 1;
d8d6ff
 	      regno = regno2;
d8d6ff
 	      start_offset += increment * 2;
d8d6ff
 	    }
d8d6ff
 	  else
d8d6ff
 	    {
d8d6ff
 	      if (restore == false)
d8d6ff
-		insn = emit_move_insn (mem, gen_rtx_REG (DImode, regno));
d8d6ff
+		{
d8d6ff
+		  insn = emit_move_insn (mem, reg1);
d8d6ff
+	  	  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
+		}
d8d6ff
 	      else
d8d6ff
 		{
d8d6ff
-		  insn = emit_move_insn (gen_rtx_REG (DImode, regno), mem);
d8d6ff
-		  add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (DImode, regno));
d8d6ff
+		  emit_move_insn (reg1, mem);
d8d6ff
+		  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg1, *cfi_ops);
d8d6ff
 		}
d8d6ff
 	      start_offset += increment;
d8d6ff
 	    }
d8d6ff
-	  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
 	}
d8d6ff
     }
d8d6ff
 
d8d6ff
-  aarch64_save_or_restore_fprs (start_offset, increment, restore, base_rtx);
d8d6ff
-
d8d6ff
+  aarch64_save_or_restore_fprs (start_offset, increment, restore,
d8d6ff
+				base_rtx, cfi_ops);
d8d6ff
 }
d8d6ff
 
d8d6ff
 /* AArch64 stack frames generated by this compiler look like:
d8d6ff
@@ -1966,7 +1963,7 @@ aarch64_expand_prologue (void)
d8d6ff
 	}
d8d6ff
 
d8d6ff
       aarch64_save_or_restore_callee_save_registers
d8d6ff
-	(fp_offset + cfun->machine->frame.hardfp_offset, 0);
d8d6ff
+	(fp_offset + cfun->machine->frame.hardfp_offset, 0, NULL);
d8d6ff
     }
d8d6ff
 
d8d6ff
   /* when offset >= 512,
d8d6ff
@@ -1991,6 +1988,7 @@ aarch64_expand_epilogue (bool for_sibcal
d8d6ff
   HOST_WIDE_INT fp_offset;
d8d6ff
   rtx insn;
d8d6ff
   rtx cfa_reg;
d8d6ff
+  rtx cfi_ops = NULL;
d8d6ff
 
d8d6ff
   aarch64_layout_frame ();
d8d6ff
   original_frame_size = get_frame_size () + cfun->machine->saved_varargs_size;
d8d6ff
@@ -2035,15 +2033,17 @@ aarch64_expand_epilogue (bool for_sibcal
d8d6ff
       insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
d8d6ff
 				       hard_frame_pointer_rtx,
d8d6ff
 				       GEN_INT (- fp_offset)));
d8d6ff
+      /* CFA should be calculated from the value of SP from now on.  */
d8d6ff
+      add_reg_note (insn, REG_CFA_ADJUST_CFA,
d8d6ff
+		    gen_rtx_SET (VOIDmode, stack_pointer_rtx,
d8d6ff
+				 plus_constant (Pmode, hard_frame_pointer_rtx,
d8d6ff
+						-fp_offset)));
d8d6ff
       RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
-      /* As SP is set to (FP - fp_offset), according to the rules in
d8d6ff
-	 dwarf2cfi.c:dwarf2out_frame_debug_expr, CFA should be calculated
d8d6ff
-	 from the value of SP from now on.  */
d8d6ff
       cfa_reg = stack_pointer_rtx;
d8d6ff
     }
d8d6ff
 
d8d6ff
   aarch64_save_or_restore_callee_save_registers
d8d6ff
-    (fp_offset + cfun->machine->frame.hardfp_offset, 1);
d8d6ff
+    (fp_offset + cfun->machine->frame.hardfp_offset, 1, &cfi_ops);
d8d6ff
 
d8d6ff
   /* Restore the frame pointer and lr if the frame pointer is needed.  */
d8d6ff
   if (offset > 0)
d8d6ff
@@ -2051,6 +2051,8 @@ aarch64_expand_epilogue (bool for_sibcal
d8d6ff
       if (frame_pointer_needed)
d8d6ff
 	{
d8d6ff
 	  rtx mem_fp, mem_lr;
d8d6ff
+	  rtx reg_fp = hard_frame_pointer_rtx;
d8d6ff
+	  rtx reg_lr = gen_rtx_REG (DImode, LR_REGNUM);
d8d6ff
 
d8d6ff
 	  if (fp_offset)
d8d6ff
 	    {
d8d6ff
@@ -2063,52 +2065,36 @@ aarch64_expand_epilogue (bool for_sibcal
d8d6ff
 						     stack_pointer_rtx,
d8d6ff
 						     fp_offset
d8d6ff
 						     + UNITS_PER_WORD));
d8d6ff
-	      insn = emit_insn (gen_load_pairdi (hard_frame_pointer_rtx,
d8d6ff
-						 mem_fp,
d8d6ff
-						 gen_rtx_REG (DImode,
d8d6ff
-							      LR_REGNUM),
d8d6ff
-						 mem_lr));
d8d6ff
+	      emit_insn (gen_load_pairdi (reg_fp, mem_fp, reg_lr, mem_lr));
d8d6ff
+
d8d6ff
+	      insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
d8d6ff
+					       GEN_INT (offset)));
d8d6ff
 	    }
d8d6ff
 	  else
d8d6ff
 	    {
d8d6ff
 	      insn = emit_insn (gen_loadwb_pairdi_di
d8d6ff
-				(stack_pointer_rtx,
d8d6ff
-				 stack_pointer_rtx,
d8d6ff
-				 hard_frame_pointer_rtx,
d8d6ff
-				 gen_rtx_REG (DImode, LR_REGNUM),
d8d6ff
-				 GEN_INT (offset),
d8d6ff
+				(stack_pointer_rtx, stack_pointer_rtx,
d8d6ff
+				 reg_fp, reg_lr, GEN_INT (offset),
d8d6ff
 				 GEN_INT (GET_MODE_SIZE (DImode) + offset)));
d8d6ff
-	      RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 2)) = 1;
d8d6ff
-	      add_reg_note (insn, REG_CFA_ADJUST_CFA,
d8d6ff
-			    (gen_rtx_SET (Pmode, stack_pointer_rtx,
d8d6ff
-					  plus_constant (Pmode, cfa_reg,
d8d6ff
-							 offset))));
d8d6ff
-	    }
d8d6ff
-
d8d6ff
-	  /* The first part of a frame-related parallel insn
d8d6ff
-	     is always assumed to be relevant to the frame
d8d6ff
-	     calculations; subsequent parts, are only
d8d6ff
-	     frame-related if explicitly marked.  */
d8d6ff
-	  RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
d8d6ff
-	  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
-	  add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx);
d8d6ff
-	  add_reg_note (insn, REG_CFA_RESTORE,
d8d6ff
-			gen_rtx_REG (DImode, LR_REGNUM));
d8d6ff
-
d8d6ff
-	  if (fp_offset)
d8d6ff
-	    {
d8d6ff
-	      insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
d8d6ff
-					       GEN_INT (offset)));
d8d6ff
-	      RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
 	    }
d8d6ff
+	  cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg_fp, cfi_ops);
d8d6ff
+	  cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg_lr, cfi_ops);
d8d6ff
 	}
d8d6ff
       else
d8d6ff
 	{
d8d6ff
 	  insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
d8d6ff
 					   GEN_INT (offset)));
d8d6ff
-	  RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
 	}
d8d6ff
+      cfi_ops = alloc_reg_note (REG_CFA_ADJUST_CFA,
d8d6ff
+				gen_rtx_SET (VOIDmode, stack_pointer_rtx,
d8d6ff
+					     plus_constant (Pmode, cfa_reg,
d8d6ff
+							    offset)),
d8d6ff
+				cfi_ops);
d8d6ff
+      REG_NOTES (insn) = cfi_ops;
d8d6ff
+      RTX_FRAME_RELATED_P (insn) = 1;
d8d6ff
     }
d8d6ff
+  else
d8d6ff
+    gcc_assert (cfi_ops == NULL);
d8d6ff
 
d8d6ff
   /* Stack adjustment for exception handler.  */
d8d6ff
   if (crtl->calls_eh_return)