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]

[RFC] Toplev.c reorganization


Hello,

after discussing it with Honza Hubicka, I have written the following
attempt to reorganize toplev.c. It has the following goals:

1) Make it easier to change order of passes, by building/updating
   automatically the requiered structures and verifying prerequisites.
   The final state should be that any ordering of passes would either
   work or say you why it is impossible.
2) Decrease the number of unnecessary rebuilds of structures, by keeping
   track of those that are up-to-date.
3) Perhaps also make things better organized.

Out of these goals, 1) is surely not fulfilled at all in current state,
and I am very far from reaching it. For 2) you may see the impact on
compilation speed and number of updates of some key structures in
attached results (gcc_rtl is with patch, gcc_rtl_comp without it, both
based on rtlopt-branch).

Any comments are welcome, especially things like "I don't like your evil
macros, you should do it in this clear and elegant way...", or "This
will break things if ULTRA_WEIRD_MACHINE is defined" :-)  (or "Throw
it away, it will never get into mainline while I am alive" -- better
to hear it now while I haven't spent too much time with it).

While the code seems to be in relatively good shape just now (it passes
bootstrap & regtesting on i686), I am not going to commit it to
rtlopt-branch for few following weeks so that it does not interfere
with merge.

Zdenek

Attachment: yyy-O0
Description: Text document

Attachment: yyy-O1
Description: Text document

Attachment: yyy-O2
Description: Text document

Attachment: yyy-O3
Description: Text document

Attachment: diff_toplev_cleanup.diff
Description: Text document

Attachment: passes.def
Description: Text document

/* passes.c -- definitions of passes and internal structures of gcc.
   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

*/

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "toplev.h"

/* Requiered because of actions.  */
#include "rtl.h"
#include "regs.h"
#include "basic-block.h"
#include "except.h"
#include "output.h"
#include "timevar.h"
#include "ssa.h"
#include "cfgloop.h"
#include "gcse-globals.h"
#include "flags.h"
#include "vpt.h"
#include "ggc.h"
#include "insn-config.h"
#include "reload.h"
#include "integrate.h"
#include "recog.h"

#include "passes.h"


/* Structure state names.  */
const char *str_state_name[SS_MAX] =
{
  "NONE",
  "DIRTY",
  "OK"
};

/* Names of structures.  */
const char *structure_name[STR_MAX] =
{
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  NAME,
#include "structures.def"
};

/* Types of structures.  */
enum str_type structure_type[STR_MAX] =
{
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  ST_##TYPE,
#include "structures.def"
};

/* Structure states.  */
enum str_state structure_state[STR_MAX];

/* Prototypes for helper functions.  */
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  static bool create_structure_##ID##_helper PARAMS ((void));	\
  static bool update_structure_##ID##_helper PARAMS ((void));	\
  static bool destroy_structure_##ID##_helper PARAMS ((void));
#include "structures.def"

/* The helper and manipulation functions.  */
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
static bool							\
create_structure_##ID##_helper ()				\
{								\
  CREATE							\
}								\
								\
static bool							\
update_structure_##ID##_helper ()				\
{								\
  UPDATE							\
}								\
								\
static bool							\
destroy_structure_##ID##_helper ()				\
{								\
  DESTROY							\
}								\
								\
void								\
preserve_implied_structures_##ID ()				\
{								\
  IMPLIES							\
}								\
								\
bool								\
create_structure_##ID ()					\
{								\
  bool ret;							\
								\
  ASSERT_STRUCTURE (ID, NONE);					\
  ret = create_structure_##ID##_helper ();			\
  if (ret)							\
    FORCE_STRUCTURE (ID, OK);					\
  return ret;							\
}								\
								\
bool								\
update_structure_##ID ()					\
{								\
  bool ret;							\
								\
  ASSERT_STRUCTURE (ID, DIRTY);					\
  ret = update_structure_##ID##_helper ();			\
  if (ret)							\
    FORCE_STRUCTURE (ID, OK);					\
  return ret;							\
}								\
								\
bool								\
destroy_structure_##ID ()					\
{								\
  bool ret;							\
								\
  if (STATE_OF_STRUCTURE (ID) == SS_NONE)			\
    {								\
      error ("State of %s is expected not to be %s.",		\
	     structure_name[STR_##ID],				\
	     str_state_name[SS_NONE]);				\
      abort ();							\
    }								\
  ret = destroy_structure_##ID##_helper ();			\
  if (ret)							\
    FORCE_STRUCTURE (ID, NONE);					\
  return ret;							\
}
#include "structures.def"

/* Initialize states of all structures.  */
void
init_structure_states ()
{
  if (dump_structure_manipulations)
    fprintf (stderr, "Starting tracking structures\n");
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  FORCE_STRUCTURE (ID, INIT);
#include "structures.def"
}

/* Release all dirty structures.  */
void
release_dirty_structures ()
{
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  if (STATE_OF_STRUCTURE (ID) == SS_DIRTY)			\
    destroy_structure_##ID ();
#include "structures.def"
}

/* Finalize all structures.  */
void
finish_structures ()
{
  /* Create structures that are requiered to be up-to-date.  */
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  if (SS_##FINAL == SS_OK)					\
    REQ_STRUCTURE (ID, OK);
#include "structures.def"

  /* Destroy the structures that are requiered to be finished.  Do it in
     a separate pass, so that we do not recreate the destroyed structures.  */
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  if (SS_##FINAL == SS_NONE)					\
    REQ_STRUCTURE (ID, NONE);
#include "structures.def"
  if (dump_structure_manipulations)
    fprintf (stderr, "Stopping tracking structures\n\n");
}

/* The pass manipulation functions.  */

/* Current pass name.  */
const char *current_pass;

/* Structures preserved by pass.  */
int pass_preserves[STR_MAX];
int pass_preserves_all;

/* Updates states of the structures according to list of preserved ones.  */
void
update_structures (preserves, preserves_all)
     int preserves[STR_MAX];
     int preserves_all;
{
  enum structures id;

  if (preserves_all)
    return;
  
  for (id = 0; id < STR_MAX; id++)
    {
      if (preserves[id] || structure_type[id] == ST_DURABLE)
	continue;

      if (structure_state[id] == SS_OK)
	{
	  REPORT ("made dirty", structure_name[id]);
	  structure_state[id] = SS_DIRTY;
	}
    }
}

/* The prototypes for generated functions:  */

#undef DEF_PASS
#define DEF_PASS(ID, NAME, DESC, PARS, NPARS, HEADER, TYPE, VALUE, INIT, DONE, RUN) \
static TYPE run_pass_##ID##_helper PARAMS (PARS);
#include "passes.def"

/* The generated functions:  */

#undef DEF_PASS
#define DEF_PASS(ID, NAME, DESC, PARS, NPARS, HEADER, TYPE, VALUE, INIT, DONE, RUN) \
void								\
initialize_pass_##ID NPARS					\
HEADER								\
{								\
  INIT								\
}								\
								\
TYPE pass_##ID##_return_value_temp;				\
void								\
finalize_pass_##ID NPARS					\
HEADER								\
{								\
  TYPE VALUE;							\
  VALUE = pass_##ID##_return_value_temp;			\
  DONE								\
}								\
								\
static TYPE							\
run_pass_##ID##_helper NPARS					\
HEADER								\
{								\
  RUN								\
}								\
								\
TYPE								\
run_pass_##ID NPARS						\
HEADER								\
{								\
  int pass_preserves[STR_MAX];					\
  int pass_preserves_all = 0;					\
  TYPE VALUE;							\
  const char *old_pass = current_pass;				\
  current_pass = NAME;						\
  memset (pass_preserves, 0, sizeof (pass_preserves));		\
								\
  INIT								\
  VALUE = run_pass_##ID##_helper NPARS;				\
  DONE								\
  update_structures (pass_preserves, pass_preserves_all);	\
								\
  current_pass = old_pass;					\
  return VALUE;							\
}
#include "passes.def"
/* passes.h -- definitions of passes and internal structures of gcc.
   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

*/

/* Structures:  */

/* Generate prototypes for structure manipulation functions.  */
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  void preserve_implied_structures_##ID PARAMS ((void));	\
  bool create_structure_##ID PARAMS ((void));			\
  bool update_structure_##ID PARAMS ((void));			\
  bool destroy_structure_##ID PARAMS ((void));
#include "structures.def"

/* Enumeration of possible structure states.  */
enum str_state
{
  SS_NONE,	/* Does not exist.  */
  SS_DIRTY,	/* The structure is here, but needs to be updated.  */
  SS_OK,	/* The structure is ready.  */
  SS_MAX
};

/* Their names.  */
extern const char *str_state_name[SS_MAX];

/* Type of structure.  */
enum str_type
{
  ST_FRAGILE,
  ST_DURABLE
};

/* Enumeration of all structures.  */
enum structures
{
#undef DEF_STRUCTURE
#define DEF_STRUCTURE(ID, NAME, DESC, INIT, FINAL, TYPE, IMPLIES, CREATE, UPDATE, DESTROY) \
  STR_##ID,
#include "structures.def"
  STR_MAX
};

/* Their names.  */
extern const char *structure_name[STR_MAX];

/* And types.  */
extern enum str_type structure_type[STR_MAX];

/* Structure states are stored here.  */
extern enum str_state structure_state[STR_MAX];

/* Structure manipulation macros, for description see structures.def.  */
#define STATE_OF_STRUCTURE(ID)					\
  structure_state[STR_##ID]

#define ASSERT_STRUCTURE(ID, STATE)				\
  do								\
    {								\
      if (STATE_OF_STRUCTURE (ID) != SS_##STATE)		\
	{							\
	  error ("State of %s is expected to be %s.",		\
		 structure_name[STR_##ID],			\
		 str_state_name[SS_##STATE]);			\
	  abort ();						\
	}							\
    }								\
  while (0)

#define FORCE_STRUCTURE(ID, STATE)				\
  do								\
    {								\
      if (SS_DIRTY != SS_##STATE				\
	  || STATE_OF_STRUCTURE (ID) != SS_NONE)		\
	{							\
	  if (SS_##STATE == SS_NONE)				\
	    REPORT ("forced none", structure_name[STR_##ID]);	\
	  if (SS_##STATE == SS_DIRTY)				\
	    REPORT ("forced dirty", structure_name[STR_##ID]);	\
	  if (SS_##STATE == SS_OK)				\
	    REPORT ("forced ok", structure_name[STR_##ID]);	\
	  STATE_OF_STRUCTURE (ID) = SS_##STATE;			\
	}							\
    }								\
  while (0)

#define REPORT(EVENT, STR)					\
  do								\
    {								\
      if (!dump_structure_manipulations)			\
	break;							\
      fprintf (stderr, "%s %s due to ", EVENT, STR);		\
      if (current_pass)						\
	fprintf(stderr,"%s\n", current_pass);			\
      else							\
	fprintf(stderr,"%s:%d\n", __FILE__, __LINE__);		\
    } while (0)

#define REQ_STRUCTURE(ID, STATE)				\
  do								\
    {								\
      enum str_state state = SS_##STATE;			\
      enum structures id = STR_##ID;				\
      const char *str_name = structure_name[id];		\
								\
      if (state == SS_DIRTY)					\
	{							\
	  error ("Requested to bring %s into %s state.",	\
		 str_name, str_state_name[SS_DIRTY]);		\
	  abort ();						\
	}							\
      if (structure_state[id] == state)				\
	break;							\
								\
      if (state == SS_NONE)					\
	{							\
	  if (destroy_structure_##ID ())			\
	    {							\
	      REPORT ("destroyed", str_name);			\
	      break;						\
	    }							\
	  error ("Failed to destroy %s.", str_name);		\
	  abort ();						\
	}							\
								\
      if (state != SS_OK)					\
	abort ();  /* Just for sure.  */			\
      if (structure_state[id] == SS_DIRTY)			\
	{							\
	  if (update_structure_##ID ())				\
	    {							\
	      REPORT ("updated", str_name);			\
	      break;						\
	    }							\
	  if (!destroy_structure_##ID ())			\
	    {							\
	      error ("Failed to update %s.", str_name);		\
	      abort ();						\
	    }							\
	  REPORT ("destroyed", str_name);			\
	}							\
      if (structure_state[id] != SS_NONE)			\
	{							\
	  error ("Information about state of %s is inconsistent.", \
		 str_name);					\
	  abort ();						\
	}							\
								\
      if (create_structure_##ID ())				\
	{							\
	  REPORT ("created", str_name);				\
	  break;						\
	}							\
								\
      error ("Failed to %s %s.",				\
	     state == SS_OK ? "create" : "update",		\
	     str_name);						\
      abort ();							\
    }								\
  while (0)

/* Exported functions.  */
void init_structure_states	PARAMS ((void));
void release_dirty_structures	PARAMS ((void));
void finish_structures		PARAMS ((void));

/* Passes:  */

/* Enumeration of all passes.  */
enum passes
{
#undef DEF_PASS
#define DEF_PASS(ID, NAME, DESC, PARS, NPARS, HEADER, TYPE, VALUE, INIT, DONE, RUN) \
  PASS_##ID,
#include "passes.def"
  PASS_MAX
};

/* Current pass name.  */
extern const char *current_pass;

/* Structures preserved by pass.  */
extern int pass_preserves[STR_MAX];
extern int pass_preserves_all;

/* Temporary variables for passing return value to pass finalization.  */
#undef DEF_PASS
#define DEF_PASS(ID, NAME, DESC, PARS, NPARS, HEADER, TYPE, VALUE, INIT, DONE, RUN) \
extern TYPE pass_##ID##_return_value_temp;
#include "passes.def"

/* Pass manipulation macros, for description see passes.def.  */

#define REQ_DEFAULT_STRUCTURES					\
  do								\
    {								\
      REQ_STRUCTURE (cfg, OK);					\
      REQ_STRUCTURE (ssa, NONE);				\
      REQ_STRUCTURE (loops_for_loop2, NONE);			\
    }								\
  while (0)

#define PRESERVE_STRUCTURE(ID)					\
  if (!pass_preserves[STR_##ID])				\
    {								\
      pass_preserves[STR_##ID] = 1;				\
      preserve_implied_structures_##ID ();			\
    }

#define PRESERVE_ALL_STRUCTURES					\
  pass_preserves_all = 1

#define BEGIN_PASS (ID, PARS)					\
  {								\
    int __pass_preserves[STR_MAX];				\
    int __pass_preserves_all = pass_preserves_all;		\
    enum passes __pass_id = PASS_#ID;				\
    memcpy (__pass_preserves, pass_preserves, sizeof (pass_preserves)); \
    pass_preserves_all = 0;					\
    memset (pass_preserves, 0, sizeof (pass_preserves));	\
								\
    initialize_pass_##ID PARS;

#define END_PASS (ID, PARS, RETURN_VALUE)			\
    if (__pass_id != PASS_#ID)					\
      {								\
	error ("Mismatched END_PASS.");				\
	abort ();						\
      }								\
    pass_##ID##_return_value_temp = (RETURN_VALUE);		\
    finalize_pass_##ID PARS;					\
    update_structures (pass_preserves, pass_preserves_all);	\
    pass_preserves_all = __pass_preserves_all;			\
    memcpy (pass_preserves, __pass_preserves, sizeof (__pass_preserves)); \
  }

#define RUN_PASS(ID, PARS)					\
  run_pass_##ID PARS

/* Exported functions.  */
void update_structures		PARAMS ((int [STR_MAX], int));

/* The generated functions.  */
#undef DEF_PASS
#define DEF_PASS(ID, NAME, DESC, PARS, NPARS, HEADER, TYPE, VALUE, INIT, DONE, RUN) \
void initialize_pass_##ID	PARAMS (PARS);			\
void finalize_pass_##ID		PARAMS (PARS);			\
TYPE run_pass_##ID		PARAMS (PARS);
#include "passes.def"

Attachment: structures.def
Description: Text document


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