2007-06-26 Jakub Jelinek * defaults.h (TARGET_INDEX_OPERAND_FIRST): Define. * config/rs6000/rs6000.h (TARGET_INDEX_OPERAND_FIRST): Define. * optabs.c (emit_cmp_and_jump_insns): Don't call swap_operand twice. * rtlanal.c (commutative_operand_precedence): Only prefer REG_POINTER and MEM_POINTER operands over REG and MEM operands if TARGET_INDEX_OPERAND_FIRST. (swap_commutative_operands_p): Only sort on REGNO if TARGET_INDEX_OPERAND_FIRST. * tree-ssa-address.c (gen_addr_rtx): Only use simplify_gen_binary instead of gen_rtx_PLUS if TARGET_INDEX_OPERAND_FIRST. 2007-06-20 Peter Bergner PR middle-end/28690 * optabs.c (emit_cmp_and_jump_insns): Allow EQ compares. * rtlanal.c (commutative_operand_precedence): Prefer both REG_POINTER and MEM_POINTER operands over REG and MEM operands. (swap_commutative_operands_p): In case of a tie, sort on REGNO. * tree-ssa-address.c (gen_addr_rtx): Use simplify_gen_binary instead of gen_rtx_PLUS. --- gcc/defaults.h.jj 2007-02-20 22:39:12.000000000 +0100 +++ gcc/defaults.h 2007-06-26 00:32:16.000000000 +0200 @@ -785,6 +785,10 @@ Software Foundation, 51 Franklin Street, #define TARGET_C99_FUNCTIONS 0 #endif +#ifndef TARGET_INDEX_OPERAND_FIRST +#define TARGET_INDEX_OPERAND_FIRST 0 +#endif + /* Indicate that CLZ and CTZ are undefined at zero. */ #ifndef CLZ_DEFINED_VALUE_AT_ZERO #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) 0 --- gcc/config/rs6000/rs6000.h.jj 2007-02-20 22:39:00.000000000 +0100 +++ gcc/config/rs6000/rs6000.h 2007-06-26 00:33:32.000000000 +0200 @@ -57,6 +57,8 @@ #define PPC405_ERRATUM77 0 #endif +#define TARGET_INDEX_OPERAND_FIRST (rs6000_cpu == PROCESSOR_POWER6) + /* Common ASM definitions used by ASM_SPEC among the various targets for handling -mcpu=xxx switches. */ #define ASM_CPU_SPEC \ --- gcc/optabs.c.jj 2007-02-20 22:39:12.000000000 +0100 +++ gcc/optabs.c 2007-06-26 00:30:27.000000000 +0200 @@ -3673,12 +3673,16 @@ emit_cmp_and_jump_insns (rtx x, rtx y, e /* Swap operands and condition to ensure canonical RTL. */ if (swap_commutative_operands_p (x, y)) { - /* If we're not emitting a branch, this means some caller - is out of sync. */ - gcc_assert (label); + enum rtx_code swapped_comparison = swap_condition (comparison); + + /* If we're not emitting a branch, callers are required to pass + operands in an order conforming to canonical RTL. We relax this + for commutative comparsions so callers using EQ don't need to do + swapping by hand. */ + gcc_assert (label || swapped_comparison == comparison); op0 = y, op1 = x; - comparison = swap_condition (comparison); + comparison = swapped_comparison; } #ifdef HAVE_cc0 --- gcc/rtlanal.c.jj 2007-02-20 22:39:12.000000000 +0100 +++ gcc/rtlanal.c 2007-06-26 00:28:56.000000000 +0200 @@ -2890,9 +2890,9 @@ commutative_operand_precedence (rtx op) /* Constants always come the second operand. Prefer "nice" constants. */ if (code == CONST_INT) - return -7; + return -10; if (code == CONST_DOUBLE) - return -6; + return -9; op = avoid_constant_pool_reference (op); code = GET_CODE (op); @@ -2900,26 +2900,31 @@ commutative_operand_precedence (rtx op) { case RTX_CONST_OBJ: if (code == CONST_INT) - return -5; + return -8; if (code == CONST_DOUBLE) - return -4; - return -3; + return -7; + return -6; case RTX_EXTRA: /* SUBREGs of objects should come second. */ if (code == SUBREG && OBJECT_P (SUBREG_REG (op))) - return -2; + return -5; if (!CONSTANT_P (op)) return 0; else /* As for RTX_CONST_OBJ. */ - return -3; + return -6; case RTX_OBJ: /* Complex expressions should be the first, so decrease priority of objects. */ - return -1; + if (!TARGET_INDEX_OPERAND_FIRST) + return -1; + if (REG_P (op)) + return (REG_POINTER (op)) ? -1 : -3; + else + return (MEM_P (op) && MEM_POINTER (op)) ? -2 : -4; case RTX_COMM_ARITH: /* Prefer operands that are themselves commutative to be first. @@ -2949,8 +2954,16 @@ commutative_operand_precedence (rtx op) int swap_commutative_operands_p (rtx x, rtx y) { - return (commutative_operand_precedence (x) - < commutative_operand_precedence (y)); + int result = (commutative_operand_precedence (x) + - commutative_operand_precedence (y)); + if (!TARGET_INDEX_OPERAND_FIRST || result) + return result < 0; + + /* Group together equal REGs to do more simplification. */ + if (REG_P (x) && REG_P (y)) + return REGNO (x) > REGNO (y); + + return 0; } /* Return 1 if X is an autoincrement side effect and the register is --- gcc/tree-ssa-address.c.jj 2007-02-20 22:39:12.000000000 +0100 +++ gcc/tree-ssa-address.c 2007-06-26 00:29:49.000000000 +0200 @@ -124,7 +124,9 @@ gen_addr_rtx (rtx symbol, rtx base, rtx if (base) { if (*addr) - *addr = gen_rtx_PLUS (Pmode, *addr, base); + *addr = (TARGET_INDEX_OPERAND_FIRST + ? simplify_gen_binary (PLUS, Pmode, base, *addr) + : gen_rtx_PLUS (Pmode, *addr, base)); else *addr = base; }