patch for ia64 epilogue scheduling bug

Jim Wilson wilson@cygnus.com
Thu Mar 23 11:41:00 GMT 2000


This fixes a bug where the predicate register restores in the epilogue could
be moved before the last use of predicate registers in the function.  The
particular example that found the problem had a conditional expression as
the return value.

Thu Mar 23 11:34:39 2000  Jim Wilson  <wilson@cygnus.com>

	* config/ia64/ia64.c (rtx_needs_barrier, case UNSPEC): Move case 6...
	(rtx_needs_barrier, case UNSPEC_VOLATILE): to here.
	* config/ia64/ia64.md (pr_restore): Change UNSPEC to UNSPEC_VOLATILE.

Index: ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.6
diff -p -r1.6 ia64.c
*** ia64.c	2000/03/21 04:05:49	1.6
--- ia64.c	2000/03/23 19:34:02
*************** rtx_needs_barrier (x, flags, pred)
*** 2421,2436 ****
  	    need_barrier |= rws_access_reg (i, flags, pred);
  	  break;
  
! 	case 6: /* mov pr= */
! 	  /* This writes all predicate registers.  */
! 	  new_flags.is_write = 1;
! 	  /* We need to skip by two, because rws_access_reg always writes
! 	     to two predicate registers at a time.  */
! 	  /* ??? Strictly speaking, we shouldn't be counting writes to pr0.  */
! 	  for (i = PR_REG (0); i < PR_REG (64); i += 2)
! 	    need_barrier |= rws_access_reg (i, new_flags, pred);
! 	  break;
! 
  	case 7:
  	  abort ();
  
--- 2421,2427 ----
  	    need_barrier |= rws_access_reg (i, flags, pred);
  	  break;
  
! 	case 6:
  	case 7:
  	  abort ();
  
*************** rtx_needs_barrier (x, flags, pred)
*** 2484,2489 ****
--- 2475,2490 ----
  	case 4: /* mov ar.pfs= */
  	  new_flags.is_write = 1;
  	  need_barrier = rws_access_reg (REG_AR_PFS, new_flags, pred);
+ 	  break;
+ 
+ 	case 6: /* mov pr= */
+ 	  /* This writes all predicate registers.  */
+ 	  new_flags.is_write = 1;
+ 	  /* We need to skip by two, because rws_access_reg always writes
+ 	     to two predicate registers at a time.  */
+ 	  /* ??? Strictly speaking, we shouldn't be counting writes to pr0.  */
+ 	  for (i = PR_REG (0); i < PR_REG (64); i += 2)
+ 	    need_barrier |= rws_access_reg (i, new_flags, pred);
  	  break;
  
  	default:
Index: ia64.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.md,v
retrieving revision 1.5
diff -p -r1.5 ia64.md
*** ia64.md	2000/03/17 20:22:18	1.5
--- ia64.md	2000/03/23 19:34:02
***************
*** 3049,3056 ****
    "mov %0 = pr"
    [(set_attr "type" "I")])
  
  (define_insn "pr_restore"
!   [(unspec [(const_int 0)] 6)
     (use (match_operand:DI 0 "register_operand" "r"))]
    ""
    "mov pr = %0, -1"
--- 3049,3059 ----
    "mov %0 = pr"
    [(set_attr "type" "I")])
  
+ ;; ??? This is volatile to prevent it from being moved before a conditional
+ ;; expression that calculates the return value.
+ 
  (define_insn "pr_restore"
!   [(unspec_volatile [(const_int 0)] 6)
     (use (match_operand:DI 0 "register_operand" "r"))]
    ""
    "mov pr = %0, -1"


More information about the Gcc-patches mailing list