m68k.c (post_inc_operand,pre_dec_operand): New.
authorRoman Zippel <zippel@linux-m68k.org>
Fri, 6 Aug 2004 07:14:56 +0000 (07:14 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 6 Aug 2004 07:14:56 +0000 (00:14 -0700)
        * config/m68k/m68k.c (post_inc_operand,pre_dec_operand): New.
        * config/m68k/m68k.h (PREDICATE_CODES): add post_inc_operand,
        pre_dec_operand.
        * config/m68k/m68k.md (zero_extend*2): delay the splitting of the
        pattern until reload is finished to allow better code generation
        and split them completely into separate instrunctions.
        (*andsi3_split): New pattern.

From-SVN: r85631

gcc/ChangeLog
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md

index d7d4abd4ff730ad9887105ff2ff2c1bbedd2b4cd..b35bb6a8367a8c2de48b28b13ba85ac6d73c5f47 100644 (file)
@@ -1,3 +1,13 @@
+2004-08-06  Roman Zippel  <zippel@linux-m68k.org>
+        * config/m68k/m68k.c (post_inc_operand,pre_dec_operand): New.
+        * config/m68k/m68k.h (PREDICATE_CODES): add post_inc_operand,
+        pre_dec_operand.
+        * config/m68k/m68k.md (zero_extend*2): delay the splitting of the
+        pattern until reload is finished to allow better code generation
+        and split them completely into separate instrunctions.
+        (*andsi3_split): New pattern.
+
 2004-08-05  Mark Mitchell  <mark@codesourcery.com>
 
        * tree.c (handle_dll_attribute): Move here from i383/winnt.c.
index 4f2b71e06f9dc37507089b04e7c931dfb7e0b8fe..e44f490c5a6c4332d7ab409fdaf4afc843d98c25 100644 (file)
@@ -3185,6 +3185,18 @@ memory_src_operand (rtx op, enum machine_mode mode)
   return memory_operand (op, mode);
 }
 
+int
+post_inc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC;
+}
+
+int
+pre_dec_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return MEM_P (op) && GET_CODE (XEXP (op, 0)) == PRE_DEC;
+}
+
 /* Predicate that accepts only a pc-relative address.  This is needed
    because pc-relative addresses don't satisfy the predicate
    "general_src_operand".  */
index 14a8b9bb8ae7bb8fb0bc6a67b4f0d35bafe87f9a..6af7116f78b37218e09ddc33da314dabea913d46 100644 (file)
@@ -1271,4 +1271,6 @@ extern int m68k_last_compare_had_fp_operands;
   {"valid_dbcc_comparison_p", {EQ, NE, GTU, LTU, GEU, LEU,             \
                               GT, LT, GE, LE}},                        \
   {"extend_operator", {SIGN_EXTEND, ZERO_EXTEND}},                     \
-  {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},
+  {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                        \
+  {"post_inc_operand", {MEM}},                                         \
+  {"pre_dec_operand", {MEM}},
index cc69553683c138b173ad1999cc49b9191c9e713f..57ddd4a78f32aeb24984cf4c8cb94df37757476f 100644 (file)
 \f
 ;; zero extension instructions
 
-(define_insn "zero_extendqidi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
-       (zero_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
+;; two special patterns to match various post_inc/pre_dec patterns
+(define_insn_and_split "*zero_extend_inc"
+  [(set (match_operand 0 "post_inc_operand" "")
+       (zero_extend (match_operand 1 "register_operand" "")))]
+  "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT &&
+   GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT &&
+   GET_MODE_SIZE (GET_MODE (operands[0])) == GET_MODE_SIZE (GET_MODE (operands[1])) * 2"
+  "#"
+  ""
+  [(set (match_dup 0)
+       (const_int 0))
+   (set (match_dup 0)
+       (match_dup 1))]
+{
+  operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
+})
+
+(define_insn_and_split "*zero_extend_dec"
+  [(set (match_operand 0 "pre_dec_operand" "")
+       (zero_extend (match_operand 1 "register_operand" "")))]
+  "(GET_MODE (operands[0]) != HImode || XEXP (XEXP (operands[0], 0), 0) != stack_pointer_rtx) &&
+   GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT &&
+   GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT &&
+   GET_MODE_SIZE (GET_MODE (operands[0])) == GET_MODE_SIZE (GET_MODE (operands[1])) * 2"
+  "#"
   ""
+  [(set (match_dup 0)
+       (match_dup 1))
+   (set (match_dup 0)
+       (const_int 0))]
 {
-  CC_STATUS_INIT;
-  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  return "moveq #0,%0\;moveq #0,%2\;move%.b %1,%2";
+  operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
 })
 
-(define_insn "zero_extendhidi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
-       (zero_extend:DI (match_operand:HI 1 "general_operand" "rm")))]
+(define_insn_and_split "zero_extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI (match_operand:QI 1 "nonimmediate_src_operand" "")))]
+  ""
+  "#"
   ""
+  [(set (match_dup 2)
+       (zero_extend:SI (match_dup 1)))
+   (set (match_dup 3)
+       (const_int 0))]
 {
-  CC_STATUS_INIT;
-  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  return "moveq #0,%0\;moveq #0,%2\;move%.w %1,%2";
+  operands[2] = gen_lowpart (SImode, operands[0]);
+  operands[3] = gen_highpart (SImode, operands[0]);
+})
+
+(define_insn_and_split "zero_extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI (match_operand:HI 1 "nonimmediate_src_operand" "")))]
+  ""
+  "#"
+  ""
+  [(set (match_dup 2)
+       (zero_extend:SI (match_dup 1)))
+   (set (match_dup 3)
+       (const_int 0))]
+{
+  operands[2] = gen_lowpart (SImode, operands[0]);
+  operands[3] = gen_highpart (SImode, operands[0]);
 })
 
-;; this is the canonical form for (lshiftrt:DI x 32)
 (define_expand "zero_extendsidi2"
   [(set (match_operand:DI 0 "nonimmediate_operand" "")
-    (zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
+       (zero_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "")))]
   ""
   "")
 
-(define_insn "*zero_extendsidi2_cf"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
-    (zero_extend:DI (match_operand:SI 1 "general_operand" "rm,r")))]
-  "TARGET_COLDFIRE"
+(define_insn_and_split "*zero_extendsidi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (zero_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "")))]
+  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+  "#"
+  ""
+  [(set (match_dup 2)
+       (match_dup 1))
+   (set (match_dup 3)
+       (const_int 0))]
 {
-  CC_STATUS_INIT;
-  if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    return "move%.l %1,%0\;clr%.l %0";
-  else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    return "clr%.l %0\;move%.l %1,%0";
-  else
-    operands[2] = adjust_address (operands[0], SImode, 4);
-  if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
-      || REGNO (operands[1]) != REGNO (operands[2]))
-    output_asm_insn ("move%.l %1,%2", operands);
-  if (ADDRESS_REG_P (operands[0]))
-    return "sub%.l %0,%0";
-  else
-    return "clr%.l %0";
+  operands[2] = gen_lowpart (SImode, operands[0]);
+  operands[3] = gen_highpart (SImode, operands[0]);
 })
 
-(define_insn "*zero_extendsidi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
-    (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
-  "!TARGET_COLDFIRE"
-{
-  CC_STATUS_INIT;
-  if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    return "move%.l %1,%0\;clr%.l %0";
-  else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    return "clr%.l %0\;move%.l %1,%0";
-  else
-    operands[2] = adjust_address (operands[0], SImode, 4);
-  if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
-      || REGNO (operands[1]) != REGNO (operands[2]))
-    output_asm_insn ("move%.l %1,%2", operands);
-  if (ADDRESS_REG_P (operands[0]))
-    return "sub%.l %0,%0";
-  else
-    return "clr%.l %0";
-})
+(define_insn "*zero_extendhisi2_cf"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
+  "TARGET_CFV4"
+  "mvz%.w %1,%0")
 
-(define_expand "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "")
-       (const_int 0))
-   (set (strict_low_part (match_dup 2))
-       (match_operand:HI 1 "general_operand" ""))]
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
   ""
-  "
-{
-  operands[1] = make_safe_from (operands[1], operands[0]);
-  operands[2] = gen_lowpart_SUBREG (HImode, operands[0]);
-}")
+  "#")
 
 (define_expand "zero_extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "")
-       (const_int 0))
-   (set (strict_low_part (match_dup 2))
-       (match_operand:QI 1 "general_operand" ""))]
-  ""
-  "
-{
-  operands[1] = make_safe_from (operands[1], operands[0]);
-  operands[2] = gen_lowpart_SUBREG (QImode, operands[0]);
-}")
+       (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "")))]
+  "!TARGET_COLDFIRE"
+  "")
 
-(define_expand "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "")
-       (const_int 0))
-   (set (strict_low_part (match_dup 2))
-       (match_operand:QI 1 "general_operand" ""))]
-  ""
-  "
-{
-  operands[1] = make_safe_from (operands[1], operands[0]);
-  operands[2] = gen_lowpart_SUBREG (QImode, operands[0]);
-}")
-\f
-;; Patterns to recognize zero-extend insns produced by the combiner.
-;; We don't allow both operands in memory, because of aliasing problems.
-;; Explicitly disallow two memory operands via the condition since reloading
-;; of this case will result in worse code than the uncombined patterns.
+(define_insn "*zero_extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=d")
+       (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+  "!TARGET_COLDFIRE"
+  "#")
 
-(define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d<")
-       (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
-  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
-{
-  if (DATA_REG_P (operands[0]))
-    {
-      if (TARGET_CFV4)
-        return "mvz%.w %1,%0";
-      if (GET_CODE (operands[1]) == REG
-         && REGNO (operands[0]) == REGNO (operands[1]))
-       return "and%.l #0xFFFF,%0";
-      if (reg_mentioned_p (operands[0], operands[1]))
-        return "move%.w %1,%0\;and%.l #0xFFFF,%0";
-      return "clr%.l %0\;move%.w %1,%0";
-    }
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    return "move%.w %1,%0\;clr%.w %0";
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    return "clr%.w %0\;move%.w %1,%0";
-  else
-    {
-      output_asm_insn ("clr%.w %0", operands);
-      operands[0] = adjust_address (operands[0], HImode, 2);
-      return "move%.w %1,%0";
-    }
-})
+(define_insn "*zero_extendqisi2_cfv4"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+  "TARGET_CFV4"
+  "mvz%.b %1,%0")
 
-(define_insn ""
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=do<>,d")
-       (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
-  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+  ""
+  "#")
+
+;; these two pattern split everything else which isn't matched by
+;; something else above
+(define_split
+  [(set (match_operand 0 "register_operand" "")
+       (zero_extend (match_operand 1 "nonimmediate_src_operand" "")))]
+  "!TARGET_CFV4 && reload_completed && reg_mentioned_p (operands[0], operands[1])"
+  [(set (strict_low_part (match_dup 2))
+       (match_dup 1))
+   (set (match_dup 0)
+       (match_op_dup 4 [(match_dup 0) (match_dup 3)]))]
 {
-  if (DATA_REG_P (operands[0]))
-    {
-      if (GET_CODE (operands[1]) == REG
-         && REGNO (operands[0]) == REGNO (operands[1]))
-       {
-         if (TARGET_CFV4)
-           return "mvz%.b %0,%0";      
-         return (!TARGET_COLDFIRE ? "and%.w #0xFF,%0" : "and%.l #0xFF,%0");
-       }
-      if (reg_mentioned_p (operands[0], operands[1]))
-        {
-         if (TARGET_CFV4)
-           return "mvz%.b %1,%0";      
-         return (!TARGET_COLDFIRE ? "move%.b %1,%0\;and%.w #0xFF,%0" 
-                              : "move%.b %1,%0\;and%.l #0xFF,%0");
-       }
-      return "clr%.w %0\;move%.b %1,%0";
-    }
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    {
-      if (REGNO (XEXP (XEXP (operands[0], 0), 0))
-         == STACK_POINTER_REGNUM)
-       {
-         output_asm_insn ("clr%.w %-", operands);
-         operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
-                                    plus_constant (stack_pointer_rtx, 1));
-         return "move%.b %1,%0";
-       }
-      else
-       return "move%.b %1,%0\;clr%.b %0";
-    }
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    return "clr%.b %0\;move%.b %1,%0";
-  else
-    {
-      output_asm_insn ("clr%.b %0", operands);
-      operands[0] = adjust_address (operands[0], QImode, 1);
-      return "move%.b %1,%0";
-    }
+  operands[2] = gen_lowpart (GET_MODE (operands[1]), operands[0]);
+  operands[3] = GEN_INT (GET_MODE_MASK (GET_MODE (operands[1])));
+  operands[4] = gen_rtx_AND (GET_MODE (operands[0]), operands[0], operands[3]);
 })
 
-(define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d")
-       (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
-  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+(define_split
+  [(set (match_operand 0 "register_operand" "")
+       (zero_extend (match_operand 1 "nonimmediate_src_operand" "")))]
+  "!TARGET_CFV4 && reload_completed"
+  [(set (match_dup 0)
+       (const_int 0))
+   (set (strict_low_part (match_dup 2))
+       (match_dup 1))]
 {
-  if (DATA_REG_P (operands[0]))
-    {
-      if (TARGET_CFV4)
-        return "mvz%.b %1,%0";
-      if (GET_CODE (operands[1]) == REG
-         && REGNO (operands[0]) == REGNO (operands[1]))
-       return "and%.l #0xFF,%0";
-      if (reg_mentioned_p (operands[0], operands[1]))
-        return "move%.b %1,%0\;and%.l #0xFF,%0";
-      return "clr%.l %0\;move%.b %1,%0";
-    }
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    {
-      operands[0] = XEXP (XEXP (operands[0], 0), 0);
-      return MOTOROLA ?
-       "clr%.l -(%0)\;move%.b %1,(3,%0)" :
-       "clrl %0@-\;moveb %1,%0@(3)";
-    }
-  else if (GET_CODE (operands[0]) == MEM
-          && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    {
-      operands[0] = XEXP (XEXP (operands[0], 0), 0);
-      return MOTOROLA ?
-       "clr%.l (%0)+\;move%.b %1,(-1,%0)" :
-       "clrl %0@+\;moveb %1,%0@(-1)";
-    }
-  else
-    {
-      output_asm_insn ("clr%.l %0", operands);
-      operands[0] = adjust_address (operands[0], QImode, 3);
-      return "move%.b %1,%0";
-    }
+  operands[2] = gen_lowpart (GET_MODE (operands[1]), operands[0]);
 })
 \f
 ;; sign extension instructions
   ""
   "")
 
+;; produced by split operations after reload finished
+(define_insn "*andsi3_split"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (and:SI (match_operand:SI 1 "register_operand" "0")
+               (match_operand:SI 2 "const_int_operand" "i")))]
+  "reload_completed && !TARGET_COLDFIRE"
+{
+  return output_andsi3 (operands);
+})
+
 (define_insn "andsi3_internal"
   [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
        (and:SI (match_operand:SI 1 "general_operand" "%0,0")