Commit 0b262c28 by Georg-Johann Lay Committed by Georg-Johann Lay

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
parent 8d071654
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
......
...@@ -1062,8 +1062,8 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) ...@@ -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) ...@@ -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,43 +1092,50 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) ...@@ -1092,43 +1092,50 @@ 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) 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, fp, stack_pointer_rtx));
}
insn = emit_move_insn (my_fp, plus_constant (my_fp, -size)); 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,
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.
if (AVR_HAVE_8BIT_SP || AVR_XMEGA) For meaning of irq_state see movhi_sp_r insn. */
{
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,
fp, irqs_are_on));
}
else
{
insn = emit_move_insn (stack_pointer_rtx, fp);
}
if (!frame_pointer_needed) if (cfun->machine->is_interrupt)
RTX_FRAME_RELATED_P (insn) = 1; irq_state = 1;
if (TARGET_NO_INTERRUPTS
|| cfun->machine->is_signal
|| cfun->machine->is_OS_main)
irq_state = 0;
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)
{
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) ...@@ -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);
...@@ -1376,7 +1387,8 @@ expand_epilogue (bool sibcall_p) ...@@ -1376,7 +1387,8 @@ expand_epilogue (bool sibcall_p)
if (size) if (size)
{ {
/* 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;
...@@ -1406,23 +1418,15 @@ expand_epilogue (bool sibcall_p) ...@@ -1406,23 +1418,15 @@ expand_epilogue (bool sibcall_p)
emit_move_insn (my_fp, plus_constant (my_fp, size)); emit_move_insn (my_fp, plus_constant (my_fp, size));
/* 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);
} if (AVR_HAVE_8BIT_SP)
else if (TARGET_NO_INTERRUPTS irq_state = 2;
|| isr_p
|| cfun->machine->is_OS_main) emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
{ GEN_INT (irq_state)));
rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp, irqs_are_on));
}
else
{
emit_move_insn (stack_pointer_rtx, fp);
}
fp_plus_insns = get_insns (); fp_plus_insns = get_insns ();
end_sequence (); end_sequence ();
......
...@@ -583,23 +583,26 @@ ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment