From a42f1f7028fa80961114dab58ec9e028fcf9f9bd Mon Sep 17 00:00:00 2001
From: Richard Lowe <richlowe@richlowe.net>
Date: Fri, 3 May 2019 00:56:45 +0000
Subject: i386: don't assert the FP is valid during epilogue
 adjustment

I did this, I think, to double check some assumptions.  Unfortunately,
there is a case where the fp won't be valid here, despite us having
saved arguments.  That where we're returning through an error handler
via __builtin_eh_return().

While here, make the code more readable and conventional.
---
 gcc/config/i386/i386.cc | 68 +++++++++++++++++++----------------------
 1 file changed, 32 insertions(+), 36 deletions(-)

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 25ae3371a45f..6387a7206f63 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -7198,21 +7198,21 @@ static void
 ix86_emit_save_regs (void)
 {
   unsigned int regno;
+  struct ix86_frame &frame = cfun->machine->frame;
   rtx_insn *insn;
 
   if (TARGET_SAVE_ARGS)
     {
       int i;
-      int nsaved = ix86_nsaved_args ();
       int start = cfun->returns_struct;
 
-      for (i = start; i < start + nsaved; i++)
+      for (i = start; i < start + frame.nmsave_args; i++)
 	{
 	  regno = x86_64_int_parameter_registers[i];
 	  insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno)));
 	  RTX_FRAME_RELATED_P (insn) = 1;
 	}
-      if (nsaved % 2 != 0)
+      if (frame.nmsave_args % 2 != 0)
 	pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
 				   GEN_INT (-UNITS_PER_WORD), -1, false);
     }
@@ -7303,22 +7303,21 @@ ix86_emit_save_reg_using_mov (machine_mode mode, unsigned int regno,
 /* Emit code to save registers using MOV insns.
    First register is stored at CFA - CFA_OFFSET.  */
 static void
-ix86_emit_save_regs_using_mov (const struct ix86_frame *frame)
+ix86_emit_save_regs_using_mov (const struct ix86_frame &frame)
 {
   unsigned int regno;
-  HOST_WIDE_INT cfa_offset = frame->arg_save_offset;
+  HOST_WIDE_INT cfa_offset = frame.arg_save_offset;
 
   if (TARGET_SAVE_ARGS)
     {
       int i;
-      int nsaved = ix86_nsaved_args ();
       int start = cfun->returns_struct;
 
       /* We deal with this twice? */
-      if (nsaved % 2 != 0)
+      if (frame.nmsave_args % 2 != 0)
 	cfa_offset -= UNITS_PER_WORD;
 
-      for (i = start + nsaved - 1; i >= start; i--)
+      for (i = start + frame.nmsave_args - 1; i >= start; i--)
 	{
 	  regno = x86_64_int_parameter_registers[i];
 	  ix86_emit_save_reg_using_mov(word_mode, regno, cfa_offset);
@@ -7326,7 +7325,7 @@ ix86_emit_save_regs_using_mov (const struct ix86_frame *frame)
 	}
     }
 
-  cfa_offset = frame->reg_save_offset;
+  cfa_offset = frame.reg_save_offset;
 
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, true, true))
@@ -8723,7 +8722,7 @@ ix86_expand_prologue (void)
 	       && (! TARGET_STACK_PROBE
 		   || frame.stack_pointer_offset < CHECK_STACK_LIMIT))
 	{
-	  ix86_emit_save_regs_using_mov (&frame);
+	  ix86_emit_save_regs_using_mov (frame);
 	  cfun->machine->red_zone_used = true;
 	  int_registers_saved = true;
 	}
@@ -9023,7 +9022,7 @@ ix86_expand_prologue (void)
     }
 
   if (!int_registers_saved)
-    ix86_emit_save_regs_using_mov (&frame);
+    ix86_emit_save_regs_using_mov (frame);
   if (!sse_registers_saved)
     ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset);
   else if (save_stub_call_needed)
@@ -9683,33 +9682,30 @@ ix86_expand_epilogue (int style)
       ix86_emit_restore_regs_using_pop ();
     }
 
-  if (TARGET_SAVE_ARGS) {
-    /*
-     * For each saved argument, emit a restore note, to make sure it happens
-     * correctly within the shrink wrapping (I think).
-     *
-     * Note that 'restore' in this case merely means the rule is the same as
-     * it was on function entry, not that we have actually done a register
-     * restore (which of course, we haven't).
-     *
-     * If we do not do this, the DWARF code will emit sufficient restores to
-     * provide balance on its own initiative, which in the presence of
-     * -fshrink-wrap may actually _introduce_ unbalance (whereby we only
-     * .cfi_offset a register sometimes, but will always .cfi_restore it.
-     * This will trip an assert.)
-     */
-    int start = cfun->returns_struct;
-    int nsaved = ix86_nsaved_args();
-    int i;
-
-    for (i = start + nsaved - 1; i >= start; i--)
-      queued_cfa_restores
-	= alloc_reg_note (REG_CFA_RESTORE,
+  /*
+   * For each saved argument, emit a restore note, to make sure it happens
+   * correctly within the shrink wrapping (I think).
+   *
+   * Note that 'restore' in this case merely means the rule is the same as
+   * it was on function entry, not that we have actually done a register
+   * restore (which of course, we haven't).
+   *
+   * If we do not do this, the DWARF code will emit sufficient restores to
+   * provide balance on its own initiative, which in the presence of
+   * -fshrink-wrap may actually _introduce_ unbalance (whereby we only
+   * .cfi_offset a register sometimes, but will always .cfi_restore it.
+   * This will trip an assert.)
+   */
+  if (TARGET_SAVE_ARGS && frame.nmsave_args > 0) {
+	  int start = cfun->returns_struct;
+	  int i;
+
+	  for (i = start + frame.nmsave_args - 1; i >= start; i--)
+		  queued_cfa_restores
+		      = alloc_reg_note (REG_CFA_RESTORE,
 			  gen_rtx_REG(Pmode,
-				      x86_64_int_parameter_registers[i]),
+			      x86_64_int_parameter_registers[i]),
 			  queued_cfa_restores);
-
-    gcc_assert(m->fs.fp_valid);
   }
 
   /* If we used a stack pointer and haven't already got rid of it,