Fix for execute/990128-1.c -O2 failure on x86

Joern Rennecke amylaar@cygnus.co.uk
Tue Feb 2 15:35:00 GMT 1999


For this testcase, check_dbra_loop is called for this loop:

(note 16 82 22 "" NOTE_INSN_LOOP_BEG)

(code_label 22 16 23 6 "")

(note 23 22 24 ("/y/egcs/gcc/testsuite/gcc.c-torture/execute/990128-1.c") 21)

(note 24 23 25 "" NOTE_INSN_DELETED)

(insn 25 24 27 (set (reg:SI 25)
        (ashift:SI (reg/v:SI 24)
            (const_int 2))) -1 (nil)
    (nil))

(insn 27 25 29 (set (reg:SI 26)
        (plus:SI (reg:SI 25)
            (symbol_ref:SI ("sss")))) -1 (nil)
    (nil))

(insn 29 27 30 (set (mem/s:SI (reg/v:SI 23) 1)
        (reg:SI 26)) -1 (nil)
    (nil))

(note 30 29 32 ("/y/egcs/gcc/testsuite/gcc.c-torture/execute/990128-1.c") 22)

(insn 32 30 33 (set (reg/v:SI 23)
        (reg:SI 26)) -1 (nil)
    (nil))

(note 33 32 34 ("/y/egcs/gcc/testsuite/gcc.c-torture/execute/990128-1.c") 23)

(note 34 33 35 ("/y/egcs/gcc/testsuite/gcc.c-torture/execute/990128-1.c") 20)

(note 35 34 38 "" NOTE_INSN_LOOP_CONT)

(insn 38 35 85 (set (reg/v:SI 24)
        (plus:SI (reg/v:SI 24)
            (const_int 1))) -1 (nil)
    (nil))

(note 85 38 18 "" NOTE_INSN_LOOP_VTOP)

(insn 18 85 19 (set (cc0)
        (compare (reg/v:SI 24)
            (const_int 9))) -1 (nil)
    (nil))

(jump_insn 19 18 44 (set (pc)
        (if_then_else (le (cc0)
                (const_int 0))
            (label_ref 22)
            (pc))) -1 (nil)
    (nil))

(note 44 19 103 "" NOTE_INSN_LOOP_END)


Note that (reg/v:SI 23) is a giv that is used in insn 29, and then later
set in insn 32.  Thus, the store in insn 29 is not reversible.
Currently, check_dbra_loop thinks that it is, which results in an incorrect
loop reversal.  Here is a fix:

Sat Jan 30 03:24:37 1999  J"orn Rennecke <amylaar@cygnus.co.uk>

	* loop.c (first_loop_store_insn): New file-scope variable.
	(check_dbra_loop): Check if a store depends on a register
	that is set after the store.

Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.126
diff -p -r1.126 loop.c
*** loop.c	1999/02/02 13:38:56	1.126
--- loop.c	1999/02/02 23:27:24
*************** static char *moved_once;
*** 173,178 ****
--- 173,181 ----
  
  static rtx loop_store_mems;
  
+ /* The insn where the first of these was found.  */
+ static rtx first_loop_store_insn;
+ 
  typedef struct loop_mem_info {
    rtx mem;      /* The MEM itself.  */
    rtx reg;      /* Corresponding pseudo, if any.  */
*************** prescan_loop (start, end)
*** 2456,2461 ****
--- 2458,2465 ----
  	    loop_has_tablejump = 1;
  	  
  	  note_stores (PATTERN (insn), note_addr_stored);
+ 	  if (! first_loop_store_insn && loop_store_mems)
+ 	    first_loop_store_insn = insn;
  
  	  if (! loop_has_multiple_exit_targets
  	      && GET_CODE (insn) == JUMP_INSN
*************** check_dbra_loop (loop_end, insn_count, l
*** 7682,7690 ****
  	     case, the insn should have been moved out of the loop.  */
  
  	  if (num_mem_sets == 1)
! 	    reversible_mem_store
! 	      = (! unknown_address_altered
! 		 && ! invariant_p (XEXP (loop_store_mems, 0)));
  	}
        else
  	return 0;
--- 7686,7711 ----
  	     case, the insn should have been moved out of the loop.  */
  
  	  if (num_mem_sets == 1)
! 	    {
! 	      struct induction *v;
! 
! 	      reversible_mem_store
! 		= (! unknown_address_altered
! 		   && ! invariant_p (XEXP (loop_store_mems, 0)));
! 
! 	      /* If the store depends on a register that is set after the
! 		 store, it depends on the initial value, and is thus not
! 		 reversible.  */
! 	      for (v = bl->giv; reversible_mem_store && v; v = v->next_iv)
! 		{
! 		  if (v->giv_type == DEST_REG
! 		      && reg_mentioned_p (v->dest_reg,
! 					  XEXP (loop_store_mems, 0))
! 		      && (INSN_LUID (v->insn)
! 			  > INSN_LUID (first_loop_store_insn)))
! 		    reversible_mem_store = 0;
! 		}
! 	    }
  	}
        else
  	return 0;


More information about the Gcc-patches mailing list