avr port path: switch/case improvements
Denis Chertykov
denisc@overta.ru
Tue Nov 14 11:11:00 GMT 2000
Tue Nov 14 21:54:31 2000 Marek Michalkiewicz <marekm@linux.org.pl> & Denis Chertykov <denisc@overta.ru>
* config/avr/avr.c (avr_case_values_threshold): New.
(avr_override_options): Set it depending on options, make it large
when not optimizing to work around "unable to generate reloads".
* config/avr/avr.h (TARGET_SWITCHES): Add -mno-tablejump option.
(EXTRA_SECTION_FUNCTIONS): Make the .progmem.gcc_sw_table section
executable if not AVR_MEGA. Make sure jump tables are word-aligned.
(JUMP_TABLES_IN_TEXT_SECTION): Define as 0, not 1.
(ASM_OUTPUT_ADDR_VEC_ELT): Optimize, use "rjmp" if not AVR_MEGA.
(avr_case_values_threshold): Declare as extern int.
(CASE_VALUES_THRESHOLD): Define as avr_case_values_threshold.
* config/avr/avr.md (tablejump): Removed.
(*tablejump_rjmp): New for jump tables made from "rjmp" instructions.
(*tablejump_lib, *tablejump_enh, *tablejump): Change to expect the
index in the table, not multiplied by 2.
(casesi): Change to match the above insns. Always enable.
* config/avr/libgcc.S (__tablejump__): Rename to __tablejump2__.
Change to expect the word address of the table, multiply it by 2
here and not in the caller. Change "adiw" to faster "inc".
diff -rc3p orig/egcs/gcc/config/avr/avr.c egcs/gcc/config/avr/avr.c
*** orig/egcs/gcc/config/avr/avr.c Fri Oct 20 18:24:12 2000
--- egcs/gcc/config/avr/avr.c Sat Nov 11 14:54:21 2000
*************** static const struct mcu_type_s avr_mcu_t
*** 160,165 ****
--- 160,167 ----
{ NULL, 0 }
};
+ int avr_case_values_threshold = 30000;
+
void
avr_override_options ()
{
*************** avr_override_options ()
*** 188,193 ****
--- 190,198 ----
case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; break;
}
+
+ if (optimize && !TARGET_NO_TABLEJUMP)
+ avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
}
diff -rc3p orig/egcs/gcc/config/avr/avr.h egcs/gcc/config/avr/avr.h
*** orig/egcs/gcc/config/avr/avr.h Fri Oct 20 18:24:13 2000
--- egcs/gcc/config/avr/avr.h Sat Nov 11 15:41:43 2000
*************** extern int target_flags;
*** 51,56 ****
--- 51,57 ----
#define MASK_ORDER_1 0x00001000
#define MASK_INSN_SIZE_DUMP 0x00002000
#define MASK_ORDER_2 0x00004000
+ #define MASK_NO_TABLEJUMP 0x00008000
#define MASK_INT8 0x00010000
#define MASK_NO_INTERRUPTS 0x00020000
#define MASK_CALL_PROLOGUES 0x00040000
*************** extern int target_flags;
*** 63,68 ****
--- 64,70 ----
#define TARGET_INSN_SIZE_DUMP (target_flags & MASK_INSN_SIZE_DUMP)
#define TARGET_CALL_PROLOGUES (target_flags & MASK_CALL_PROLOGUES)
#define TARGET_TINY_STACK (target_flags & MASK_TINY_STACK)
+ #define TARGET_NO_TABLEJUMP (target_flags & MASK_NO_TABLEJUMP)
/* Dump each assembler insn's rtl into the output file.
This is for debugging the compiler itself. */
*************** extern int target_flags;
*** 102,107 ****
--- 104,111 ----
N_("Use subroutines for function prologue/epilogue") }, \
{ "tiny-stack", MASK_TINY_STACK, \
N_("Change only the low 8 bits of the stack pointer") }, \
+ { "no-tablejump", MASK_NO_TABLEJUMP, \
+ N_("Do not generate tablejump insns") }, \
{ "rtl", MASK_RTL_DUMP, NULL }, \
{ "size", MASK_INSN_SIZE_DUMP, \
N_("Output instruction sizes to the asm file") }, \
*************** progmem_section (void) \
*** 2001,2007 ****
if (in_section != in_progmem) \
{ \
fprintf (asm_out_file, \
! ".section .progmem.gcc_sw_table, \"a\", @progbits\n"); \
in_section = in_progmem; \
} \
}
--- 2005,2014 ----
if (in_section != in_progmem) \
{ \
fprintf (asm_out_file, \
! "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n", \
! AVR_MEGA ? "a" : "ax"); \
! /* Should already be aligned, this is just to be safe if it isn't. */ \
! fprintf (asm_out_file, "\t.p2align 1\n"); \
in_section = in_progmem; \
} \
}
*************** progmem_section (void) \
*** 2042,2048 ****
Do not define this macro if you put all constants in the read-only
data section. */
! #define JUMP_TABLES_IN_TEXT_SECTION 1
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used.
--- 2049,2055 ----
Do not define this macro if you put all constants in the read-only
data section. */
! #define JUMP_TABLES_IN_TEXT_SECTION 0
/* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used.
*************** sprintf (STRING, "*.%s%d", PREFIX, NUM)
*** 2706,2712 ****
not be optimal, since this macro is used only when profiling. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
! fprintf (STREAM, "\t.word pm(.L%d)\n", VALUE);
/* This macro should be provided on machines where the addresses in a
dispatch table are absolute.
--- 2713,2724 ----
not be optimal, since this macro is used only when profiling. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
! do { \
! if (AVR_MEGA) \
! fprintf (STREAM, "\t.word pm(.L%d)\n", VALUE); \
! else \
! fprintf (STREAM, "\trjmp .L%d\n", VALUE); \
! } while (0)
/* This macro should be provided on machines where the addresses in a
dispatch table are absolute.
*************** fprintf (STREAM, "\t.skip %d,0\n", n)
*** 2761,2767 ****
/* An alias for a machine mode name. This is the machine mode that
elements of a jump-table should have. */
! #define CASE_VALUES_THRESHOLD 17
/* `CASE_VALUES_THRESHOLD'
Define this to be the smallest number of different values for
which it is best to use a jump-table instead of a tree of
--- 2773,2781 ----
/* An alias for a machine mode name. This is the machine mode that
elements of a jump-table should have. */
! extern int avr_case_values_threshold;
!
! #define CASE_VALUES_THRESHOLD avr_case_values_threshold
/* `CASE_VALUES_THRESHOLD'
Define this to be the smallest number of different values for
which it is best to use a jump-table instead of a tree of
diff -rc3p orig/egcs/gcc/config/avr/avr.md egcs/gcc/config/avr/avr.md
*** orig/egcs/gcc/config/avr/avr.md Fri Oct 20 18:24:13 2000
--- egcs/gcc/config/avr/avr.md Sat Nov 11 15:53:20 2000
***************
*** 1852,1892 ****
(define_expand "tablejump"
[(parallel [(set (pc) (match_operand:HI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))])]
! "optimize"
"")
;; Not a prologue, but similar idea - move the common piece of code to libgcc.
(define_insn "*tablejump_lib"
[(set (pc) (mem:HI (plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))]
! "TARGET_CALL_PROLOGUES"
! "*{
! output_asm_insn (AS2 (subi,r30,lo8(-(%2))) CR_TAB
! AS2 (sbci,r31,hi8(-(%2))), operands);
! return (AVR_MEGA
! ? AS1 (jmp,__tablejump__)
! : AS1 (rjmp,__tablejump__));
! }"
! [(set_attr "cc" "clobber")
! (set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
! (const_int 3)
! (const_int 4)))])
!
(define_insn "*tablejump_enh"
[(set (pc) (mem:HI
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))]
! "AVR_ENHANCED"
! "subi r30,lo8(-(%2))
! sbci r31,hi8(-(%2))
lpm __tmp_reg__,Z+
lpm r31,Z
mov r30,__tmp_reg__
ijmp"
! [(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "*tablejump"
--- 1852,1904 ----
(define_expand "tablejump"
[(parallel [(set (pc) (match_operand:HI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))])]
! "0 && optimize"
"")
+ ;; Note: the (mem:HI (...)) memory references here are special - actually
+ ;; the data is read from a word address in program memory (r31:r30 is the
+ ;; index in the table, not multiplied by 2 - see the "casesi" pattern).
+
+ ;; Table made from "rjmp" instructions for <=8K devices.
+ (define_insn "*tablejump_rjmp"
+ [(set (pc) (mem:HI
+ (plus:HI (match_operand:HI 0 "register_operand" "=&z")
+ (label_ref (match_operand 2 "" "")))))
+ (use (label_ref (match_operand 1 "" "")))]
+ "!AVR_MEGA"
+ "subi r30,pm_lo8(-(%2))
+ sbci r31,pm_hi8(-(%2))
+ ijmp"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
;; Not a prologue, but similar idea - move the common piece of code to libgcc.
(define_insn "*tablejump_lib"
[(set (pc) (mem:HI (plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))]
! "AVR_MEGA && TARGET_CALL_PROLOGUES"
! "subi r30,pm_lo8(-(%2))
! sbci r31,pm_hi8(-(%2))
! jmp __tablejump2__"
! [(set_attr "length" "4")
! (set_attr "cc" "clobber")])
(define_insn "*tablejump_enh"
[(set (pc) (mem:HI
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))]
! "AVR_MEGA && AVR_ENHANCED"
! "subi r30,pm_lo8(-(%2))
! sbci r31,pm_hi8(-(%2))
! lsl r30
! rol r31
lpm __tmp_reg__,Z+
lpm r31,Z
mov r30,__tmp_reg__
ijmp"
! [(set_attr "length" "8")
(set_attr "cc" "clobber")])
(define_insn "*tablejump"
***************
*** 1894,1909 ****
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))]
! ""
! "subi r30,lo8(-(%2))
! sbci r31,hi8(-(%2))
lpm
push r0
- adiw r30,1
lpm
push r0
ret"
! [(set_attr "length" "8")
(set_attr "cc" "clobber")])
(define_expand "casesi"
--- 1906,1923 ----
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))]
! "AVR_MEGA"
! "subi r30,pm_lo8(-(%2))
! sbci r31,pm_hi8(-(%2))
! lsl r30
! rol r31
lpm
+ inc r30
push r0
lpm
push r0
ret"
! [(set_attr "length" "10")
(set_attr "cc" "clobber")])
(define_expand "casesi"
***************
*** 1920,1928 ****
(const_int 0))
(label_ref (match_operand 4 "" ""))
(pc)))
! (set (match_dup 6)
! (plus:HI (match_dup 6)
! (match_dup 6)))
;; (set (match_dup 6)
;; (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
--- 1934,1942 ----
(const_int 0))
(label_ref (match_operand 4 "" ""))
(pc)))
! ;; (set (match_dup 6)
! ;; (plus:HI (match_dup 6)
! ;; (match_dup 6)))
;; (set (match_dup 6)
;; (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
***************
*** 1930,1936 ****
(plus:HI (match_dup 6)
(label_ref (match_operand:HI 3 "" "")))))
(use (label_ref (match_dup 3)))])]
! "!optimize"
"
{
operands[6] = gen_reg_rtx (HImode);
--- 1944,1950 ----
(plus:HI (match_dup 6)
(label_ref (match_operand:HI 3 "" "")))))
(use (label_ref (match_dup 3)))])]
! ""
"
{
operands[6] = gen_reg_rtx (HImode);
diff -rc3p orig/egcs/gcc/config/avr/libgcc.S egcs/gcc/config/avr/libgcc.S
*** orig/egcs/gcc/config/avr/libgcc.S Sat Sep 2 12:48:46 2000
--- egcs/gcc/config/avr/libgcc.S Sat Nov 11 12:46:28 2000
*************** _cleanup:
*** 691,699 ****
#endif /* defined (L_cleanup) */
#ifdef L_tablejump
! .global __tablejump__
! .func __tablejump__
! __tablejump__:
#if defined (__AVR_ENHANCED__)
lpm __tmp_reg__, Z+
lpm r31, Z
--- 691,701 ----
#endif /* defined (L_cleanup) */
#ifdef L_tablejump
! .global __tablejump2__
! .func __tablejump2__
! __tablejump2__:
! lsl r30
! rol r31
#if defined (__AVR_ENHANCED__)
lpm __tmp_reg__, Z+
lpm r31, Z
*************** __tablejump__:
*** 702,708 ****
#else
lpm
push r0
! adiw r30, 1
lpm
push r0
ret
--- 704,710 ----
#else
lpm
push r0
! inc r30 ; table is word aligned, no carry to high byte
lpm
push r0
ret
More information about the Gcc-patches
mailing list