Re: [Patch, ARM][3/8] Epilogue in RTL: new patterns for vfp regs

2012-06-15 Thread Richard Earnshaw
On 31/05/12 14:55, Greta Yorsh wrote:
 New define insn pattern for epilogue with floating point registers (DFmode)
 and a new function that emits RTL for this pattern. This function is a
 helper for epilogue extension. It is used by a later patch.
 
 ChangeLog:
 
 gcc
 
 2012-05-31  Ian Bolton  ian.bol...@arm.com
 Sameera Deshpande  sameera.deshpa...@arm.com
 Greta Yorsh  greta.yo...@arm.com
 
 * config/arm/arm.md (vfp_pop_multiple_with_writeback) New
 define_insn.
 * config/arm/predicates.md (pop_multiple_fp) New special predicate.
 * config/arm/arm.c (arm_emit_vfp_multi_reg_pop): New function.
 
 

OK.

R.



[Patch, ARM][3/8] Epilogue in RTL: new patterns for vfp regs

2012-05-31 Thread Greta Yorsh
New define insn pattern for epilogue with floating point registers (DFmode)
and a new function that emits RTL for this pattern. This function is a
helper for epilogue extension. It is used by a later patch.

ChangeLog:

gcc

2012-05-31  Ian Bolton  ian.bol...@arm.com
Sameera Deshpande  sameera.deshpa...@arm.com
Greta Yorsh  greta.yo...@arm.com

* config/arm/arm.md (vfp_pop_multiple_with_writeback) New
define_insn.
* config/arm/predicates.md (pop_multiple_fp) New special predicate.
* config/arm/arm.c (arm_emit_vfp_multi_reg_pop): New function.diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 9093801..491ffea 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -16618,6 +16618,76 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
   REG_NOTES (par) = dwarf;
 }
 
+/* Generate and emit an insn pattern that we will recognize as a pop_multi
+   of NUM_REGS consecutive VFP regs, starting at FIRST_REG.
+
+   Unfortunately, since this insn does not reflect very well the actual
+   semantics of the operation, we need to annotate the insn for the benefit
+   of DWARF2 frame unwind information.  */
+static void
+arm_emit_vfp_multi_reg_pop (int first_reg, int num_regs, rtx base_reg)
+{
+  int i, j;
+  rtx par;
+  rtx dwarf = NULL_RTX;
+  rtx tmp, reg;
+
+  gcc_assert (num_regs  num_regs = 32);
+
+/* Workaround ARM10 VFPr1 bug.  */
+  if (num_regs == 2  !arm_arch6)
+{
+  if (first_reg == 15)
+first_reg--;
+
+  num_regs++;
+}
+
+  /* We can emit at most 16 D-registers in a single pop_multi instruction, and
+ there could be up to 32 D-registers to restore.
+ If there are more than 16 D-registers, make two recursive calls,
+ each of which emits one pop_multi instruction.  */
+  if (num_regs  16)
+{
+  arm_emit_vfp_multi_reg_pop (first_reg, 16, base_reg);
+  arm_emit_vfp_multi_reg_pop (first_reg + 16, num_regs - 16, base_reg);
+  return;
+}
+
+  /* The parallel needs to hold num_regs SETs
+ and one SET for the stack update.  */
+  par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs + 1));
+
+  /* Increment the stack pointer, based on there being
+ num_regs 8-byte registers to restore.  */
+  tmp = gen_rtx_SET (VOIDmode,
+ base_reg,
+ plus_constant (base_reg, 8 * num_regs));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (par, 0, 0) = tmp;
+
+  /* Now show every reg that will be restored, using a SET for each.  */
+  for (j = 0, i=first_reg; j  num_regs; i += 2)
+{
+  reg = gen_rtx_REG (DFmode, i);
+
+  tmp = gen_rtx_SET (VOIDmode,
+ reg,
+ gen_frame_mem
+ (DFmode,
+  plus_constant (base_reg, 8 * j)));
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (par, 0, j + 1) = tmp;
+
+  dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+
+  j++;
+}
+
+  par = emit_insn (par);
+  REG_NOTES (par) = dwarf;
+}
+
 /* Calculate the size of the return value that is passed in registers.  */
 static unsigned
 arm_size_return_regs (void)
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 862ccf4..98387fa 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11042,6 +11042,41 @@
   [(set_attr type load1)
(set_attr predicable yes)]
 )
+;; Pop for floating point registers (as used in epilogue RTL)
+(define_insn *vfp_pop_multiple_with_writeback
+  [(match_parallel 0 pop_multiple_fp
+[(set (match_operand:SI 1 s_register_operand +rk)
+  (plus:SI (match_dup 1)
+   (match_operand:SI 2 const_int_operand I)))
+ (set (match_operand:DF 3 arm_hard_register_operand )
+  (mem:DF (match_dup 1)))])]
+  TARGET_32BIT  TARGET_HARD_FLOAT  TARGET_VFP
+  *
+  {
+int num_regs = XVECLEN (operands[0], 0);
+char pattern[100];
+rtx op_list[2];
+strcpy (pattern, \fldmfdd\\t\);
+strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 
0)))]);
+strcat (pattern, \!, {\);
+op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
+strcat (pattern, \%P0\);
+if ((num_regs - 1)  1)
+  {
+strcat (pattern, \-%P1\);
+op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
+  }
+
+strcat (pattern, \}\);
+output_asm_insn (pattern, op_list);
+return \\;
+  }
+  
+  [(set_attr type load4)
+   (set_attr conds unconditional)
+   (set_attr predicable no)]
+)
+
 ;; Special patterns for dealing with the constant pool
 
 (define_insn align_4
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 24dd4ea..92114bd 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -401,6 +401,14 @@
  /*return_pc=*/true);
 })
 
+(define_special_predicate pop_multiple_fp
+  (match_code parallel)
+{
+ return ldm_stm_operation_p (op, /*load=*/true, DFmode,
+