diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cse.c | 78 | ||||
-rw-r--r-- | gcc/fold-const.c | 12 | ||||
-rw-r--r-- | gcc/tree.def | 6 |
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). @@ -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. |