]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rs6000.c (rs6000_emit_prologue): Do not place a RTX_FRAME_RELATED_P marker on the...
authorUlrich Weigand <uweigand@de.ibm.com>
Thu, 14 Nov 2013 18:24:32 +0000 (18:24 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Thu, 14 Nov 2013 18:24:32 +0000 (18:24 +0000)
ChangeLog:

2013-11-14  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

* config/rs6000/rs6000.c (rs6000_emit_prologue): Do not place a
RTX_FRAME_RELATED_P marker on the UNSPEC_MOVESI_FROM_CR insn.
Instead, add USEs of all modified call-saved CR fields to the
insn storing the result to the stack slot, and provide an
appropriate REG_FRAME_RELATED_EXPR for that insn.
* config/rs6000/rs6000.md ("*crsave"): New insn pattern.
* config/rs6000/predicates.md ("crsave_operation"): New predicate.

testsuite/ChangeLog:

2013-11-14  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

* g++.dg/eh/ppc64-sighandle-cr.C: New test.

From-SVN: r204799

gcc/ChangeLog
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog

index cc088e04db7febc4b8ec921cf080d82fd4460cd0..307ac548e56473e0432b79abd32b15458d45859e 100644 (file)
@@ -1,3 +1,13 @@
+2013-11-14  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       * config/rs6000/rs6000.c (rs6000_emit_prologue): Do not place a
+       RTX_FRAME_RELATED_P marker on the UNSPEC_MOVESI_FROM_CR insn.
+       Instead, add USEs of all modified call-saved CR fields to the
+       insn storing the result to the stack slot, and provide an
+       appropriate REG_FRAME_RELATED_EXPR for that insn.
+       * config/rs6000/rs6000.md ("*crsave"): New insn pattern.
+       * config/rs6000/predicates.md ("crsave_operation"): New predicate.
+
 2013-11-14  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
            Alan Modra  <amodra@gmail.com>
 
index b5bff04477911819aadfed8431ec113c30cf081b..3f46001daf63309bd67277b32791ae2565460587 100644 (file)
   return 1;
 })
 
+;; Return 1 if OP is valid for crsave insn, known to be a PARALLEL.
+(define_predicate "crsave_operation"
+  (match_code "parallel")
+{
+  int count = XVECLEN (op, 0);
+  int i;
+
+  for (i = 1; i < count; i++)
+    {
+      rtx exp = XVECEXP (op, 0, i);
+
+      if (GET_CODE (exp) != USE
+         || GET_CODE (XEXP (exp, 0)) != REG
+         || GET_MODE (XEXP (exp, 0)) != CCmode
+         || ! CR_REGNO_P (REGNO (XEXP (exp, 0))))
+       return 0;
+    }
+  return 1;
+})
+
 ;; Return 1 if OP is valid for lmw insn, known to be a PARALLEL.
 (define_predicate "lmw_operation"
   (match_code "parallel")
index c6faa40bf24ac664543f4e0eb22db8197946cc51..1628bf31a1b4605d354f87277644e33b32b35768 100644 (file)
@@ -21766,21 +21766,9 @@ rs6000_emit_prologue (void)
       && REGNO (frame_reg_rtx) != cr_save_regno
       && !(using_static_chain_p && cr_save_regno == 11))
     {
-      rtx set;
-
       cr_save_rtx = gen_rtx_REG (SImode, cr_save_regno);
       START_USE (cr_save_regno);
-      insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
-      RTX_FRAME_RELATED_P (insn) = 1;
-      /* Now, there's no way that dwarf2out_frame_debug_expr is going
-        to understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)'.
-        But that's OK.  All we have to do is specify that _one_ condition
-        code register is saved in this stack slot.  The thrower's epilogue
-        will then restore all the call-saved registers.
-        We use CR2_REGNO (70) to be compatible with gcc-2.95 on Linux.  */
-      set = gen_rtx_SET (VOIDmode, cr_save_rtx,
-                        gen_rtx_REG (SImode, CR2_REGNO));
-      add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
+      emit_insn (gen_movesi_from_cr (cr_save_rtx));
     }
 
   /* Do any required saving of fpr's.  If only one or two to save, do
@@ -22091,26 +22079,62 @@ rs6000_emit_prologue (void)
       rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
                               GEN_INT (info->cr_save_offset + frame_off));
       rtx mem = gen_frame_mem (SImode, addr);
-      /* See the large comment above about why CR2_REGNO is used.  */
-      rtx magic_eh_cr_reg = gen_rtx_REG (SImode, CR2_REGNO);
 
       /* If we didn't copy cr before, do so now using r0.  */
       if (cr_save_rtx == NULL_RTX)
        {
-         rtx set;
-
          START_USE (0);
          cr_save_rtx = gen_rtx_REG (SImode, 0);
-         insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
-         RTX_FRAME_RELATED_P (insn) = 1;
-         set = gen_rtx_SET (VOIDmode, cr_save_rtx, magic_eh_cr_reg);
-         add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
-       }
-      insn = emit_move_insn (mem, cr_save_rtx);
+         emit_insn (gen_movesi_from_cr (cr_save_rtx));
+       }
+
+      /* Saving CR requires a two-instruction sequence: one instruction
+        to move the CR to a general-purpose register, and a second
+        instruction that stores the GPR to memory.
+
+        We do not emit any DWARF CFI records for the first of these,
+        because we cannot properly represent the fact that CR is saved in
+        a register.  One reason is that we cannot express that multiple
+        CR fields are saved; another reason is that on 64-bit, the size
+        of the CR register in DWARF (4 bytes) differs from the size of
+        a general-purpose register.
+
+        This means if any intervening instruction were to clobber one of
+        the call-saved CR fields, we'd have incorrect CFI.  To prevent
+        this from happening, we mark the store to memory as a use of
+        those CR fields, which prevents any such instruction from being
+        scheduled in between the two instructions.  */
+      rtx crsave_v[9];
+      int n_crsave = 0;
+      int i;
+
+      crsave_v[n_crsave++] = gen_rtx_SET (VOIDmode, mem, cr_save_rtx);
+      for (i = 0; i < 8; i++)
+       if (save_reg_p (CR0_REGNO + i))
+         crsave_v[n_crsave++]
+           = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
+
+      insn = emit_insn (gen_rtx_PARALLEL (VOIDmode,
+                                         gen_rtvec_v (n_crsave, crsave_v)));
       END_USE (REGNO (cr_save_rtx));
 
-      rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
-                           NULL_RTX, NULL_RTX);
+      /* Now, there's no way that dwarf2out_frame_debug_expr is going to
+        understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)',
+        so we need to construct a frame expression manually.  */
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      /* Update address to be stack-pointer relative, like
+        rs6000_frame_related would do.  */
+      addr = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM),
+                          GEN_INT (info->cr_save_offset + sp_off));
+      mem = gen_frame_mem (SImode, addr);
+
+      /* We still cannot express that multiple CR fields are saved in the
+        CR save slot.  By convention, we use a single CR regnum to represent
+        the fact that all call-saved CR fields are saved.  We use CR2_REGNO
+        to be compatible with gcc-2.95 on Linux.  */
+      rtx set = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, CR2_REGNO));
+      add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
     }
 
   /* Update stack and set back pointer unless this is V.4,
index d299a466a2d26218d349f3457ef9e880007f18c1..20204682069ec6d1366c5b50a5eb414995c2564c 100644 (file)
   "mfcr %0"
   [(set_attr "type" "mfcr")])
 
+(define_insn "*crsave"
+  [(match_parallel 0 "crsave_operation"
+                  [(set (match_operand:SI 1 "memory_operand" "=m")
+                        (match_operand:SI 2 "gpc_reg_operand" "r"))])]
+  ""
+  "stw %2,%1"
+  [(set_attr "type" "store")])
+
 (define_insn "*stmw"
   [(match_parallel 0 "stmw_operation"
                   [(set (match_operand:SI 1 "memory_operand" "=m")
index 0f95048e0caa7ba4383839b1a7126f25cd37cccc..be9a3a56b99dac6e510e9cfa3af92c769fbfde3a 100644 (file)
@@ -1,3 +1,7 @@
+2013-11-14  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       * g++.dg/eh/ppc64-sighandle-cr.C: New test.
+
 2013-11-14  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * gcc.dg/torture/float128-cmp-invalid.c: Require fenv_exceptions.