This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

combine simplify fix for alphaev4


Seen in a bootstrap:

A signed short int load looks like

	ldq_u	t1, mem
	lda	t2, addr+2
	extqh	t1, t2, t3
	sra	t3, 48, c

Where extqh is

        (ashift:DI
         (match_operand:DI 1 "reg_or_0_operand" "rJ")
          (minus:DI (const_int 64)
                    (ashift:DI
                     (and:DI
                      (match_operand:DI 2 "reg_or_8bit_operand" "rI")
                      (const_int 7))
                     (const_int 3))))

If the address has known alignment, such as we might get from the
frame pointer, then combine can simplify this instruction to

	(ashift:DI (reg:DI T1) (const_int N))

In this case, the address was 6 mod 8, so addr+2 is 0 mod 8, so
the N above is 64.

So now we have (ashift reg 64), which, since Alpha defines 
SHIFT_COUNT_TRUNCATED, is a noop.  But simplify_shift_const
refuses to simplify this case, even though it handles others.
This is the bug.

Back to the problem description, in trying to combine with
the following shift, we get (ashiftrt (ashift T1 64) 48)
which make_extraction simplifies to (ashift 16), which is
of course not what we wanted.

Bootstraped on alphaev4-linux.


r~


	* combine.c (simplify_shift_const): Move SHIFT_COUNT_TRUNCATED
	simplification above out of range check.

Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.242
diff -c -p -d -r1.242 combine.c
*** combine.c	2001/12/10 22:52:26	1.242
--- combine.c	2001/12/12 01:32:32
*************** merge_outer_ops (pop0, pconst0, op1, con
*** 8811,8825 ****
     are ASHIFTRT and ROTATE, which are always done in their original mode,  */
  
  static rtx
! simplify_shift_const (x, code, result_mode, varop, input_count)
       rtx x;
       enum rtx_code code;
       enum machine_mode result_mode;
       rtx varop;
!      int input_count;
  {
    enum rtx_code orig_code = code;
-   int orig_count = input_count;
    unsigned int count;
    int signed_count;
    enum machine_mode mode = result_mode;
--- 8811,8824 ----
     are ASHIFTRT and ROTATE, which are always done in their original mode,  */
  
  static rtx
! simplify_shift_const (x, code, result_mode, varop, orig_count)
       rtx x;
       enum rtx_code code;
       enum machine_mode result_mode;
       rtx varop;
!      int orig_count;
  {
    enum rtx_code orig_code = code;
    unsigned int count;
    int signed_count;
    enum machine_mode mode = result_mode;
*************** simplify_shift_const (x, code, result_mo
*** 8833,8858 ****
    int complement_p = 0;
    rtx new;
  
    /* If we were given an invalid count, don't do anything except exactly
       what was requested.  */
  
!   if (input_count < 0 || input_count >= (int) GET_MODE_BITSIZE (mode))
      {
        if (x)
  	return x;
  
!       return gen_rtx_fmt_ee (code, mode, varop, GEN_INT (input_count));
      }
  
!   count = input_count;
! 
!   /* Make sure and truncate the "natural" shift on the way in.  We don't
!      want to do this inside the loop as it makes it more difficult to
!      combine shifts.  */
! #ifdef SHIFT_COUNT_TRUNCATED
!   if (SHIFT_COUNT_TRUNCATED)
!     count %= GET_MODE_BITSIZE (mode);
! #endif
  
    /* Unless one of the branches of the `if' in this loop does a `continue',
       we will `break' the loop after the `if'.  */
--- 8832,8857 ----
    int complement_p = 0;
    rtx new;
  
+   /* Make sure and truncate the "natural" shift on the way in.  We don't
+      want to do this inside the loop as it makes it more difficult to
+      combine shifts.  */
+ #ifdef SHIFT_COUNT_TRUNCATED
+   if (SHIFT_COUNT_TRUNCATED)
+     orig_count &= GET_MODE_BITSIZE (mode) - 1;
+ #endif
+ 
    /* If we were given an invalid count, don't do anything except exactly
       what was requested.  */
  
!   if (orig_count < 0 || orig_count >= (int) GET_MODE_BITSIZE (mode))
      {
        if (x)
  	return x;
  
!       return gen_rtx_fmt_ee (code, mode, varop, GEN_INT (orig_count));
      }
  
!   count = orig_count;
  
    /* Unless one of the branches of the `if' in this loop does a `continue',
       we will `break' the loop after the `if'.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]