diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-10-11 21:06:19 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-10-11 21:06:19 +0000 |
commit | c877353c907f31f7af74452d4eb2c44b6900493d (patch) | |
tree | 7cecf6ae296fc7a727d050bc66fc9a49652ab40e /gcc | |
parent | e3be1116138b7a387420d370e9f6fddcc395f283 (diff) | |
download | gcc-c877353c907f31f7af74452d4eb2c44b6900493d.zip gcc-c877353c907f31f7af74452d4eb2c44b6900493d.tar.gz gcc-c877353c907f31f7af74452d4eb2c44b6900493d.tar.bz2 |
re PR rtl-optimization/12260 (ICE in output_operand: invalid expression as operand)
PR optimization/12260
* simplify-rtx.c (simplify_unary_operation): Simplify all unary
operations through CONST nodes. Optimize (neg (plus X C)) as
(minus -C X) for constant values C.
(simplify_binary_operation): Optimize (minus (neg X) C) as
(minus -C X) for constant values C.
(simplify_plus_minus): Avoid creating (neg (const (plus X C)),
instead create (minus -C X).
* gcc.c-torture/compile/20031011-2.c: New test case.
From-SVN: r72379
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/20031011-2.c | 15 |
4 files changed, 62 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 38bd51f..4251bf3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2003-10-11 Roger Sayle <roger@eyesopen.com> + PR optimization/12260 + * simplify-rtx.c (simplify_unary_operation): Simplify all unary + operations through CONST nodes. Optimize (neg (plus X C)) as + (minus -C X) for constant values C. + (simplify_binary_operation): Optimize (minus (neg X) C) as + (minus -C X) for constant values C. + (simplify_plus_minus): Avoid creating (neg (const (plus X C)), + instead create (minus -C X). + +2003-10-11 Roger Sayle <roger@eyesopen.com> + * expr.c (expand_expr <PLUS_EXPR>): Let expand_operands call safe_from_p for us, once it chooses an evaluation order. (expand_expr <MULT_EXPR>): Likewise. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 0e86463..22ba167 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -407,6 +407,8 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, return gen_rtx_CONST_VECTOR (mode, v); } } + else if (GET_CODE (op) == CONST) + return simplify_unary_operation (code, mode, XEXP (op, 0), op_mode); if (VECTOR_MODE_P (mode) && GET_CODE (trueop) == CONST_VECTOR) { @@ -971,11 +973,22 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, return simplify_gen_binary (MINUS, mode, XEXP (op, 1), XEXP (op, 0)); - /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ if (GET_CODE (op) == PLUS && !HONOR_SIGNED_ZEROS (mode) && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) { + /* (neg (plus A C)) is simplified to (minus -C A). */ + if (GET_CODE (XEXP (op, 1)) == CONST_INT + || GET_CODE (XEXP (op, 1)) == CONST_DOUBLE) + { + temp = simplify_unary_operation (NEG, mode, XEXP (op, 1), + mode); + if (temp) + return simplify_gen_binary (MINUS, mode, temp, + XEXP (op, 0)); + } + + /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1)); } @@ -1572,6 +1585,16 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, if (GET_CODE (op1) == NEG) return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); + /* (-x - c) may be simplified as (-c - x). */ + if (GET_CODE (op0) == NEG + && (GET_CODE (op1) == CONST_INT + || GET_CODE (op1) == CONST_DOUBLE)) + { + tem = simplify_unary_operation (NEG, mode, op1, mode); + if (tem) + return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0)); + } + /* If one of the operands is a PLUS or a MINUS, see if we can simplify this by the associative law. Don't use the associative law for floating point. @@ -2375,6 +2398,13 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0, /* Sort the operations based on swap_commutative_operands_p. */ qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp); + /* Create (minus -C X) instead of (neg (const (plus X C))). */ + if (n_ops == 2 + && GET_CODE (ops[1].op) == CONST_INT + && CONSTANT_P (ops[0].op) + && ops[0].neg) + return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op); + /* We suppressed creation of trivial CONST expressions in the combination loop to avoid recursion. Create one manually now. The combination loop should have ensured that there is exactly diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 331794d..ad9bafc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2003-10-11 Roger Sayle <roger@eyesopen.com> + PR optimization/12260 + * gcc.c-torture/compile/20031011-2.c: New test case. + +2003-10-11 Roger Sayle <roger@eyesopen.com> + * gcc.c-torture/execute/20031011-1.c: New testcase. 2003-10-11 Eric Botcazou <ebotcazou@libertysurf.fr> diff --git a/gcc/testsuite/gcc.c-torture/compile/20031011-2.c b/gcc/testsuite/gcc.c-torture/compile/20031011-2.c new file mode 100644 index 0000000..0268455 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20031011-2.c @@ -0,0 +1,15 @@ +/* PR optimization/12260. */ + +extern int f(void); +extern int g(int); + +static char buf[512]; +void h(int l) { + while (l) { + char *op = buf; + if (f() == 0) + break; + if (g(op - buf + 1)) + break; + } +} |