From b5b90b5a2b71100ac888ea978e13682cac81ad57 Mon Sep 17 00:00:00 2001 From: gjl Date: Wed, 22 Feb 2012 09:25:35 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184461 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 +++++++ gcc/config/avr/avr.c | 100 ++++++++++++++++++++++++++------------------------ gcc/config/avr/avr.md | 29 ++++++++------- 3 files changed, 82 insertions(+), 61 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 88c01d4eb83..d5aa9114079 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2012-02-22 Georg-Johann Lay + + 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 * ira.c (check_allocation): Use REG_WORDS_BIG_ENDIAN, not diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 8a0d69ae3ea..2a462922976 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -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 leaf function and thus X has already been saved. */ + int irq_state = -1; rtx fp_plus_insns, fp, my_fp; - rtx sp_minus_size = plus_constant (stack_pointer_rtx, -size); gcc_assert (frame_pointer_needed || !isr_p @@ -1076,7 +1076,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) if (AVR_HAVE_8BIT_SP) { /* 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]; } @@ -1092,43 +1092,50 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) the frame pointer subtraction is done. */ insn = emit_move_insn (fp, stack_pointer_rtx); - if (!frame_pointer_needed) - RTX_FRAME_RELATED_P (insn) = 1; + if (frame_pointer_needed) + { + 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)); - RTX_FRAME_RELATED_P (insn) = 1; - if (frame_pointer_needed) { + RTX_FRAME_RELATED_P (insn) = 1; 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 changed the CFA to the frame pointer this operation - need not be annotated if frame pointer is needed. */ - - if (AVR_HAVE_8BIT_SP || AVR_XMEGA) - { - 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); - } + 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 (!frame_pointer_needed) - RTX_FRAME_RELATED_P (insn) = 1; + if (cfun->machine->is_interrupt) + 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 (); end_sequence (); @@ -1143,9 +1150,13 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) 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; - + 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) { insn = emit_move_insn (fp, stack_pointer_rtx); @@ -1376,7 +1387,8 @@ expand_epilogue (bool sibcall_p) if (size) { /* Try two methods to adjust stack and select shortest. */ - + + int irq_state = -1; rtx fp, my_fp; rtx fp_plus_insns; @@ -1406,23 +1418,15 @@ expand_epilogue (bool sibcall_p) emit_move_insn (my_fp, plus_constant (my_fp, size)); /* Copy to stack pointer. */ - - if (AVR_HAVE_8BIT_SP || AVR_XMEGA) - { - 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)); - } - else - { - emit_move_insn (stack_pointer_rtx, fp); - } + + if (TARGET_NO_INTERRUPTS) + irq_state = 0; + + if (AVR_HAVE_8BIT_SP) + irq_state = 2; + + emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp, + GEN_INT (irq_state))); fp_plus_insns = get_insns (); end_sequence (); diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index a7fa04cb51f..b217d032726 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -583,23 +583,26 @@ ;; Move register $1 to the Stack Pointer register SP. ;; This insn is emit during function prologue/epilogue generation. -;; $2 = 0: We know that IRQs are off -;; $2 = 1: We know that IRQs are on -;; Remaining cases when the state of the I-Flag is unknown are -;; handled by generic movhi insn. +;; $2 = 0: We know that IRQs are off +;; $2 = 1: We know that IRQs are on +;; $2 = 2: SP has 8 bits only, IRQ state does not matter +;; $2 = -1: We don't know anything about IRQ on/off +;; Always write SP via unspec, see PR50063 (define_insn "movhi_sp_r" - [(set (match_operand:HI 0 "stack_register_operand" "=q,q,q") - (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r,r") - (match_operand:HI 2 "const_int_operand" "L,P,LP")] + [(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,r,r") + (match_operand:HI 2 "const_int_operand" "L,P,N,K,LPN")] UNSPECV_WRITE_SP))] - "!AVR_HAVE_8BIT_SP" + "" "@ - out __SP_H__,%B1\;out __SP_L__,%A1 - cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1 - out __SP_L__,%A1\;out __SP_H__,%B1" - [(set_attr "length" "2,4,2") - (set_attr "isa" "no_xmega,no_xmega,xmega") + out %B0,%B1\;out %A0,%A1 + cli\;out %B0,%B1\;sei\;out %A0,%A1 + in __tmp_reg__,__SREG__\;cli\;out %B0,%B1\;out __SREG__,__tmp_reg__\;out %A0,%A1 + out %A0,%A1 + 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")]) (define_peephole2 -- 2.11.4.GIT