Patch to fix mark_constant_function

John Wehle john@feith.com
Thu Sep 21 14:47:00 GMT 2000


This patch fixes mark_constant_function which has been busted since
a change on 2000-02-18.  It also addresses a long standing issue
where recursive functions and functions with loops were considered
as constant function candidates ... several people pointed out that
this is undesirable since the function might never return which counts
as a side effect.  This patch passes make bootstrap and make check on
IBM AIX 4.3, Solaris 7 SPARC, and Compaq Tru64 UNIX 4.0f.

ChangeLog:

Thu Sep 21 02:41:10 EDT 2000  John Wehle  (john@feith.com)

	* alias.c: Include basic-block.h.
	(loop_p): New function.
	(mark_constant_function): Use it.  Don't check pure functions.
	Initialize and end alias analysis.
	(nonlocal_mentioned_p): Rename from nonlocal_reference_p.
	Don't make a special exception for recursion.  Handle
	UNSPEC_VOLATILE.  Don't assume ASM_OPERANDS is non-local
	unless it's volatile.
	* Makefile.in (alias.o): Update dependencies.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/alias.c.ORIGINAL	Wed Sep 20 22:16:27 2000
--- gcc/alias.c	Thu Sep 21 03:03:33 2000
*************** Boston, MA 02111-1307, USA.  */
*** 29,34 ****
--- 29,35 ----
  #include "expr.h"
  #include "regs.h"
  #include "hard-reg-set.h"
+ #include "basic-block.h"
  #include "flags.h"
  #include "output.h"
  #include "toplev.h"
*************** static rtx fixed_scalar_and_varying_stru
*** 103,109 ****
  						      int (*) (rtx)));
  static int aliases_everything_p         PARAMS ((rtx));
  static int write_dependence_p           PARAMS ((rtx, rtx, int));
! static int nonlocal_reference_p         PARAMS ((rtx));
  
  /* Set up all info needed to perform alias analysis on memory references.  */
  
--- 104,112 ----
  						      int (*) (rtx)));
  static int aliases_everything_p         PARAMS ((rtx));
  static int write_dependence_p           PARAMS ((rtx, rtx, int));
! static int nonlocal_mentioned_p         PARAMS ((rtx));
! 
! static int loop_p                       PARAMS ((void));
  
  /* Set up all info needed to perform alias analysis on memory references.  */
  
*************** output_dependence (mem, x)
*** 1725,1735 ****
    return write_dependence_p (mem, x, /*writep=*/1);
  }
  
! /* Returns non-zero if X might refer to something which is not
     local to the function and is not constant.  */
  
  static int
! nonlocal_reference_p (x)
       rtx x;
  {
    rtx base;
--- 1728,1738 ----
    return write_dependence_p (mem, x, /*writep=*/1);
  }
  
! /* Returns non-zero if X mentions something which is not
     local to the function and is not constant.  */
  
  static int
! nonlocal_mentioned_p (x)
       rtx x;
  {
    rtx base;
*************** nonlocal_reference_p (x)
*** 1789,1801 ****
        return 1;
  
      case CALL:
!       /* Recursion introduces no additional considerations.  */
!       if (GET_CODE (XEXP (x, 0)) == MEM
! 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
! 	  && strcmp(XSTR (XEXP (XEXP (x, 0), 0), 0),
! 		    IDENTIFIER_POINTER (
! 			  DECL_ASSEMBLER_NAME (current_function_decl))) == 0)
! 	return 0;
        return 1;
  
      case MEM:
--- 1792,1798 ----
        return 1;
  
      case CALL:
!       /* Non-constant calls and recursion are not local.  */
        return 1;
  
      case MEM:
*************** nonlocal_reference_p (x)
*** 1826,1835 ****
  	}
        return 1;
  
      case ASM_INPUT:
-     case ASM_OPERANDS:
        return 1;
  
      default:
        break;
      }
--- 1823,1838 ----
  	}
        return 1;
  
+     case UNSPEC_VOLATILE:
      case ASM_INPUT:
        return 1;
  
+     case ASM_OPERANDS:
+       if (MEM_VOLATILE_P (x))
+ 	return 1;
+ 
+     /* FALLTHROUGH */
+ 
      default:
        break;
      }
*************** nonlocal_reference_p (x)
*** 1844,1857 ****
        {
  	if (fmt[i] == 'e' && XEXP (x, i))
  	  {
! 	    if (nonlocal_reference_p (XEXP (x, i)))
  	      return 1;
  	  }
  	else if (fmt[i] == 'E')
  	  {
  	    register int j;
  	    for (j = 0; j < XVECLEN (x, i); j++)
! 	      if (nonlocal_reference_p (XVECEXP (x, i, j)))
  		return 1;
  	  }
        }
--- 1847,1860 ----
        {
  	if (fmt[i] == 'e' && XEXP (x, i))
  	  {
! 	    if (nonlocal_mentioned_p (XEXP (x, i)))
  	      return 1;
  	  }
  	else if (fmt[i] == 'E')
  	  {
  	    register int j;
  	    for (j = 0; j < XVECLEN (x, i); j++)
! 	      if (nonlocal_mentioned_p (XVECEXP (x, i, j)))
  		return 1;
  	  }
        }
*************** nonlocal_reference_p (x)
*** 1860,1887 ****
    return 0;
  }
  
  /* Mark the function if it is constant.  */
  
  void
  mark_constant_function ()
  {
    rtx insn;
  
    if (TREE_PUBLIC (current_function_decl)
        || TREE_READONLY (current_function_decl)
        || TREE_THIS_VOLATILE (current_function_decl)
        || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode)
      return;
  
    /* Determine if this is a constant function.  */
  
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
!     if (INSN_P (insn) && nonlocal_reference_p (insn))
!       return;
  
    /* Mark the function.  */
  
!   TREE_READONLY (current_function_decl) = 1;
  }
  
  
--- 1863,1953 ----
    return 0;
  }
  
+ /* Return non-zero if a loop (natural or otherwise) is present.  */
+ 
+ static int
+ loop_p ()
+ {
+   int changed;
+   int loop_present;
+   int i;
+   edge e;
+   sbitmap *bb_successors;
+   sbitmap successors;
+ 
+   bb_successors
+     = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
+   successors = sbitmap_alloc (n_basic_blocks);
+ 
+   sbitmap_vector_zero (bb_successors, n_basic_blocks);
+ 
+   for (i = 0; i < n_basic_blocks; i++)
+     for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
+       if (e->dest != EXIT_BLOCK_PTR)
+ 	SET_BIT (bb_successors[i], e->dest->index);
+ 
+   changed = 1;
+   loop_present = 0;
+   while (changed && ! loop_present)
+     {
+       changed = 0;
+       for (i = 0; i < n_basic_blocks; i++)
+ 	{
+ 	  sbitmap_union_of_succs (successors, bb_successors, i);
+ 	  if (TEST_BIT (successors, i))
+ 	    {
+ 	      loop_present = 1;
+ 	      break;
+ 	    }
+ 	  changed |= sbitmap_a_or_b (bb_successors[i], bb_successors[i],
+ 				     successors);
+ 	}
+     }
+ 
+   sbitmap_vector_free (bb_successors);
+   free (successors);
+ 
+   return loop_present;
+ }
+ 
  /* Mark the function if it is constant.  */
  
  void
  mark_constant_function ()
  {
    rtx insn;
+   int nonlocal_mentioned;
  
    if (TREE_PUBLIC (current_function_decl)
        || TREE_READONLY (current_function_decl)
+       || DECL_IS_PURE (current_function_decl)
        || TREE_THIS_VOLATILE (current_function_decl)
        || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode)
      return;
  
+   /* A loop might not return which counts as a side effect.  */
+   if (loop_p ())
+     return;
+ 
+   nonlocal_mentioned = 0;
+ 
+   init_alias_analysis ();
+ 
    /* Determine if this is a constant function.  */
  
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
!     if (INSN_P (insn) && nonlocal_mentioned_p (insn))
!       {
! 	nonlocal_mentioned = 1;
! 	break;
!       }
! 
!   end_alias_analysis ();
  
    /* Mark the function.  */
  
!   if (! nonlocal_mentioned)
!     TREE_READONLY (current_function_decl) = 1;
  }
  
  
*** gcc/Makefile.in.ORIGINAL	Thu Sep 14 23:22:46 2000
--- gcc/Makefile.in	Thu Sep 21 02:36:46 2000
*************** reorg.o : reorg.c $(CONFIG_H) system.h $
*** 1373,1380 ****
     $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(INSN_ATTR_H) insn-flags.h \
     $(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h
  alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
!    $(REGS_H) toplev.h output.h $(EXPR_H) insn-flags.h $(GGC_H) function.h \
!    cselib.h $(TREE_H)
  regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
     $(RECOG_H) output.h $(REGS_H) hard-reg-set.h flags.h function.h \
     $(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
--- 1373,1380 ----
     $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(INSN_ATTR_H) insn-flags.h \
     $(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h
  alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
!    $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h $(EXPR_H) insn-flags.h \
!    $(GGC_H) function.h cselib.h $(TREE_H)
  regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
     $(RECOG_H) output.h $(REGS_H) hard-reg-set.h flags.h function.h \
     $(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------



More information about the Gcc-patches mailing list