]> gcc.gnu.org Git - gcc.git/commitdiff
tm.texi (CLZ_DEFINED_VALUE_AT_ZERO, [...]): Document change in interpretation of...
authorSandra Loosemore <sandra@codesourcery.com>
Thu, 9 Aug 2007 14:08:54 +0000 (10:08 -0400)
committerSandra Loosemore <sandra@gcc.gnu.org>
Thu, 9 Aug 2007 14:08:54 +0000 (10:08 -0400)
2007-08-09  Sandra Loosemore  <sandra@codesourcery.com>
    Nigel Stephens  <nigel@mips.com>

gcc/
* doc/tm.texi (CLZ_DEFINED_VALUE_AT_ZERO, CTZ_DEFINED_VALUE_AT_ZERO):
Document change in interpretation of value from boolean to
tri-state integer.
* optabs.c (expand_ffs, expand_ctz): New functions to compute
ffs and ctz using clz.
(expand_unop):  Call them.
* config/rs6000/rs6000.h (CLZ_DEFINED_VALUE_AT_ZERO): Fix its
result value.
(CTZ_DEFINED_VALUE_AT_ZERO): Likewise.
* config/mips/mips.h (CLZ_DEFINED_VALUE_AT_ZERO): Likewise, to
enable the new ffs expansion on this target.

Co-Authored-By: Nigel Stephens <nigel@mips.com>
From-SVN: r127318

gcc/ChangeLog
gcc/config/mips/mips.h
gcc/config/rs6000/rs6000.h
gcc/doc/tm.texi
gcc/optabs.c

index d5170d8e9f9af8fc454bd5fd2aeee7f904702a21..826aa532c63525ef3dd1a642d458da0d312b4f36 100644 (file)
@@ -1,3 +1,18 @@
+2007-08-09  Sandra Loosemore  <sandra@codesourcery.com>
+           Nigel Stephens  <nigel@mips.com>
+
+       * doc/tm.texi (CLZ_DEFINED_VALUE_AT_ZERO, CTZ_DEFINED_VALUE_AT_ZERO):
+       Document change in interpretation of value from boolean to
+       tri-state integer.
+       * optabs.c (expand_ffs, expand_ctz): New functions to compute
+       ffs and ctz using clz.
+       (expand_unop):  Call them.
+       * config/rs6000/rs6000.h (CLZ_DEFINED_VALUE_AT_ZERO): Fix its
+       result value.
+       (CTZ_DEFINED_VALUE_AT_ZERO): Likewise.
+       * config/mips/mips.h (CLZ_DEFINED_VALUE_AT_ZERO): Likewise, to
+       enable the new ffs expansion on this target.
+
 2007-08-09  Jan Hubicka  <jh@suse.cz>
 
        * optabs.c (expand_widen_pattern_expr): Use optabs accestors.
index 9a55f02fc7c823090f14ae2e4409560848a73435..9e9047846d543f0e757e507cf5d18148b02c7df5 100644 (file)
@@ -1295,7 +1295,7 @@ extern enum mips_code_readable_setting mips_code_readable;
 /* The [d]clz instructions have the natural values at 0.  */
 
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
-  ((VALUE) = GET_MODE_BITSIZE (MODE), true)
+  ((VALUE) = GET_MODE_BITSIZE (MODE), 2)
 \f
 /* Standard register usage.  */
 
index fae5ea2b578b59ab9dfccc779aa1f22cfcf13476..5f34c800fb62fe8ae91ea0d41da672871cd1202c 100644 (file)
@@ -1856,10 +1856,10 @@ do {                                                            \
 
 /* The cntlzw and cntlzd instructions return 32 and 64 for input of zero.  */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
-  ((VALUE) = ((MODE) == SImode ? 32 : 64))
+  ((VALUE) = ((MODE) == SImode ? 32 : 64), 1)
 
 /* The CTZ patterns return -1 for input of zero.  */
-#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = -1)
+#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = -1, 1)
 
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
index bf6859d2c39366570b454016fd94860fb908ecf0..1b690a1cb726af2c298d7842d8fae3118af6ad06 100644 (file)
@@ -9638,14 +9638,23 @@ given mode.
 
 @defmac CLZ_DEFINED_VALUE_AT_ZERO (@var{mode}, @var{value})
 @defmacx CTZ_DEFINED_VALUE_AT_ZERO (@var{mode}, @var{value})
-A C expression that evaluates to true if the architecture defines a value
-for @code{clz} or @code{ctz} with a zero operand.  If so, @var{value}
-should be set to this value.  If this macro is not defined, the value of
-@code{clz} or @code{ctz} is assumed to be undefined.
+A C expression that indicates whether the architecture defines a value
+for @code{clz} or @code{ctz} with a zero operand.  
+A result of @code{0} indicates the value is undefined.
+If the value is defined for only the RTL expression, the macro should
+evaluate to @code{1}; if the value applies also to the corresponding optab
+entry (which is normally the case if it expands directly into
+the corresponding RTL), then the macro should evaluate to @code{2}.  
+In the cases where the value is defined, @var{value} should be set to
+this value.  
+
+If this macro is not defined, the value of @code{clz} or
+@code{ctz} at zero is assumed to be undefined.
 
 This macro must be defined if the target's expansion for @code{ffs}
 relies on a particular value to get correct results.  Otherwise it
-is not necessary, though it may be used to optimize some corner cases.
+is not necessary, though it may be used to optimize some corner cases, and
+to provide a default expansion for the @code{ffs} optab.
 
 Note that regardless of this macro the ``definedness'' of @code{clz}
 and @code{ctz} at zero do @emph{not} extend to the builtin functions
index 5afd935657d76ae4f45e9e11145339bb97a29f21..bf15d4f925b1e20ed408357e0db07545a9ad0e3b 100644 (file)
@@ -122,6 +122,8 @@ static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *,
                                   enum machine_mode *, int *);
 static rtx widen_clz (enum machine_mode, rtx, rtx);
 static rtx expand_parity (enum machine_mode, rtx, rtx);
+static rtx expand_ffs (enum machine_mode, rtx, rtx);
+static rtx expand_ctz (enum machine_mode, rtx, rtx);
 static enum rtx_code get_rtx_code (enum tree_code, bool);
 static rtx vector_compare_rtx (tree, bool, enum insn_code);
 
@@ -2561,6 +2563,68 @@ expand_parity (enum machine_mode mode, rtx op0, rtx target)
   return 0;
 }
 
+/* Try calculating ffs(x) using clz(x).  Since the ffs builtin promises
+   to return zero for a zero value and clz may have an undefined value
+   in that case, only do this if we know clz returns the right thing so
+   that we don't have to generate a test and branch.  */
+static rtx
+expand_ffs (enum machine_mode mode, rtx op0, rtx target)
+{
+  HOST_WIDE_INT val;
+  if (clz_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
+      && CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2
+      && val == GET_MODE_BITSIZE (mode))
+    {
+      rtx last = get_last_insn ();
+      rtx temp;
+
+      temp = expand_unop (mode, neg_optab, op0, NULL_RTX, true);
+      if (temp)
+       temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
+                            true, OPTAB_DIRECT);
+      if (temp)
+       temp = expand_unop (mode, clz_optab, temp, NULL_RTX, true);
+      if (temp)
+       temp = expand_binop (mode, sub_optab,
+                            GEN_INT (GET_MODE_BITSIZE (mode)),
+                            temp,
+                            target, true, OPTAB_DIRECT);
+      if (temp == 0)
+       delete_insns_since (last);
+      return temp;
+    }
+  return 0;
+}
+
+/* We can compute ctz(x) using clz(x) with a similar recipe.  Here the ctz
+   builtin has an undefined result on zero, just like clz, so we don't have
+   to do that check.  */
+static rtx
+expand_ctz (enum machine_mode mode, rtx op0, rtx target)
+{
+  if (clz_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+    {
+      rtx last = get_last_insn ();
+      rtx temp;
+
+      temp = expand_unop (mode, neg_optab, op0, NULL_RTX, true);
+      if (temp)
+       temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
+                            true, OPTAB_DIRECT);
+      if (temp)
+       temp = expand_unop (mode, clz_optab, temp, NULL_RTX, true);
+      if (temp)
+       temp = expand_binop (mode, xor_optab, temp,
+                            GEN_INT (GET_MODE_BITSIZE (mode) - 1),
+                            target,
+                            true, OPTAB_DIRECT);
+      if (temp == 0)
+       delete_insns_since (last);
+      return temp;
+    }
+  return 0;
+}
+
 /* Extract the OMODE lowpart from VAL, which has IMODE.  Under certain
    conditions, VAL may already be a SUBREG against which we cannot generate
    a further SUBREG.  In this case, we expect forcing the value into a
@@ -2886,6 +2950,22 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
        return temp;
     }
 
+  /* Try implementing ffs (x) in terms of clz (x).  */
+  if (unoptab == ffs_optab)
+    {
+      temp = expand_ffs (mode, op0, target);
+      if (temp)
+       return temp;
+    }
+
+  /* Try implementing ctz (x) in terms of clz (x).  */
+  if (unoptab == ctz_optab)
+    {
+      temp = expand_ctz (mode, op0, target);
+      if (temp)
+       return temp;
+    }
+
  try_libcall:
   /* Now try a library call in this mode.  */
   if (optab_handler (unoptab, mode)->libfunc)
This page took 0.128439 seconds and 5 git commands to generate.