diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7ce99da8c3e..8773d622c18 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2012-01-27 Georg-Johann Lay + + * config/avr/avr-protos.h (lpm_reg_rtx, lpm_addr_reg_rtx, + tmp_reg_rtx, zero_reg_rtx, all_regs_rtx, rampz_rtx): Make global. + * config/avr/avr.c: Ditto. + (avr_regnames): Remove because unused. + * config/avr/avr.md (*cpse.ne): New peephole. + (*cpse.eq): New peephole from former cpse peepholes. + 2012-01-27 Michael Eager * config/microblaze.c (microblaze_emit_compare): Correct diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index f64dbbf5ae3..2575fc497cd 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -124,6 +124,14 @@ extern bool avr_mem_flash_p (rtx); extern bool avr_mem_memx_p (rtx); extern bool avr_load_libgcc_p (rtx); extern bool avr_xload_libgcc_p (enum machine_mode); + +extern rtx lpm_reg_rtx; +extern rtx lpm_addr_reg_rtx; +extern rtx tmp_reg_rtx; +extern rtx zero_reg_rtx; +extern rtx all_regs_rtx[32]; +extern rtx rampz_rtx; + #endif /* RTX_CODE */ #ifdef REAL_VALUE_TYPE diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 66260876fde..968f450c4f4 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -140,30 +140,33 @@ static bool avr_rtx_costs (rtx, int, int, int, int *, bool); #define FIRST_CUM_REG 26 /* Implicit target register of LPM instruction (R0) */ -static GTY(()) rtx lpm_reg_rtx; +extern GTY(()) rtx lpm_reg_rtx; +rtx lpm_reg_rtx; /* (Implicit) address register of LPM instruction (R31:R30 = Z) */ -static GTY(()) rtx lpm_addr_reg_rtx; +extern GTY(()) rtx lpm_addr_reg_rtx; +rtx lpm_addr_reg_rtx; -/* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */ -static GTY(()) rtx tmp_reg_rtx; +/* Temporary register RTX (reg:QI TMP_REGNO) */ +extern GTY(()) rtx tmp_reg_rtx; +rtx tmp_reg_rtx; -/* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */ -static GTY(()) rtx zero_reg_rtx; +/* Zeroed register RTX (reg:QI ZERO_REGNO) */ +extern GTY(()) rtx zero_reg_rtx; +rtx zero_reg_rtx; + +/* RTXs for all general purpose registers as QImode */ +extern GTY(()) rtx all_regs_rtx[32]; +rtx all_regs_rtx[32]; /* RAMPZ special function register */ -static GTY(()) rtx rampz_rtx; +extern GTY(()) rtx rampz_rtx; +rtx rampz_rtx; /* RTX containing the strings "" and "e", respectively */ static GTY(()) rtx xstring_empty; static GTY(()) rtx xstring_e; -/* RTXs for all general purpose registers as QImode */ -static GTY(()) rtx all_regs_rtx[32]; - -/* AVR register names {"r0", "r1", ..., "r31"} */ -static const char *const avr_regnames[] = REGISTER_NAMES; - /* Preprocessor macros to define depending on MCU type. */ const char *avr_extra_arch_macro; diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 0c477943d1e..24044b3a8f9 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -5010,27 +5010,61 @@ AS1 (jmp,%1)); }") -(define_peephole - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (const_int 0))) - (set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc)))] - "jump_over_one_insn_p (insn, operands[1])" - "cpse %0,__zero_reg__") -(define_peephole +(define_peephole ; "*cpse.eq" [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "register_operand" ""))) + (compare (match_operand:QI 1 "register_operand" "r,r") + (match_operand:QI 2 "reg_or_0_operand" "r,L"))) (set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 2 "" "")) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "jump_over_one_insn_p (insn, operands[0])" + "@ + cpse %1,%2 + cpse %1,__zero_reg__") + +;; This peephole avoids code like +;; +;; TST Rn ; *cmpqi +;; BREQ .+2 ; branch +;; RJMP .Lm +;; +;; Notice that the peephole is always shorter than cmpqi + branch. +;; The reason to write it as peephole is that sequences like +;; +;; AND Rm, Rn +;; BRNE .La +;; +;; shall not be superseeded. With a respective combine pattern +;; the latter sequence would be +;; +;; AND Rm, Rn +;; CPSE Rm, __zero_reg__ +;; RJMP .La +;; +;; and thus longer and slower and not easy to be rolled back. + +(define_peephole ; "*cpse.ne" + [(set (cc0) + (compare (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "reg_or_0_operand" ""))) + (set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) (pc)))] - "jump_over_one_insn_p (insn, operands[2])" - "cpse %0,%1") + "!AVR_HAVE_JMP_CALL + || !avr_current_device->errata_skip" + { + if (operands[2] == const0_rtx) + operands[2] = zero_reg_rtx; + + return 3 == avr_jump_mode (operands[0], insn) + ? "cpse %1,%2\;jmp %0" + : "cpse %1,%2\;rjmp %0"; + }) ;;pppppppppppppppppppppppppppppppppppppppppppppppppppp ;;prologue/epilogue support instructions