rs6000.c (rs6000_emit_prologue): Do not place a RTX_FRAME_RELATED_P marker on the UNSPEC_MOVESI_FROM_CR insn.
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
This commit is contained in:
parent
2e4ceca56c
commit
dc2faee140
|
@ -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>
|
||||
|
||||
|
|
|
@ -1538,6 +1538,26 @@
|
|||
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")
|
||||
|
|
|
@ -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);
|
||||
emit_insn (gen_movesi_from_cr (cr_save_rtx));
|
||||
}
|
||||
insn = emit_move_insn (mem, 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,
|
||||
|
|
|
@ -15035,6 +15035,14 @@
|
|||
"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")
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue