]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rx.h (JUMP_ALIGN): Define.
authorNick Clifton <nickc@redhat.com>
Wed, 16 Mar 2011 11:47:59 +0000 (11:47 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Wed, 16 Mar 2011 11:47:59 +0000 (11:47 +0000)
* 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

gcc/ChangeLog
gcc/config/rx/rx-protos.h
gcc/config/rx/rx.c
gcc/config/rx/rx.h
gcc/config/rx/rx.md

index 7380093e91bfa9ab539c0aa45ea0658b0a1b6367..ca9398cdfefbfb28eec01e400f829ce277c1bff1 100644 (file)
@@ -1,3 +1,24 @@
+2011-03-16  Nick Clifton  <nickc@redhat.com>
+
+       * 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  <jason@redhat.com>
 
        PR c++/48029
index 2d291c1ad958296272a71ab7835b145ac0ed0d10..e2b05175fe534801030c01a71fa86292347c4f65 100644 (file)
@@ -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);
index d1d17f9c65651bb0e3de7e17492b32f928fd3f76..6b693c8ed4595c99bc8fddfbfb1962f02047ebbe 100644 (file)
@@ -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;
 }
 \f
+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;
+}
+\f
 #undef  TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE          rx_function_value
 
index 85e911916cf3fb0e52559bea130a5b6620bbf128..a424c89f144442f549c9ca19d58592f32a3f05bd 100644 (file)
@@ -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)
index c33fa2f0b772cc329ed8632b418d4017b670c048..d6720aa5e1d78348c4e432f7e4fa6d449fa9f218 100644 (file)
    (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"
   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")]
 )
 
   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")]
 )
 
    (set_attr "length" "3,4,5,6,7,6")]
 )
 \f
+;; 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 "*<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
+  [(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))]
+  ""
+  "<memex_commutative:op>\t%<extend_types:letter>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 "*<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
+  [(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))]
+  ""
+  "<memex_noncomm:op>\t%<extend_types:letter>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 "*<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
+  [(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"))))]
+  ""
+  "<memex_nocc:op>\t%<extend_types:letter>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_<extend_types:code><small_int_modes:mode>"
+  [(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%<extend_types:letter>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.
+\f
 ;; Floating Point Instructions
 
 (define_insn "addsf3"
   ""
   "bset\t%1, %0.B"
   [(set_attr "length" "3")
-   (set_attr "timings" "34")]
+   (set_attr "timings" "33")]
 )
 
 (define_insn "*bitinvert"
   ""
   "bclr\t%1, %0.B"
   [(set_attr "length" "3")
-   (set_attr "timings" "34")]
+   (set_attr "timings" "33")]
 )
 
 (define_insn "*insv_imm"