From: Roger Sayle Date: Tue, 16 May 2006 01:17:13 +0000 (+0000) Subject: re PR rtl-optimization/22563 (performance regression for gcc newer than 2.95) X-Git-Tag: releases/gcc-4.0.4~685 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d028573f38f52340f47efde0fc519806ad829511;p=thirdparty%2Fgcc.git re PR rtl-optimization/22563 (performance regression for gcc newer than 2.95) PR rtl-optimization/22563 Backports from mainline * expmed.c (store_fixed_bit_field): When using AND and IOR to store a fixed width bitfield, always force the intermediates into pseudos. Also check whether the bitsize is valid for the machine's "insv" instruction before moving the target into a pseudo for use with the insv. * config/i386/predicates.md (const8_operand): New predicate. * config/i386/i386.md (extv, extzv, insv): Use the new const8_operand predicate where appropriate. From-SVN: r113810 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e1574084729..bcf3002df868 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2006-05-15 Roger Sayle + + PR rtl-optimization/22563 + Backports from mainline + * expmed.c (store_fixed_bit_field): When using AND and IOR to store + a fixed width bitfield, always force the intermediates into pseudos. + Also check whether the bitsize is valid for the machine's "insv" + instruction before moving the target into a pseudo for use with + the insv. + * config/i386/predicates.md (const8_operand): New predicate. + * config/i386/i386.md (extv, extzv, insv): Use the new + const8_operand predicate where appropriate. + 2006-05-15 Roger Sayle PR middle-end/26729 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 263c0d343e5f..49346adbd1e9 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -12136,8 +12136,8 @@ (define_expand "extv" [(set (match_operand:SI 0 "register_operand" "") (sign_extract:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + (match_operand:SI 2 "const8_operand" "") + (match_operand:SI 3 "const8_operand" "")))] "" { /* Handle extractions from %ah et al. */ @@ -12153,8 +12153,8 @@ (define_expand "extzv" [(set (match_operand:SI 0 "register_operand" "") (zero_extract:SI (match_operand 1 "ext_register_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + (match_operand:SI 2 "const8_operand" "") + (match_operand:SI 3 "const8_operand" "")))] "" { /* Handle extractions from %ah et al. */ @@ -12169,12 +12169,12 @@ (define_expand "insv" [(set (zero_extract (match_operand 0 "ext_register_operand" "") - (match_operand 1 "immediate_operand" "") - (match_operand 2 "immediate_operand" "")) + (match_operand 1 "const8_operand" "") + (match_operand 2 "const8_operand" "")) (match_operand 3 "register_operand" ""))] "" { - /* Handle extractions from %ah et al. */ + /* Handle insertions to %ah et al. */ if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8) FAIL; diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 3d1930f74838..29456cdb8878 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -501,6 +501,11 @@ (and (match_code "const_int") (match_test "op == const1_rtx"))) +;; Match exactly eight. +(define_predicate "const8_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) == 8"))) + ;; Match 2, 4, or 8. Used for leal multiplicands. (define_predicate "const248_operand" (match_code "const_int") diff --git a/gcc/expmed.c b/gcc/expmed.c index db957dff31d2..a1e3d9529cc4 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -1,7 +1,8 @@ /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -616,7 +617,9 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* Ensure insv's size is wide enough for this field. */ && (GET_MODE_BITSIZE (op_mode) >= bitsize) && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG) - && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode)))) + && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))) + && insn_data[CODE_FOR_insv].operand[1].predicate (GEN_INT (bitsize), + VOIDmode)) { int xbitpos = bitpos; rtx value1; @@ -773,7 +776,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, { enum machine_mode mode; unsigned int total_bits = BITS_PER_WORD; - rtx subtarget, temp; + rtx temp; int all_zero = 0; int all_one = 0; @@ -899,24 +902,28 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, /* Now clear the chosen bits in OP0, except that if VALUE is -1 we need not bother. */ + /* We keep the intermediates in registers to allow CSE to combine + consecutive bitfield assignments. */ - subtarget = (REG_P (op0) || ! flag_force_mem) ? op0 : 0; + temp = force_reg (mode, op0); if (! all_one) { - temp = expand_binop (mode, and_optab, op0, + temp = expand_binop (mode, and_optab, temp, mask_rtx (mode, bitpos, bitsize, 1), - subtarget, 1, OPTAB_LIB_WIDEN); - subtarget = temp; + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = force_reg (mode, temp); } - else - temp = op0; /* Now logical-or VALUE into OP0, unless it is zero. */ if (! all_zero) - temp = expand_binop (mode, ior_optab, temp, value, - subtarget, 1, OPTAB_LIB_WIDEN); + { + temp = expand_binop (mode, ior_optab, temp, value, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = force_reg (mode, temp); + } + if (op0 != temp) emit_move_insn (op0, temp); }