re PR rtl-optimization/50063 (DSE: wrong code for gcc.dg/torture/pta-ptrarith-3.c)

PR rtl-optimization/50063
	* config/avr/avr.md (movhi_sp_r): Handle -1 (unknown IRQ state)
	and 2 (8-bit SP) in operand 2.
	* config/avr/avr.c (avr_prologue_setup_frame): Adjust prologue
	setup to use movhi_sp_r instead of vanilla move to write SP.
	Adjust REG_CFA notes to superseed unspec.
	(expand_epilogue): Adjust epilogue setup to use movhi_sp_r instead
	of vanilla move.
	As function body might contain CLI or SEI: Use irq_state 0 (IRQ
	known to be off) only with TARGET_NO_INTERRUPTS. Never use
	irq_state 1 (IRQ known to be on) here.

From-SVN: r184461
This commit is contained in:
Georg-Johann Lay 2012-02-22 09:25:35 +00:00 committed by Georg-Johann Lay
parent 8d071654dc
commit 0b262c28c6
3 changed files with 84 additions and 63 deletions

View File

@ -1,3 +1,17 @@
2012-02-22 Georg-Johann Lay <avr@gjlay.de>
PR rtl-optimization/50063
* config/avr/avr.md (movhi_sp_r): Handle -1 (unknown IRQ state)
and 2 (8-bit SP) in operand 2.
* config/avr/avr.c (avr_prologue_setup_frame): Adjust prologue
setup to use movhi_sp_r instead of vanilla move to write SP.
Adjust REG_CFA notes to superseed unspec.
(expand_epilogue): Adjust epilogue setup to use movhi_sp_r instead
of vanilla move.
As function body might contain CLI or SEI: Use irq_state 0 (IRQ
known to be off) only with TARGET_NO_INTERRUPTS. Never use
irq_state 1 (IRQ known to be on) here.
2012-02-21 Bernd Schmidt <bernds@codesourcery.com> 2012-02-21 Bernd Schmidt <bernds@codesourcery.com>
* ira.c (check_allocation): Use REG_WORDS_BIG_ENDIAN, not * ira.c (check_allocation): Use REG_WORDS_BIG_ENDIAN, not

View File

@ -1062,8 +1062,8 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
!frame_pointer_needed can only occur if the function is not a !frame_pointer_needed can only occur if the function is not a
leaf function and thus X has already been saved. */ leaf function and thus X has already been saved. */
int irq_state = -1;
rtx fp_plus_insns, fp, my_fp; rtx fp_plus_insns, fp, my_fp;
rtx sp_minus_size = plus_constant (stack_pointer_rtx, -size);
gcc_assert (frame_pointer_needed gcc_assert (frame_pointer_needed
|| !isr_p || !isr_p
@ -1076,7 +1076,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
if (AVR_HAVE_8BIT_SP) if (AVR_HAVE_8BIT_SP)
{ {
/* The high byte (r29) does not change: /* The high byte (r29) does not change:
Prefer SUBI (1 cycle) over ABIW (2 cycles, same size). */ Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
my_fp = all_regs_rtx[FRAME_POINTER_REGNUM]; my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
} }
@ -1092,42 +1092,49 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
the frame pointer subtraction is done. */ the frame pointer subtraction is done. */
insn = emit_move_insn (fp, stack_pointer_rtx); insn = emit_move_insn (fp, stack_pointer_rtx);
if (!frame_pointer_needed)
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (my_fp, plus_constant (my_fp, -size));
RTX_FRAME_RELATED_P (insn) = 1;
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_ADJUST_CFA, add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (VOIDmode, fp, sp_minus_size)); gen_rtx_SET (VOIDmode, fp, stack_pointer_rtx));
}
insn = emit_move_insn (my_fp, plus_constant (my_fp, -size));
if (frame_pointer_needed)
{
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (VOIDmode, fp,
plus_constant (fp, -size)));
} }
/* Copy to stack pointer. Note that since we've already /* Copy to stack pointer. Note that since we've already
changed the CFA to the frame pointer this operation changed the CFA to the frame pointer this operation
need not be annotated if frame pointer is needed. */ need not be annotated if frame pointer is needed.
Always move through unspec, see PR50063.
For meaning of irq_state see movhi_sp_r insn. */
if (AVR_HAVE_8BIT_SP || AVR_XMEGA) if (cfun->machine->is_interrupt)
{ irq_state = 1;
insn = emit_move_insn (stack_pointer_rtx, fp);
}
else if (TARGET_NO_INTERRUPTS
|| isr_p
|| cfun->machine->is_OS_main)
{
rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx, if (TARGET_NO_INTERRUPTS
fp, irqs_are_on)); || cfun->machine->is_signal
} || cfun->machine->is_OS_main)
else irq_state = 0;
{
insn = emit_move_insn (stack_pointer_rtx, fp);
}
if (AVR_HAVE_8BIT_SP)
irq_state = 2;
insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
fp, GEN_INT (irq_state)));
if (!frame_pointer_needed) if (!frame_pointer_needed)
RTX_FRAME_RELATED_P (insn) = 1; {
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx,
-size)));
}
fp_plus_insns = get_insns (); fp_plus_insns = get_insns ();
end_sequence (); end_sequence ();
@ -1143,9 +1150,13 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
start_sequence (); start_sequence ();
insn = emit_move_insn (stack_pointer_rtx, sp_minus_size); insn = emit_move_insn (stack_pointer_rtx,
plus_constant (stack_pointer_rtx, -size));
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx,
-size)));
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
insn = emit_move_insn (fp, stack_pointer_rtx); insn = emit_move_insn (fp, stack_pointer_rtx);
@ -1377,6 +1388,7 @@ expand_epilogue (bool sibcall_p)
{ {
/* Try two methods to adjust stack and select shortest. */ /* Try two methods to adjust stack and select shortest. */
int irq_state = -1;
rtx fp, my_fp; rtx fp, my_fp;
rtx fp_plus_insns; rtx fp_plus_insns;
@ -1407,22 +1419,14 @@ expand_epilogue (bool sibcall_p)
/* Copy to stack pointer. */ /* Copy to stack pointer. */
if (AVR_HAVE_8BIT_SP || AVR_XMEGA) if (TARGET_NO_INTERRUPTS)
{ irq_state = 0;
emit_move_insn (stack_pointer_rtx, fp);
}
else if (TARGET_NO_INTERRUPTS
|| isr_p
|| cfun->machine->is_OS_main)
{
rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp, irqs_are_on)); if (AVR_HAVE_8BIT_SP)
} irq_state = 2;
else
{ emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
emit_move_insn (stack_pointer_rtx, fp); GEN_INT (irq_state)));
}
fp_plus_insns = get_insns (); fp_plus_insns = get_insns ();
end_sequence (); end_sequence ();

View File

@ -583,23 +583,26 @@
;; Move register $1 to the Stack Pointer register SP. ;; Move register $1 to the Stack Pointer register SP.
;; This insn is emit during function prologue/epilogue generation. ;; This insn is emit during function prologue/epilogue generation.
;; $2 = 0: We know that IRQs are off ;; $2 = 0: We know that IRQs are off
;; $2 = 1: We know that IRQs are on ;; $2 = 1: We know that IRQs are on
;; Remaining cases when the state of the I-Flag is unknown are ;; $2 = 2: SP has 8 bits only, IRQ state does not matter
;; handled by generic movhi insn. ;; $2 = -1: We don't know anything about IRQ on/off
;; Always write SP via unspec, see PR50063
(define_insn "movhi_sp_r" (define_insn "movhi_sp_r"
[(set (match_operand:HI 0 "stack_register_operand" "=q,q,q") [(set (match_operand:HI 0 "stack_register_operand" "=q,q,q,q,q")
(unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r,r") (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r,r,r,r")
(match_operand:HI 2 "const_int_operand" "L,P,LP")] (match_operand:HI 2 "const_int_operand" "L,P,N,K,LPN")]
UNSPECV_WRITE_SP))] UNSPECV_WRITE_SP))]
"!AVR_HAVE_8BIT_SP" ""
"@ "@
out __SP_H__,%B1\;out __SP_L__,%A1 out %B0,%B1\;out %A0,%A1
cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1 cli\;out %B0,%B1\;sei\;out %A0,%A1
out __SP_L__,%A1\;out __SP_H__,%B1" in __tmp_reg__,__SREG__\;cli\;out %B0,%B1\;out __SREG__,__tmp_reg__\;out %A0,%A1
[(set_attr "length" "2,4,2") out %A0,%A1
(set_attr "isa" "no_xmega,no_xmega,xmega") out %A0,%A1\;out %B0,%B1"
[(set_attr "length" "2,4,5,1,2")
(set_attr "isa" "no_xmega,no_xmega,no_xmega,*,xmega")
(set_attr "cc" "none")]) (set_attr "cc" "none")])
(define_peephole2 (define_peephole2