From 9ce79a7a5ee9a5dbf634979dc17534d01459104f Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Mon, 19 Jan 2004 21:51:06 +0000 Subject: [PATCH] re PR rtl-optimization/5263 (a & b & ~a & ~b not optimized) PR optimization/5263 * simplify-rtx.c (associative_constant_p): Delete. (simplify_associative_operation): Rewrite to linearize terms, and attempt to simplify new term against both left and right subterms. (simplify_binary_operation): Call swap_commutative_operands_p on op0 and op1, not trueop0 and trueop1. Move the initialization of trueop0 and trueop1 down to where first needed. (simplify_relational_operation): Likewise. * rtlanal.c (commutative_operand_precedence): Also order constant operands using avoid_constant_pool_reference. From-SVN: r76179 --- gcc/ChangeLog | 13 ++++++ gcc/rtlanal.c | 7 ++- gcc/simplify-rtx.c | 107 +++++++++++++++++++++------------------------ 3 files changed, 68 insertions(+), 59 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4de9dac9f16..7949b4feadc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2004-01-19 Roger Sayle + + PR optimization/5263 + * simplify-rtx.c (associative_constant_p): Delete. + (simplify_associative_operation): Rewrite to linearize terms, and + attempt to simplify new term against both left and right subterms. + (simplify_binary_operation): Call swap_commutative_operands_p on + op0 and op1, not trueop0 and trueop1. Move the initialization of + trueop0 and trueop1 down to where first needed. + (simplify_relational_operation): Likewise. + * rtlanal.c (commutative_operand_precedence): Also order constant + operands using avoid_constant_pool_reference. + 2004-01-19 Richard Henderson * config/alpha/alpha.c (aligned_memory_operand): Check MEM_ALIGN, diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 15c4879eb0b..44a6c6c40f8 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1,6 +1,6 @@ /* Analyze RTL for C-Compiler Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -3022,6 +3022,11 @@ int commutative_operand_precedence (rtx op) { /* Constants always come the second operand. Prefer "nice" constants. */ + if (GET_CODE (op) == CONST_INT) + return -7; + if (GET_CODE (op) == CONST_DOUBLE) + return -6; + op = avoid_constant_pool_reference (op); if (GET_CODE (op) == CONST_INT) return -5; if (GET_CODE (op) == CONST_DOUBLE) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 51585c80b0b..7272424f8cc 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -55,7 +55,6 @@ static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx, rtx, int); static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode, unsigned int); -static bool associative_constant_p (rtx); static rtx simplify_associative_operation (enum rtx_code, enum machine_mode, rtx, rtx); @@ -1084,67 +1083,59 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, } } -/* Subroutine of simplify_associative_operation. Return true if rtx OP - is a suitable integer or floating point immediate constant. */ -static bool -associative_constant_p (rtx op) -{ - if (GET_CODE (op) == CONST_INT - || GET_CODE (op) == CONST_DOUBLE) - return true; - op = avoid_constant_pool_reference (op); - return GET_CODE (op) == CONST_INT - || GET_CODE (op) == CONST_DOUBLE; -} +/* Subroutine of simplify_binary_operation to simplify a commutative, + associative binary operation CODE with result mode MODE, operating + on OP0 and OP1. CODE is currently one of PLUS, MULT, AND, IOR, XOR, + SMIN, SMAX, UMIN or UMAX. Return zero if no simplification or + canonicalization is possible. */ -/* Subroutine of simplify_binary_operation to simplify an associative - binary operation CODE with result mode MODE, operating on OP0 and OP1. - Return 0 if no simplification is possible. */ static rtx simplify_associative_operation (enum rtx_code code, enum machine_mode mode, rtx op0, rtx op1) { rtx tem; - /* Simplify (x op c1) op c2 as x op (c1 op c2). */ - if (GET_CODE (op0) == code - && associative_constant_p (op1) - && associative_constant_p (XEXP (op0, 1))) + /* Linearize the operator to the left. */ + if (GET_CODE (op1) == code) { - tem = simplify_binary_operation (code, mode, XEXP (op0, 1), op1); - if (! tem) - return tem; - return simplify_gen_binary (code, mode, XEXP (op0, 0), tem); + /* "(a op b) op (c op d)" becomes "((a op b) op c) op d)". */ + if (GET_CODE (op0) == code) + { + tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); + return simplify_gen_binary (code, mode, tem, XEXP (op1, 1)); + } + + /* "a op (b op c)" becomes "(b op c) op a". */ + if (! swap_commutative_operands_p (op1, op0)) + return simplify_gen_binary (code, mode, op1, op0); + + tem = op0; + op0 = op1; + op1 = tem; } - /* Simplify (x op c1) op (y op c2) as (x op y) op (c1 op c2). */ - if (GET_CODE (op0) == code - && GET_CODE (op1) == code - && associative_constant_p (XEXP (op0, 1)) - && associative_constant_p (XEXP (op1, 1))) + if (GET_CODE (op0) == code) { - rtx c = simplify_binary_operation (code, mode, - XEXP (op0, 1), XEXP (op1, 1)); - if (! c) - return 0; - tem = simplify_gen_binary (code, mode, XEXP (op0, 0), XEXP (op1, 0)); - return simplify_gen_binary (code, mode, tem, c); - } + /* Canonicalize "(x op c) op y" as "(x op y) op c". */ + if (swap_commutative_operands_p (XEXP (op0, 1), op1)) + { + tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); + return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); + } - /* Canonicalize (x op c) op y as (x op y) op c. */ - if (GET_CODE (op0) == code - && associative_constant_p (XEXP (op0, 1))) - { - tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); - return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); - } + /* Attempt to simplify "(a op b) op c" as "a op (b op c)". */ + tem = swap_commutative_operands_p (XEXP (op0, 1), op1) + ? simplify_binary_operation (code, mode, op1, XEXP (op0, 1)) + : simplify_binary_operation (code, mode, XEXP (op0, 1), op1); + if (tem != 0) + return simplify_gen_binary (code, mode, XEXP (op0, 0), tem); - /* Canonicalize x op (y op c) as (x op y) op c. */ - if (GET_CODE (op1) == code - && associative_constant_p (XEXP (op1, 1))) - { - tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); - return simplify_gen_binary (code, mode, tem, XEXP (op1, 1)); + /* Attempt to simplify "(a op b) op c" as "(a op c) op b". */ + tem = swap_commutative_operands_p (XEXP (op0, 0), op1) + ? simplify_binary_operation (code, mode, op1, XEXP (op0, 0)) + : simplify_binary_operation (code, mode, XEXP (op0, 0), op1); + if (tem != 0) + return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); } return 0; @@ -1162,9 +1153,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, HOST_WIDE_INT arg0, arg1, arg0s, arg1s; HOST_WIDE_INT val; unsigned int width = GET_MODE_BITSIZE (mode); + rtx trueop0, trueop1; rtx tem; - rtx trueop0 = avoid_constant_pool_reference (op0); - rtx trueop1 = avoid_constant_pool_reference (op1); /* Relational operations don't work here. We must know the mode of the operands in order to do the comparison correctly. @@ -1176,12 +1166,14 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, /* Make sure the constant is second. */ if (GET_RTX_CLASS (code) == 'c' - && swap_commutative_operands_p (trueop0, trueop1)) + && swap_commutative_operands_p (op0, op1)) { tem = op0, op0 = op1, op1 = tem; - tem = trueop0, trueop0 = trueop1, trueop1 = tem; } + trueop0 = avoid_constant_pool_reference (op0); + trueop1 = avoid_constant_pool_reference (op1); + if (VECTOR_MODE_P (mode) && GET_CODE (trueop0) == CONST_VECTOR && GET_CODE (trueop1) == CONST_VECTOR) @@ -2509,22 +2501,21 @@ simplify_relational_operation (enum rtx_code code, enum machine_mode mode, if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) op1 = XEXP (op0, 1), op0 = XEXP (op0, 0); - trueop0 = avoid_constant_pool_reference (op0); - trueop1 = avoid_constant_pool_reference (op1); - /* We can't simplify MODE_CC values since we don't know what the actual comparison is. */ if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC || CC0_P (op0)) return 0; /* Make sure the constant is second. */ - if (swap_commutative_operands_p (trueop0, trueop1)) + if (swap_commutative_operands_p (op0, op1)) { tem = op0, op0 = op1, op1 = tem; - tem = trueop0, trueop0 = trueop1, trueop1 = tem; code = swap_condition (code); } + trueop0 = avoid_constant_pool_reference (op0); + trueop1 = avoid_constant_pool_reference (op1); + /* For integer comparisons of A and B maybe we can simplify A - B and can then simplify a comparison of that with zero. If A and B are both either a register or a CONST_INT, this can't help; testing for these cases will