Patchwork Commit: RX: Add support for MIN and MAX instructions in QI and HI modes

login
register
mail settings
Submitter Nick Clifton
Date Sept. 28, 2011, 2:34 p.m.
Message ID <m3d3ekka6m.fsf@redhat.com>
Download mbox | patch
Permalink /patch/116797/
State New
Headers show

Comments

Nick Clifton - Sept. 28, 2011, 2:34 p.m.
Hi Guys,

  I am going to apply the patch below to the RX backend to add support
  for generating MIN and MAX instructions for HI and QI modes.

Cheers
  Nick

gcc/ChangeLog
2011-09-28  Nick Clifton  <nickc@redhat.com>

	* config/rx/predicates.md (rx_minmax_operand): New predicate.
	Accepts immediates and a restricted subset of MEMs.
	* config/rx/rx.md (int_modes): New iterator.
	(smaxsi3, sminsi3): Delete and replace with...
	(smax<int_mode>3, smin<int_mode>3): New patterns.
	(umax<>3_u, umax<>3_ur, umax<>3, umin<>3): New patterns.
Richard Henderson - Sept. 30, 2011, 10:39 p.m.
On 09/28/2011 07:34 AM, Nick Clifton wrote:
> -(define_insn "smaxsi3"
> -  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
> -	(smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
> -		 (match_operand:SI 2 "rx_source_operand"
> -				   "r,Sint08,Sint16,Sint24,i,Q")))]
> +(define_insn "smax<int_modes:mode>3"
> +  [(set (match_operand:int_modes                 0 "register_operand" "=r,r,r,r,r,r")
> +	(smax:int_modes (match_operand:int_modes 1 "register_operand" "%0,0,0,0,0,0")
> +			(match_operand:int_modes 2 "rx_source_operand"
> +						 "r,Sint08,Sint16,Sint24,i,Q")))]
>    ""
>    "max\t%Q2, %0"

Huh?  This doesn't work for HI or QImode.  You need to sign-extend them first
to get rid of (potential) garbage in the high bits of the register.

At least, there's no .W or .B specifiers in the document I have; only .L.


r~

Patch

Index: gcc/config/rx/predicates.md
===================================================================
--- gcc/config/rx/predicates.md	(revision 179307)
+++ gcc/config/rx/predicates.md	(working copy)
@@ -72,6 +72,16 @@ 
        (match_operand 0 "rx_restricted_mem_operand"))
 )
 
+;; Check that the operand is suitable as the source operand
+;; for a min/max instruction.  This is the same as
+;; rx_source_operand except that CONST_INTs are allowed but
+;; REGs and SUBREGs are not.
+
+(define_predicate "rx_minmaxex_operand"
+  (ior (match_operand 0 "immediate_operand")
+       (match_operand 0 "rx_restricted_mem_operand"))
+)
+
 ;; Return true if OP is a store multiple operation.  This looks like:
 ;;
 ;;   [(set (SP) (MINUS (SP) (INT)))
Index: gcc/config/rx/rx.md
===================================================================
--- gcc/config/rx/rx.md	(revision 179307)
+++ gcc/config/rx/rx.md	(working copy)
@@ -22,6 +22,9 @@ 
 ;; This code iterator is used for sign- and zero- extensions.
 (define_mode_iterator small_int_modes [(HI "") (QI "")])
 
+;; This code iterator is used for max and min operations.
+(define_mode_iterator int_modes [(SI "") (HI "") (QI "")])
+
 ;; We do not handle DFmode here because it is either
 ;; the same as SFmode, or if -m64bit-doubles is active
 ;; then all operations on doubles have to be handled by
@@ -1160,28 +1163,109 @@ 
    (set_attr "timings" "22,44")]
 )
 
-(define_insn "smaxsi3"
-  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
-	(smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
-		 (match_operand:SI 2 "rx_source_operand"
-				   "r,Sint08,Sint16,Sint24,i,Q")))]
+(define_insn "smax<int_modes:mode>3"
+  [(set (match_operand:int_modes                 0 "register_operand" "=r,r,r,r,r,r")
+	(smax:int_modes (match_operand:int_modes 1 "register_operand" "%0,0,0,0,0,0")
+			(match_operand:int_modes 2 "rx_source_operand"
+						 "r,Sint08,Sint16,Sint24,i,Q")))]
   ""
   "max\t%Q2, %0"
   [(set_attr "length" "3,4,5,6,7,6")
    (set_attr "timings" "11,11,11,11,11,33")]
 )
 
-(define_insn "sminsi3"
-  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
-	(smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
-		 (match_operand:SI 2 "rx_source_operand"
-				   "r,Sint08,Sint16,Sint24,i,Q")))]
+(define_insn "smin<int_modes:mode>3"
+  [(set (match_operand:int_modes                 0 "register_operand" "=r,r,r,r,r,r")
+	(smin:int_modes (match_operand:int_modes 1 "register_operand" "%0,0,0,0,0,0")
+		 (match_operand:int_modes        2 "rx_source_operand"
+						 "r,Sint08,Sint16,Sint24,i,Q")))]
   ""
   "min\t%Q2, %0"
   [(set_attr "length"  "3,4,5,6,7,6")
    (set_attr "timings" "11,11,11,11,11,33")]
 )
 
+(define_insn "umax<small_int_modes:mode>3_u"
+  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
+	(smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
+		 (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
+								"r,Sint08,Sint16,Sint24,i,Q"))))]
+  ""
+  "max\t%R2, %0"
+  [(set_attr "length"  "3,4,5,6,7,6")
+   (set_attr "timings" "11,11,11,11,11,33")]
+)
+
+(define_insn "umin<small_int_modes:mode>3_ur"
+  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
+	(smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
+								"r,Sint08,Sint16,Sint24,i,Q"))
+		 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
+  ""
+  "min\t%R2, %0"
+  [(set_attr "length"  "3,4,5,6,7,6")
+   (set_attr "timings" "11,11,11,11,11,33")]
+)
+
+(define_insn "umax<small_int_modes:mode>3_ur"
+  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
+	(smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
+								"r,Sint08,Sint16,Sint24,i,Q"))
+		 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
+  ""
+  "max\t%R2, %0"
+  [(set_attr "length"  "3,4,5,6,7,6")
+   (set_attr "timings" "11,11,11,11,11,33")]
+)
+
+(define_expand "umax<small_int_modes:mode>3"
+  [(set (match_dup 4)
+	(zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
+   (set (match_dup 3)
+	(smax:SI (match_dup 4)
+		 (match_operand:small_int_modes 2 "rx_source_operand"
+						"r,Sint08,Sint16,Sint24,i,Q")))
+   (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
+	(match_dup 6))
+   ]
+  ""
+  "operands[3] = gen_reg_rtx (SImode);
+   operands[4] = gen_reg_rtx (SImode);
+   operands[5] = gen_reg_rtx (SImode);
+   operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
+     TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
+   if (GET_CODE (operands[2]) != CONST_INT)
+     {
+       emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
+       operands[2] = operands[5];
+     }
+  "
+)
+
+(define_expand "umin<small_int_modes:mode>3"
+  [(set (match_dup 4)
+	(zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
+   (set (match_dup 3)
+	(smin:SI (match_dup 4)
+		 (match_operand:small_int_modes 2 "rx_source_operand"
+						"r,Sint08,Sint16,Sint24,i,Q")))
+   (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
+	(match_dup 6))
+   ]
+  ""
+  "operands[3] = gen_reg_rtx (SImode);
+   operands[4] = gen_reg_rtx (SImode);
+   operands[5] = gen_reg_rtx (SImode);
+   operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
+     TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
+   if (GET_CODE (operands[2]) != CONST_INT)
+     {
+       emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
+       operands[2] = operands[5];
+     }
+   "
+)
+
 (define_insn "mulsi3"
   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r,r,r,r")
         (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")