OSDN Git Service

* config/picochip/picochip.c (picochip_legitimize_address): Define.
authorhariharans <hariharans@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Apr 2010 09:40:21 +0000 (09:40 +0000)
committerhariharans <hariharans@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Apr 2010 09:40:21 +0000 (09:40 +0000)
        Use this function to do machine-specific conversion.
        (picochip_legitimize_reload_address): Likewise.
        (picochip_legitimate_address_p): Check valid base register only if
        strict.
        (picochip_check_conditional_copy): Check for modw only if opnd is
        register.
        * config/picochip/picochip.h (LEGITIMIZE_RELOAD_ADDRESS): Use this
        to call the function in c.
        * config/picochip/picochip-protos.h
        (picochip_legitimize_reload_address): Define.
        * config/picochip/picochip.md (supported_compare1): Define.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158927 138bc75d-0d04-0410-961f-82ee72b054a4

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

index dc50ee4..1a428b9 100644 (file)
@@ -1,3 +1,18 @@
+2010-04-30  Hariharan Sandanagobalane  <hariharan@picochip.com>
+
+       * config/picochip/picochip.c (picochip_legitimize_address): Define.
+       Use this function to do machine-specific conversion.
+       (picochip_legitimize_reload_address): Likewise.
+       (picochip_legitimate_address_p): Check valid base register only if
+       strict.
+       (picochip_check_conditional_copy): Check for modw only if opnd is
+       register.
+       * config/picochip/picochip.h (LEGITIMIZE_RELOAD_ADDRESS): Use this
+       to call the function in c.
+       * config/picochip/picochip-protos.h
+       (picochip_legitimize_reload_address): Define.
+       * config/picochip/picochip.md (supported_compare1): Define.
+
 2010-04-30  Jan Hubicka  <jh@suse.cz>
 
        * cgraph.h (cgraph_local_info): Remove for_functions_valid.
index de68c81..875bb1d 100644 (file)
@@ -99,6 +99,10 @@ extern rtx picochip_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED,
 
 #endif /* RTX_CODE inside TREE_CODE */
 
+extern int picochip_legitimize_reload_address (rtx *x, enum machine_mode mode,
+                                        int opnum, int type, int ind_levels);
+
+
 void picochip_output_ascii (FILE * file, const char *str, int length);
 
 extern int picochip_hard_regno_mode_ok (int regno, enum machine_mode mode);
index 03df3fb..0d6db58 100644 (file)
@@ -96,6 +96,10 @@ bool picochip_rtx_costs (rtx x, int code, int outer_code, int* total, bool speed
 bool picochip_return_in_memory(const_tree type,
                               const_tree fntype ATTRIBUTE_UNUSED);
 bool picochip_legitimate_address_p (enum machine_mode, rtx, bool);
+rtx picochip_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+                             enum machine_mode mode);
+int picochip_legitimize_reload_address (rtx *x, enum machine_mode mode,
+                                        int opnum, int type, int ind_levels);
 
 rtx picochip_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED);
 rtx picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
@@ -279,6 +283,9 @@ static char picochip_get_vliw_alu_id (void);
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P picochip_legitimate_address_p
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS picochip_legitimize_address
+
 /* Loading and storing QImode values to and from memory
    usually requires a scratch register. */
 #undef TARGET_SECONDARY_RELOAD
@@ -1268,9 +1275,13 @@ picochip_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
       {
        rtx base = XEXP (x, 0);
        rtx offset = XEXP (x, 1);
+        if (strict && !REGNO_OK_FOR_BASE_P (REGNO(base)))
+        {
+          valid = 0;
+          break;
+        }
 
        valid = (REG == GET_CODE (base) &&
-                REGNO_OK_FOR_BASE_P (REGNO(base)) &&
                 picochip_legitimate_address_register (base, strict) &&
                 CONST_INT == GET_CODE (offset) &&
                 picochip_const_ok_for_base (mode, REGNO (base),
@@ -1311,6 +1322,144 @@ picochip_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 
 }
 
+/* For all memory operations, picochip allows a uconst4 offset value. It
+   is hence beneficial to turn an
+   addr = <reg + long_const>
+   ld/st addr
+
+   into
+
+   X = reg + long_const & FFF0
+   diff = long_const - (long_const & FFF0)
+   ld/st <X + diff>
+
+   X can be reused in subsequent memory operations.
+   */
+rtx
+picochip_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+                             enum machine_mode mode)
+{
+  if (!optimize)
+    return x;
+
+  unsigned mask_val;
+  // Depending on mode, the offsets allowed are either 16/32/64.
+  switch (mode)
+    {
+      case QImode:
+        mask_val = 0xFFF0;
+        break;
+      case HImode:
+        mask_val = 0xFFE0;
+        break;
+      case SImode:
+        mask_val = 0xFFC0;
+        break;
+      default:
+        return x;
+    }
+
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == REG
+      && GET_CODE (XEXP (x, 1)) == CONST_INT)
+    {
+      int offset = INTVAL (XEXP (x, 1));
+      // Ignore cases with negative offsets.
+      if (offset < 0)
+        return x;
+      int high_val = offset & mask_val;
+      int low_val = offset - high_val;
+      if (high_val != 0)
+        {
+          rtx temp_reg = force_reg (Pmode, gen_rtx_PLUS (Pmode, XEXP (x, 0), GEN_INT(high_val)));
+          x = gen_rtx_PLUS (Pmode, temp_reg, GEN_INT(low_val));
+          return x;
+        }
+    }
+  return x;
+}
+
+/* For all memory operations, picochip allows a uconst4 offset value. It
+   is hence beneficial to turn an
+   addr = <reg + long_const>
+   ld/st addr
+
+   into
+
+   X = reg + long_const & FFF0
+   diff = long_const - (long_const & FFF0)
+   ld/st <X + diff>
+
+   X can be reused in subsequent memory operations.
+   */
+int
+picochip_legitimize_reload_address (rtx *x,
+                                    enum machine_mode mode,
+                                    int opnum, int type,
+                                    int ind_levels ATTRIBUTE_UNUSED)
+{
+  if (picochip_symbol_offset(*x))
+    {
+      *x = gen_rtx_CONST(mode, *x);
+      return 0;
+    }
+  if (!optimize)
+    return 0;
+
+  /* We should recognise addresses that we created.*/
+  if (GET_CODE (*x) == PLUS
+      && GET_CODE (XEXP (*x, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (*x, 0), 0)) == REG
+      && GET_CODE (XEXP (XEXP (*x, 0), 1)) == CONST_INT
+      && GET_CODE (XEXP (*x, 1)) == CONST_INT)
+    {
+      push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
+                   BASE_REG_CLASS, GET_MODE (*x), VOIDmode, 0, 0,
+                   opnum, (enum reload_type)type);
+      return 1;
+    }
+
+  unsigned mask_val;
+  // Depending on mode, the offsets allowed are either 16/32/64.
+  switch (mode)
+    {
+      case QImode:
+        mask_val = 0xFFF0;
+        break;
+      case HImode:
+        mask_val = 0xFFE0;
+        break;
+      case SImode:
+        mask_val = 0xFFC0;
+        break;
+      default:
+        return 0;
+    }
+
+  if (GET_CODE (*x) == PLUS
+      && GET_CODE (XEXP (*x, 0)) == REG
+      && GET_CODE (XEXP (*x, 1)) == CONST_INT)
+    {
+      int offset = INTVAL (XEXP (*x, 1));
+      // Ignore cases with negative offsets.
+      if (offset < 0)
+        return 0;
+      int high_val = offset & mask_val;
+      int low_val = offset - high_val;
+      if (high_val != 0)
+        {
+          rtx temp_reg = gen_rtx_PLUS (Pmode, XEXP (*x, 0), GEN_INT(high_val));
+          *x = gen_rtx_PLUS (Pmode, temp_reg, GEN_INT(low_val));
+          push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
+                       BASE_REG_CLASS, GET_MODE (*x), VOIDmode, 0, 0,
+                       opnum, (enum reload_type)type);
+          return 1;
+        }
+    }
+
+  return 0;
+}
+
 /* Detect an rtx which matches (plus (symbol_ref) (const_int)). */
 int
 picochip_symbol_offset (rtx operand)
@@ -4395,11 +4544,11 @@ picochip_check_conditional_copy (rtx * operands)
      handled using logical operations (e.g., SIreg != 0 when low ||
      high). Need to find test cases to provoke this though (fixunssfdi
      in libgcc does, but is complicated). */
-  if (GET_MODE (branch_op_0) != HImode ||
-       !(register_operand (branch_op_0, GET_MODE (branch_op_0))))
+  if (register_operand(branch_op_0, GET_MODE(branch_op_0)) &&
+      GET_MODE(branch_op_0) != HImode)
     return 0;
-  if (GET_MODE (branch_op_1) != HImode ||
-       !(picochip_comparison_operand (branch_op_1, GET_MODE (branch_op_1))))
+  if (register_operand(branch_op_1, GET_MODE(branch_op_1)) &&
+      GET_MODE(branch_op_1) != HImode)
     return 0;
 
   return 1;
index bf2ecc0..7269fa0 100644 (file)
@@ -495,7 +495,10 @@ extern const enum reg_class picochip_regno_reg_class[FIRST_PSEUDO_REGISTER];
    correct code is generated. */
 
 #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)         \
-if (picochip_symbol_offset(X)) { X = gen_rtx_CONST(MODE, X); }
+do {                                                                         \
+  if (picochip_legitimize_reload_address(&X,MODE,OPNUM,TYPE,IND_LEVELS))     \
+    goto WIN;                                                                \
+  } while(0);                                                                \
 
 /* Nonzero if the constant rtx X is a legitimate general operand.  X
    satisfies CONSTANT_P.  */
index 02f0f14..6210350 100644 (file)
    (set_attr "length" "2,2,4")
    ])
 
+;; This pattern was added to match the previous pattern. When doing if-convert
+;; the pattern generated using movhicc does not have a eq:CC but only a eq for
+;; operator. If this pattern were not to be there, Gcc decides not to use
+;; movhicc at all. Whereas, in Gcc 4.4, it seems to be cleverer.
+(define_insn "*supported_compare1"
+  [(set (reg:CC CC_REGNUM)
+        (match_operator 0 "picochip_supported_comparison_operator"
+                        [(match_operand:HI 1 "register_operand" "r,r,r")
+                         (match_operand:HI 2 "picochip_comparison_operand" "r,J,i")]))]
+  ""
+  "* return picochip_output_compare(operands);"
+  [; Must be picoAlu because it sets the condition flags.
+   (set_attr "type" "picoAlu,picoAlu,picoAlu")
+   (set_attr "longConstant" "false,false,true")
+   (set_attr "length" "2,2,4")
+   ])
+
 (define_insn "*compare"
   [(set (reg:CC CC_REGNUM)
         (match_operator:CC 0 "comparison_operator"