aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cse.c78
-rw-r--r--gcc/fold-const.c12
-rw-r--r--gcc/tree.def6
4 files changed, 71 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0ea8139..0eb39de 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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).
diff --git a/gcc/cse.c b/gcc/cse.c
index 38ba919..9ba7f72 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -3086,17 +3086,25 @@ find_best_addr (insn, loc, mode)
#endif
}
-/* 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;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index dda3102..ed98822 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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;
diff --git a/gcc/tree.def b/gcc/tree.def
index 4ccd6e3..399e057 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -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.