cse.c (find_comparison_args): Update documentation.
authorMark Mitchell <mark@codesourcery.com>
Mon, 19 Mar 2001 18:53:04 +0000 (18:53 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 19 Mar 2001 18:53:04 +0000 (18:53 +0000)
* cse.c (find_comparison_args): Update documentation.  Fix
mishandling of COMPARE operations.

* tree.def (ABS_EXPR): Add documentation.
* fold-const.c (fold): Improve folding of ABS_EXPRs.

From-SVN: r40630

gcc/ChangeLog
gcc/cse.c
gcc/fold-const.c
gcc/tree.def

index 0ea8139c37575639967080188f1091e788083a68..0eb39de722a1ce73387847f8e991aa954117c041 100644 (file)
@@ -1,3 +1,11 @@
+2001-03-19  Mark Mitchell  <mark@codesourcery.com>
+
+       * cse.c (find_comparison_args): Update documentation.  Fix
+       mishandling of COMPARE operations.
+
+       * tree.def (ABS_EXPR): Add documentation.
+       * fold-const.c (fold): Improve folding of ABS_EXPRs.
+
 2001-03-19  Zack Weinberg  <zackw@stanford.edu>
 
        * Makefile.in (hash.o): Depend on $(GCONFIG_H), not $(CONFIG_H).
index 38ba919f115abe387795afd8099739e5f2752478..9ba7f72d409b8050beccf733e05a83ac9f3ece16 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -3086,17 +3086,25 @@ find_best_addr (insn, loc, mode)
 #endif
 }
 \f
-/* Given an operation (CODE, *PARG1, *PARG2), where code is a comparison
-   operation (EQ, NE, GT, etc.), follow it back through the hash table and
-   what values are being compared.
+/* This routine accepts a comparison as input and attempts to return a
+   comparision that is cheaper to compute.
 
-   *PARG1 and *PARG2 are updated to contain the rtx representing the values
-   actually being compared.  For example, if *PARG1 was (cc0) and *PARG2
-   was (const_int 0), *PARG1 and *PARG2 will be set to the objects that were
-   compared to produce cc0.
+   On input, *PARG1 and *PARG2 should be set to the first and second
+   arguments to the comparison, respectively.  CODE is the comparision
+   code.  For example, if the comparison is:
 
-   The return value is the comparison operator and is either the code of
-   A or the code corresponding to the inverse of the comparison.  */
+     (ne:SI (reg:CC 24 cc)
+            (const_int 0 [0x0])))
+
+   The CODE should be NE, *PARG1 should be `(reg:CC 24 cc)' and 
+   *PARG2 should be `(const_int 0)'.
+
+   Upon return, *PARG1 and and *PARG2 may have new values, indicating
+   arguments to a cheaper comparison.  *PMODE1 and *PMODE2 will be the
+   modes that should be used for those arguments.  The return value
+   itself will be the comparison code that should be used to compare
+   *PARG1 and *PARG2 in order to obtain a value equivalent to that
+   given by the original comparison.  */
 
 static enum rtx_code
 find_comparison_args (code, parg1, parg2, pmode1, pmode2)
@@ -3187,30 +3195,38 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
          if (! exp_equiv_p (p->exp, p->exp, 1, 0))
            continue;
 
-         if (GET_CODE (p->exp) == COMPARE
-             /* Another possibility is that this machine has a compare insn
-                that includes the comparison code.  In that case, ARG1 would
-                be equivalent to a comparison operation that would set ARG1 to
-                either STORE_FLAG_VALUE or zero.  If this is an NE operation,
-                ORIG_CODE is the actual comparison being done; if it is an EQ,
-                we must reverse ORIG_CODE.  On machine with a negative value
-                for STORE_FLAG_VALUE, also look at LT and GE operations.  */
-             || ((code == NE
-                  || (code == LT
-                      && GET_MODE_CLASS (inner_mode) == MODE_INT
-                      && (GET_MODE_BITSIZE (inner_mode)
-                          <= HOST_BITS_PER_WIDE_INT)
-                      && (STORE_FLAG_VALUE
-                          & ((HOST_WIDE_INT) 1
-                             << (GET_MODE_BITSIZE (inner_mode) - 1))))
+         /* `(COMPARE A B) != 0)' is equivalent to `(COMPARE A B)'.
+            If CODE is EQ, rather than NE, then we are out of luck;
+            there is no way to reverse the sense of a COMPARE.  */
+         if (code == NE && GET_CODE (p->exp) == COMPARE)
+           {
+             x = p->exp;
+             break;
+           }
+         /* Another possibility is that this machine has a compare
+            insn that includes the comparison code.  In that case,
+            ARG1 would be equivalent to a comparison operation that
+            would set ARG1 to either STORE_FLAG_VALUE or zero.  If
+            this is an NE operation, ORIG_CODE is the actual
+            comparison being done; if it is an EQ, we must reverse
+            ORIG_CODE.  On machine with a negative value for
+            STORE_FLAG_VALUE, also look at LT and GE operations.  */
+         else if ((code == NE
+                   || (code == LT
+                       && GET_MODE_CLASS (inner_mode) == MODE_INT
+                       && (GET_MODE_BITSIZE (inner_mode)
+                           <= HOST_BITS_PER_WIDE_INT)
+                       && (STORE_FLAG_VALUE
+                           & ((HOST_WIDE_INT) 1
+                              << (GET_MODE_BITSIZE (inner_mode) - 1))))
 #ifdef FLOAT_STORE_FLAG_VALUE
-                  || (code == LT
-                      && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
-                      && (REAL_VALUE_NEGATIVE
-                          (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+                   || (code == LT
+                       && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
+                       && (REAL_VALUE_NEGATIVE
+                           (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
 #endif
-                  )
-                 && GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
+                   )
+                  && GET_RTX_CLASS (GET_CODE (p->exp)) == '<')
            {
              x = p->exp;
              break;
index dda3102cfae34d534b1ecd13af8654eb36f4512d..ed988222d4b19b7cdd4e85e323874ccd05632257 100644 (file)
@@ -5275,8 +5275,16 @@ fold (expr)
        {
          if (TREE_CODE (arg0) == INTEGER_CST)
            {
-             if (! TREE_UNSIGNED (type)
-                 && TREE_INT_CST_HIGH (arg0) < 0)
+             /* If the value is unsigned, then the absolute value is
+                the same as the ordinary value.  */
+             if (TREE_UNSIGNED (type))
+               return arg0;
+             /* Similarly, if the value is non-negative.  */
+             else if (INT_CST_LT (integer_minus_one_node, arg0))
+               return arg0;
+             /* If the value is negative, then the absolute value is
+                its negation.  */
+             else
                {
                  unsigned HOST_WIDE_INT low;
                  HOST_WIDE_INT high;
index 4ccd6e38944597f73f57eb2d3ecdf6f6de14b54d..399e05706a818a43490ac12edf0e74bca55230a8 100644 (file)
@@ -602,7 +602,13 @@ DEFTREECODE (NEGATE_EXPR, "negate_expr", '1', 1)
 
 DEFTREECODE (MIN_EXPR, "min_expr", '2', 2)
 DEFTREECODE (MAX_EXPR, "max_expr", '2', 2)
+
+/* Represents the absolute value of the operand.
+
+   An ABS_EXPR must have either an INTEGER_TYPE or a REAL_TYPE.  The
+   operand of the ABS_EXPR must have the same type.  */
 DEFTREECODE (ABS_EXPR, "abs_expr", '1', 1)
+
 DEFTREECODE (FFS_EXPR, "ffs_expr", '1', 1)
 
 /* Shift operations for shift and rotate.