]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR rtl-optimization/22563 (performance regression for gcc newer than 2.95)
authorRoger Sayle <roger@eyesopen.com>
Tue, 16 May 2006 01:17:13 +0000 (01:17 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Tue, 16 May 2006 01:17:13 +0000 (01:17 +0000)
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

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/config/i386/predicates.md
gcc/expmed.c

index 9e15740847293b68e83ffad34cc1afc0c16bf91f..bcf3002df8682edb7a80ff76d0a7c939e22a2184 100644 (file)
@@ -1,3 +1,16 @@
+2006-05-15  Roger Sayle  <roger@eyesopen.com>
+
+       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  <roger@eyesopen.com>
 
        PR middle-end/26729
index 263c0d343e5f3f37daa9ad258a2ccaff716cd990..49346adbd1e918556213700f4f10f47576b145bd 100644 (file)
 (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.  */
 (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.  */
 
 (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;
 
index 3d1930f74838eaed20f06404933029391b8a3001..29456cdb8878216063c1265dbdde92d9553892ef 100644 (file)
   (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")
index db957dff31d2d01ed2ec6a16b1807ea8081702b9..a1e3d9529cc446fb80d62eef948f0eef9d0927ac 100644 (file)
@@ -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);
 }