This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Avoid explicit use of machine modes (12/n) cmp(str|mem)?i


This may well be the last patch in this series.  Same basic concept as
the last one - use optab tables instead of if chains - but for BLKmode
compares.  While I was at it I made the fallback to memcmp() readable.

I'm not sure why this particular set of tables is defined in expr.c
instead of optabs.c.

Bootstrapped i686-linux (i386 being one of the few targets that
defines block memory compares).

zw

        * expr.c (cmpstr_optab, cmpmem_optab): New.
        * genopinit.c: Initialize them.
        * optabs.h: Declare them.
        * optabs.c (init_optabs): Clear them.
        (prepare_cmp_insn):  Use cmpstr_optab and cmpmem_optab to find
        block memory compare insns, not conditional chains.  Restructure
        the fallback generation of a call to memcmp/bcmp for better
        readability.

===================================================================
Index: expr.c
--- expr.c	7 Oct 2003 02:23:36 -0000	1.591
+++ expr.c	7 Oct 2003 07:16:13 -0000
@@ -235,6 +235,11 @@ enum insn_code movstr_optab[NUM_MACHINE_
 /* This array records the insn_code of insns to perform block clears.  */
 enum insn_code clrstr_optab[NUM_MACHINE_MODES];
 
+/* These arrays record the insn_code of two different kinds of insns
+   to perform block compares.  */
+enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
+enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
+
 /* Stack of EXPR_WITH_FILE_LOCATION nested expressions.  */
 struct file_stack *expr_wfl_stack;
 
===================================================================
Index: genopinit.c
--- genopinit.c	7 Oct 2003 02:23:37 -0000	1.61
+++ genopinit.c	7 Oct 2003 07:16:13 -0000
@@ -150,7 +150,9 @@ static const char * const optabs[] =
   "reload_in_optab[$A] = CODE_FOR_$(reload_in$a$)",
   "reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)",
   "movstr_optab[$A] = CODE_FOR_$(movstr$a$)",
-  "clrstr_optab[$A] = CODE_FOR_$(clrstr$a$)" };
+  "clrstr_optab[$A] = CODE_FOR_$(clrstr$a$)",
+  "cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)",
+  "cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)" };
 
 static void gen_insn (rtx);
 
===================================================================
Index: optabs.c
--- optabs.c	7 Oct 2003 02:23:37 -0000	1.195
+++ optabs.c	7 Oct 2003 07:16:14 -0000
@@ -3571,105 +3571,71 @@ prepare_cmp_insn (rtx *px, rtx *py, enum
 
   if (mode == BLKmode)
     {
+      enum machine_mode cmp_mode, result_mode;
+      enum insn_code cmp_code;
+      tree length_type;
+      rtx libfunc;
       rtx result;
-      enum machine_mode result_mode;
-      rtx opalign ATTRIBUTE_UNUSED
+      rtx opalign
 	= GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
 
+      if (size == 0)
+	abort ();
+
       emit_queue ();
       x = protect_from_queue (x, 0);
       y = protect_from_queue (y, 0);
+      size = protect_from_queue (size, 0);
 
-      if (size == 0)
-	abort ();
-#ifdef HAVE_cmpmemqi
-      if (HAVE_cmpmemqi
-	  && GET_CODE (size) == CONST_INT
-	  && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
-	{
-	  result_mode = insn_data[(int) CODE_FOR_cmpmemqi].operand[0].mode;
-	  result = gen_reg_rtx (result_mode);
-	  emit_insn (gen_cmpmemqi (result, x, y, size, opalign));
-	}
-      else
-#endif
-#ifdef HAVE_cmpmemhi
-      if (HAVE_cmpmemhi
-	  && GET_CODE (size) == CONST_INT
-	  && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
-	{
-	  result_mode = insn_data[(int) CODE_FOR_cmpmemhi].operand[0].mode;
-	  result = gen_reg_rtx (result_mode);
-	  emit_insn (gen_cmpmemhi (result, x, y, size, opalign));
-	}
-      else
-#endif
-#ifdef HAVE_cmpmemsi
-      if (HAVE_cmpmemsi)
-	{
-	  result_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
-	  result = gen_reg_rtx (result_mode);
-	  size = protect_from_queue (size, 0);
-	  emit_insn (gen_cmpmemsi (result, x, y,
-				   convert_to_mode (SImode, size, 1),
-				   opalign));
-	}
-      else
-#endif
-#ifdef HAVE_cmpstrqi
-      if (HAVE_cmpstrqi
-	  && GET_CODE (size) == CONST_INT
-	  && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
-	{
-	  result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
-	  result = gen_reg_rtx (result_mode);
-	  emit_insn (gen_cmpstrqi (result, x, y, size, opalign));
-	}
-      else
-#endif
-#ifdef HAVE_cmpstrhi
-      if (HAVE_cmpstrhi
-	  && GET_CODE (size) == CONST_INT
-	  && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
-	{
-	  result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
-	  result = gen_reg_rtx (result_mode);
-	  emit_insn (gen_cmpstrhi (result, x, y, size, opalign));
-	}
-      else
-#endif
-#ifdef HAVE_cmpstrsi
-      if (HAVE_cmpstrsi)
+      /* Try to use a memory block compare insn - either cmpstr
+	 or cmpmem will do.  */
+      for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+	   cmp_mode != VOIDmode;
+	   cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
 	{
-	  result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
+	  cmp_code = cmpmem_optab[cmp_mode];
+	  if (cmp_code == CODE_FOR_nothing)
+	    cmp_code = cmpstr_optab[cmp_mode];
+	  if (cmp_code == CODE_FOR_nothing)
+	    continue;
+
+	  /* Must make sure the size fits the insn's mode.  */
+	  if ((GET_CODE (size) == CONST_INT
+	       && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
+	      || (GET_MODE_BITSIZE (GET_MODE (size))
+		  > GET_MODE_BITSIZE (cmp_mode)))
+	    continue;
+
+	  result_mode = insn_data[cmp_code].operand[0].mode;
 	  result = gen_reg_rtx (result_mode);
-	  size = protect_from_queue (size, 0);
-	  emit_insn (gen_cmpstrsi (result, x, y,
-				   convert_to_mode (SImode, size, 1),
-				   opalign));
+	  size = convert_to_mode (cmp_mode, size, 1);
+	  emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
+
+	  *px = result;
+	  *py = const0_rtx;
+	  *pmode = result_mode;
+	  return;
 	}
-      else
-#endif
-	{
+
+      /* Otherwise call a library function, memcmp if we've got it,
+	 bcmp otherwise.  */
 #ifdef TARGET_MEM_FUNCTIONS
-	  result = emit_library_call_value (memcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
-					    TYPE_MODE (integer_type_node), 3,
-					    XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
-					    convert_to_mode (TYPE_MODE (sizetype), size,
-							     TREE_UNSIGNED (sizetype)),
-					    TYPE_MODE (sizetype));
+      libfunc = memcmp_libfunc;
+      length_type = sizetype;
 #else
-	  result = emit_library_call_value (bcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
-					    TYPE_MODE (integer_type_node), 3,
-					    XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
-					    convert_to_mode (TYPE_MODE (integer_type_node),
-							     size,
-							     TREE_UNSIGNED (integer_type_node)),
-					    TYPE_MODE (integer_type_node));
+      libfunc = bcmp_libfunc;
+      length_type = integer_type_node;
 #endif
-
-	  result_mode = TYPE_MODE (integer_type_node);
-	}
+      result_mode = TYPE_MODE (integer_type_node);
+      cmp_mode = TYPE_MODE (length_type);
+      size = convert_to_mode (TYPE_MODE (length_type), size,
+			      TREE_UNSIGNED (length_type));
+
+      result = emit_library_call_value (libfunc, 0, LCT_PURE_MAKE_BLOCK,
+					result_mode, 3,
+					XEXP (x, 0), Pmode,
+					XEXP (y, 0), Pmode,
+					size, cmp_mode);
       *px = result;
       *py = const0_rtx;
       *pmode = result_mode;
@@ -5330,6 +5296,8 @@ init_optabs (void)
     {
       movstr_optab[i] = CODE_FOR_nothing;
       clrstr_optab[i] = CODE_FOR_nothing;
+      cmpstr_optab[i] = CODE_FOR_nothing;
+      cmpmem_optab[i] = CODE_FOR_nothing;
 
 #ifdef HAVE_SECONDARY_RELOADS
       reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
===================================================================
Index: optabs.h
--- optabs.h	7 Oct 2003 02:23:38 -0000	1.18
+++ optabs.h	7 Oct 2003 07:16:14 -0000
@@ -348,6 +348,11 @@ extern enum insn_code movstr_optab[NUM_M
 /* This array records the insn_code of insns to perform block clears.  */
 extern enum insn_code clrstr_optab[NUM_MACHINE_MODES];
 
+/* These arrays record the insn_code of two different kinds of insns
+   to perform block compares.  */
+extern enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
+extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
+
 /* Define functions given in optabs.c.  */
 
 /* Expand a binary operation given optab and rtx operands.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]