From: Nick Clifton Date: Wed, 16 Mar 2011 11:47:59 +0000 (+0000) Subject: rx.h (JUMP_ALIGN): Define. X-Git-Tag: releases/gcc-4.5.3~148 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d9de4159daf9586b2a8f666502641227358284b;p=thirdparty%2Fgcc.git rx.h (JUMP_ALIGN): Define. * config/rx/rx.h (JUMP_ALIGN): Define. (JUMP_ALIGN_MAX_SKIP, LABEL_ALIGN_AFTER_BARRIER, LOOP_ALIGN, (LABEL_ALIGN, LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP, (LOOP_ALIGN_MAX_SKIP, LABEL_ALIGN_MAX_SKIP): Define. * config/rx/rx-protos.h (rx_align_for_label): Prototype. (rx_max_skip_for_label): Prototype. * config/rx/rx.md (abssi3): Use CC_ZSmode. (andis3): Fix timings. (peephole): Add peephole to combine zero- and sign- extending loads with arithmetic instructions. (bset): Fix timing. (bclr): Fix timing. * config/rx/rx.c (rx_is_legitimate_address): Add checks for QImode and HImode reg+int address. (rx_print_operand): Add support for %R. Fix generation of .B and .W addressing modes. (rx_align_for_label): New function. (rx_max_skip_for_label): New function. From-SVN: r171044 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7380093e91bf..ca9398cdfefb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2011-03-16 Nick Clifton + + * config/rx/rx.h (JUMP_ALIGN): Define. + (JUMP_ALIGN_MAX_SKIP, LABEL_ALIGN_AFTER_BARRIER, LOOP_ALIGN, + (LABEL_ALIGN, LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP, + (LOOP_ALIGN_MAX_SKIP, LABEL_ALIGN_MAX_SKIP): Define. + * config/rx/rx-protos.h (rx_align_for_label): Prototype. + (rx_max_skip_for_label): Prototype. + * config/rx/rx.md (abssi3): Use CC_ZSmode. + (andis3): Fix timings. + (peephole): Add peephole to combine zero- and sign- extending + loads with arithmetic instructions. + (bset): Fix timing. + (bclr): Fix timing. + * config/rx/rx.c (rx_is_legitimate_address): Add checks for QImode + and HImode reg+int address. + (rx_print_operand): Add support for %R. Fix generation of .B and + .W addressing modes. + (rx_align_for_label): New function. + (rx_max_skip_for_label): New function. + 2011-03-10 Jason Merrill PR c++/48029 diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h index 2d291c1ad958..e2b05175fe53 100644 --- a/gcc/config/rx/rx-protos.h +++ b/gcc/config/rx/rx-protos.h @@ -31,6 +31,7 @@ extern int rx_initial_elimination_offset (int, int); extern void rx_set_optimization_options (void); #ifdef RTX_CODE +extern int rx_align_for_label (rtx); extern bool rx_compare_redundant (rtx); extern void rx_emit_stack_popm (rtx *, bool); extern void rx_emit_stack_pushm (rtx *); @@ -41,6 +42,7 @@ extern bool rx_is_legitimate_constant (rtx); extern bool rx_is_mode_dependent_addr (rtx); extern bool rx_is_restricted_memory_address (rtx, Mmode); extern bool rx_match_ccmode (rtx, Mmode); +extern int rx_max_skip_for_label (rtx); extern void rx_notice_update_cc (rtx body, rtx insn); extern void rx_print_operand (FILE *, rtx, int); extern void rx_print_operand_address (FILE *, rtx); diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index d1d17f9c6565..6b693c8ed459 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -80,7 +80,9 @@ rx_is_legitimate_address (Mmode mode, rtx x, bool strict ATTRIBUTE_UNUSED) /* Register Indirect. */ return true; - if (GET_MODE_SIZE (mode) == 4 + if ((GET_MODE_SIZE (mode) == 4 + || GET_MODE_SIZE (mode) == 2 + || GET_MODE_SIZE (mode) == 1) && (GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)) /* Pre-decrement Register Indirect or Post-increment Register Indirect. */ @@ -182,7 +184,10 @@ rx_is_restricted_memory_address (rtx mem, enum machine_mode mode) base = XEXP (mem, 0); index = XEXP (mem, 1); - return RX_REG_P (base) && CONST_INT_P (index); + if (! RX_REG_P (base) || ! CONST_INT_P (index)) + return false; + + return IN_RANGE (INTVAL (index), 0, (0x10000 * GET_MODE_SIZE (mode)) - 1); case SYMBOL_REF: /* Can happen when small data is being supported. @@ -447,11 +452,14 @@ flags_from_code (enum rtx_code code) %L Print low part of a DImode register, integer or address. %N Print the negation of the immediate value. %Q If the operand is a MEM, then correctly generate - register indirect or register relative addressing. */ + register indirect or register relative addressing. + %R Like %Q but for zero-extending loads. */ void rx_print_operand (FILE * file, rtx op, int letter) { + bool unsigned_load = false; + switch (letter) { case 'A': @@ -615,10 +623,15 @@ rx_print_operand (FILE * file, rtx op, int letter) rx_print_integer (file, - INTVAL (op)); break; + case 'R': + gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4); + unsigned_load = true; + /* Fall through. */ case 'Q': if (MEM_P (op)) { HOST_WIDE_INT offset; + rtx mem = op; op = XEXP (op, 0); @@ -653,22 +666,24 @@ rx_print_operand (FILE * file, rtx op, int letter) rx_print_operand (file, op, 0); fprintf (file, "]."); - switch (GET_MODE_SIZE (GET_MODE (op))) + switch (GET_MODE_SIZE (GET_MODE (mem))) { case 1: - gcc_assert (offset < 65535 * 1); - fprintf (file, "B"); + gcc_assert (offset <= 65535 * 1); + fprintf (file, unsigned_load ? "UB" : "B"); break; case 2: gcc_assert (offset % 2 == 0); - gcc_assert (offset < 65535 * 2); - fprintf (file, "W"); + gcc_assert (offset <= 65535 * 2); + fprintf (file, unsigned_load ? "UW" : "W"); break; - default: + case 4: gcc_assert (offset % 4 == 0); - gcc_assert (offset < 65535 * 4); + gcc_assert (offset <= 65535 * 4); fprintf (file, "L"); break; + default: + gcc_unreachable (); } break; } @@ -2656,6 +2671,36 @@ rx_match_ccmode (rtx insn, enum machine_mode cc_mode) return true; } +int +rx_align_for_label (rtx lab ATTRIBUTE_UNUSED) +{ + return optimize_size ? 1 : 3; +} + +int +rx_max_skip_for_label (rtx lab) +{ + int opsize; + rtx op; + + if (lab == NULL_RTX) + return 0; + op = lab; + do + { + op = next_nonnote_insn (op); + } + while (op && (LABEL_P (op) + || (INSN_P (op) && GET_CODE (PATTERN (op)) == USE))); + if (!op) + return 0; + + opsize = get_attr_length (op); + if (opsize >= 0 && opsize < 8) + return opsize - 1; + return 0; +} + #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE rx_function_value diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index 85e911916cf3..a424c89f1444 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -663,3 +663,28 @@ typedef unsigned int CUMULATIVE_ARGS; #define SELECT_CC_MODE(OP,X,Y) rx_select_cc_mode ((OP), (X), (Y)) +#define JUMP_ALIGN(x) rx_align_for_label (x) +#define JUMP_ALIGN_MAX_SKIP rx_max_skip_for_label (label) +#define LABEL_ALIGN_AFTER_BARRIER(x) rx_align_for_label (x) +#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP rx_max_skip_for_label (label) +#define LOOP_ALIGN(x) rx_align_for_label (x) +#define LOOP_ALIGN_MAX_SKIP rx_max_skip_for_label (label) +#define LABEL_ALIGN(x) rx_align_for_label (x) +#define LABEL_ALIGN_MAX_SKIP rx_max_skip_for_label (NULL_RTX) + +#define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM, LOG, MAX_SKIP) \ + do \ + { \ + if ((LOG) == 0 || (MAX_SKIP) == 0) \ + break; \ + if (TARGET_AS100_SYNTAX) \ + { \ + if ((LOG) >= 2) \ + fprintf (STREAM, "\t.ALIGN 4\t; %d alignment actually requested\n", 1 << (LOG)); \ + else \ + fprintf (STREAM, "\t.ALIGN 2\n"); \ + } \ + else \ + fprintf (STREAM, "\t.balign %d,3,%d\n", 1 << (LOG), (MAX_SKIP)); \ + } \ + while (0) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index c33fa2f0b772..d6720aa5e1d7 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -798,7 +798,10 @@ (set (reg CC_REG) (compare (abs:SI (match_dup 1)) (const_int 0)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSOmode)" + ;; Note - although the ABS instruction does set the O bit in the processor + ;; status word, it does not do so in a way that is comparable with the CMP + ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode. + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ abs\t%0 abs\t%1, %0" @@ -1005,7 +1008,7 @@ and\t%1, %0 and\t%2, %1, %0 and\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,11,11,11,33,33") + [(set_attr "timings" "11,11,11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,2,5,5")] ) @@ -1027,7 +1030,7 @@ and\t%1, %0 and\t%2, %1, %0 and\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,11,11,11,33,33") + [(set_attr "timings" "11,11,11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,2,5,5")] ) @@ -1543,6 +1546,139 @@ (set_attr "length" "3,4,5,6,7,6")] ) +;; A set of peepholes to catch extending loads followed by arithmetic operations. +;; We use iterators where possible to reduce the amount of typing and hence the +;; possibilities for typos. + +(define_code_iterator extend_types [(zero_extend "") (sign_extend "")]) +(define_code_attr letter [(zero_extend "R") (sign_extend "Q")]) + +(define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")]) +(define_code_iterator memex_noncomm [(div "") (udiv "") (minus "")]) +(define_code_iterator memex_nocc [(smax "") (smin "") (mult "")]) + +(define_code_attr op [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")]) + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand"))) + (parallel [(set (match_operand:SI 2 "register_operand") + (memex_commutative:SI (match_dup 0) + (match_dup 2))) + (clobber (reg:CC CC_REG))])] + "peep2_regno_dead_p (2, REGNO (operands[0]))" + [(parallel [(set:SI (match_dup 2) + (memex_commutative:SI (match_dup 2) + (extend_types:SI (match_dup 1)))) + (clobber (reg:CC CC_REG))])] +) + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand"))) + (parallel [(set (match_operand:SI 2 "register_operand") + (memex_commutative:SI (match_dup 2) + (match_dup 0))) + (clobber (reg:CC CC_REG))])] + "peep2_regno_dead_p (2, REGNO (operands[0]))" + [(parallel [(set:SI (match_dup 2) + (memex_commutative:SI (match_dup 2) + (extend_types:SI (match_dup 1)))) + (clobber (reg:CC CC_REG))])] +) + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand"))) + (parallel [(set (match_operand:SI 2 "register_operand") + (memex_noncomm:SI (match_dup 2) + (match_dup 0))) + (clobber (reg:CC CC_REG))])] + "peep2_regno_dead_p (2, REGNO (operands[0]))" + [(parallel [(set:SI (match_dup 2) + (memex_noncomm:SI (match_dup 2) + (extend_types:SI (match_dup 1)))) + (clobber (reg:CC CC_REG))])] +) + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand"))) + (set (match_operand:SI 2 "register_operand") + (memex_nocc:SI (match_dup 0) + (match_dup 2)))] + "peep2_regno_dead_p (2, REGNO (operands[0]))" + [(set:SI (match_dup 2) + (memex_nocc:SI (match_dup 2) + (extend_types:SI (match_dup 1))))] +) + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand"))) + (set (match_operand:SI 2 "register_operand") + (memex_nocc:SI (match_dup 2) + (match_dup 0)))] + "peep2_regno_dead_p (2, REGNO (operands[0]))" + [(set:SI (match_dup 2) + (memex_nocc:SI (match_dup 2) + (extend_types:SI (match_dup 1))))] +) + +(define_insn "*si3_" + [(set (match_operand:SI 0 "register_operand" "=r") + (memex_commutative:SI (match_operand:SI 1 "register_operand" "%0") + (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q")))) + (clobber (reg:CC CC_REG))] + "" + "\t%2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5")] ;; Worst case sceanario. FIXME: If we defined separate patterns +) ;; rather than using iterators we could specify exact sizes. + +(define_insn "*si3_" + [(set (match_operand:SI 0 "register_operand" "=r") + (memex_noncomm:SI (match_operand:SI 1 "register_operand" "0") + (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q")))) + (clobber (reg:CC CC_REG))] + "" + "\t%2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5")] ;; Worst case sceanario. FIXME: If we defined separate patterns +) ;; rather than using iterators we could specify exact sizes. + +(define_insn "*si3_" + [(set (match_operand:SI 0 "register_operand" "=r") + (memex_nocc:SI (match_operand:SI 1 "register_operand" "%0") + (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))] + "" + "\t%2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5")] ;; Worst case sceanario. FIXME: If we defined separate patterns +) ;; rather than using iterators we could specify exact sizes. + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand"))) + (set (reg:CC CC_REG) + (compare:CC (match_operand:SI 2 "register_operand") + (match_dup 0)))] + "peep2_regno_dead_p (2, REGNO (operands[0]))" + [(set (reg:CC CC_REG) + (compare:CC (match_dup 2) + (extend_types:SI (match_dup 1))))] +) + +(define_insn "*comparesi3_" + [(set (reg:CC CC_REG) + (compare:CC (match_operand:SI 0 "register_operand" "=r") + (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))] + "" + "cmp\t%1, %0" + [(set_attr "timings" "33") + (set_attr "length" "5")] ;; Worst case sceanario. FIXME: If we defined separate patterns +) ;; rather than using iterators we could specify exact sizes. + ;; Floating Point Instructions (define_insn "addsf3" @@ -1641,7 +1777,7 @@ "" "bset\t%1, %0.B" [(set_attr "length" "3") - (set_attr "timings" "34")] + (set_attr "timings" "33")] ) (define_insn "*bitinvert" @@ -1687,7 +1823,7 @@ "" "bclr\t%1, %0.B" [(set_attr "length" "3") - (set_attr "timings" "34")] + (set_attr "timings" "33")] ) (define_insn "*insv_imm"