Hi. This one is more interesting as it implements hierarchical option parsing and as a first step I implemented that for optgroup suboptions.
Next candidates are dump_option_value_info and obviously my primary motivation: dump_option_value_info. I'm expecting feedback for implementation I've decided to come up with. Patch has been tested. Thanks, Martin
>From fcb78a3d07f3043766f27f73038f313f914b3976 Mon Sep 17 00:00:00 2001 From: marxin <mli...@suse.cz> Date: Fri, 5 May 2017 11:31:18 +0200 Subject: [PATCH 2/2] Add dump_flags_type<E> for handling of suboptions. gcc/ChangeLog: 2017-05-05 Martin Liska <mli...@suse.cz> * dumpfile.c (dump_option_node::initialize): New function. (dump_option_node::initialize_masks): Likewise. (dump_option_node::parse): Likewise. (gcc::dump_manager::dump_manager): Initialize options. (dump_switch_p_1): Use the new parser. (initialize_options): New function. (opt_info_switch_p_1): Use the new parser. (opt_info_switch_p): Use new dump_flags_type<E> type. * dumpfile.h (struct dump_option_node): New struct. (struct dump_flags_type): Likewise. (enum optgroup_types): New enum type. (struct dump_file_info): Change type of optgroup_flags. --- gcc/dumpfile.c | 141 ++++++++++++++++++++++++++++++++++++++++---------- gcc/dumpfile.h | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 255 insertions(+), 46 deletions(-) diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c index 907ded3695f..82c4fc9d4ff 100644 --- a/gcc/dumpfile.c +++ b/gcc/dumpfile.c @@ -135,17 +135,78 @@ static const struct dump_option_value_info optinfo_verbosity_options[] = {NULL, 0} }; -/* Flags used for -fopt-info groups. */ -static const struct dump_option_value_info optgroup_options[] = -{ - {"ipa", OPTGROUP_IPA}, - {"loop", OPTGROUP_LOOP}, - {"inline", OPTGROUP_INLINE}, - {"omp", OPTGROUP_OMP}, - {"vec", OPTGROUP_VEC}, - {"optall", OPTGROUP_ALL}, - {NULL, 0} -}; +template <typename E> +dump_option_node<E>::dump_option_node (const char *name, E enum_value): + m_name (name), m_enum_value (enum_value), m_children (), m_mask (0) +{ +} + +template <typename E> +void +dump_option_node<E>::initialize (uint64_t *mask_translation) +{ + memset (mask_translation, 0, sizeof (uint64_t) * OPT_MASK_SIZE); + unsigned current = 0; + initialize_masks (¤t, mask_translation); +} + +template <typename E> +uint64_t +dump_option_node<E>::initialize_masks (unsigned *current, + uint64_t *mask_translation) +{ + if (m_children.is_empty ()) + { + gcc_assert (*current < OPT_MASK_SIZE); + m_mask = 1 << *current; + *current += 1; + } + else + { + uint64_t combined = 0; + for (unsigned i = 0; i < m_children.length (); i++) + combined |= m_children[i]->initialize_masks (current, mask_translation); + + m_mask = combined; + } + + mask_translation[m_enum_value] = m_mask; + return m_mask; +} + +template <typename E> +uint64_t +dump_option_node<E>::parse (const char *token) +{ + char *s = xstrdup (token); + uint64_t r = parse (s); + free (s); + + return r; +} + +template <typename E> +uint64_t +dump_option_node<E>::parse (char *token) +{ + if (token == NULL) + return m_mask; + + if (strcmp (token, "all") == 0) + { + token = strtok (NULL, "-"); + return token == NULL ? m_mask : 0; + } + + for (unsigned i = 0; i < m_children.length (); i++) + if (strcmp (m_children[i]->m_name, token) == 0) + { + token = strtok (NULL, "-"); + return m_children[i]->parse (token); + } + + return 0; +} gcc::dump_manager::dump_manager (): m_next_dump (FIRST_AUTO_NUMBERED_DUMP), @@ -153,6 +214,7 @@ gcc::dump_manager::dump_manager (): m_extra_dump_files_in_use (0), m_extra_dump_files_alloced (0) { + initialize_options (); } gcc::dump_manager::~dump_manager () @@ -174,12 +236,14 @@ gcc::dump_manager::~dump_manager () XDELETEVEC (const_cast <char *> (dfi->alt_filename)); } XDELETEVEC (m_extra_dump_files); + + delete (optgroup_options); } unsigned int gcc::dump_manager:: dump_register (const char *suffix, const char *swtch, const char *glob, - dump_flags_t flags, int optgroup_flags, + dump_flags_t flags, optgroup_dump_flags_t optgroup_flags, bool take_ownership) { int num = m_next_dump++; @@ -716,8 +780,8 @@ dump_enable_all (dump_flags_t flags, const char *filename) int gcc::dump_manager:: -opt_info_enable_passes (int optgroup_flags, dump_flags_t flags, - const char *filename) +opt_info_enable_passes (optgroup_dump_flags_t optgroup_flags, + dump_flags_t flags, const char *filename) { int n = 0; size_t i; @@ -808,7 +872,7 @@ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) if (strlen (option_ptr->name) == length && !memcmp (option_ptr->name, ptr, length)) { - flags |= option_ptr->value; + flags |= option_ptr->value; goto found; } @@ -865,15 +929,36 @@ dump_switch_p (const char *arg) return any; } +void +gcc::dump_manager:: +initialize_options () +{ + /* Initialize optgroup options. */ + typedef dump_option_node<optgroup_types> node; + + optgroup_options = new node (NULL, OPTGROUP_NONE); + optgroup_options->register_suboption (new node ("ipa", OPTGROUP_IPA)); + optgroup_options->register_suboption (new node ("loop", OPTGROUP_LOOP)); + optgroup_options->register_suboption (new node ("inline", OPTGROUP_INLINE)); + optgroup_options->register_suboption (new node ("omp", OPTGROUP_OMP)); + optgroup_options->register_suboption (new node ("vec", OPTGROUP_VEC)); + optgroup_options->register_suboption (new node ("other", OPTGROUP_OTHER)); + + optgroup_options->initialize (optgroup_dump_flags_t::m_mask_translation); +} + /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags and filename. Return non-zero if it is a recognized switch. */ static int -opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags, - char **filename) +opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, + optgroup_dump_flags_t *optgroup_flags, + char **filename) { const char *option_value; const char *ptr; + optgroup_dump_flags_t f; + gcc::dump_manager *dumps = g->get_dumps (); option_value = arg; ptr = option_value; @@ -885,6 +970,7 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags, if (!ptr) return 1; /* Handle '-fopt-info' without any additional options. */ + while (*ptr) { const struct dump_option_value_info *option_ptr; @@ -909,17 +995,16 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags, if (strlen (option_ptr->name) == length && !memcmp (option_ptr->name, ptr, length)) { - *flags |= option_ptr->value; + *flags |= option_ptr->value; goto found; - } + } - for (option_ptr = optgroup_options; option_ptr->name; option_ptr++) - if (strlen (option_ptr->name) == length - && !memcmp (option_ptr->name, ptr, length)) - { - *optgroup_flags |= option_ptr->value; - goto found; - } + f = dumps->get_optgroup_options ()->parse (ptr); + if (f) + { + *optgroup_flags |= f; + goto found; + } if (*ptr == '=') { @@ -948,7 +1033,7 @@ int opt_info_switch_p (const char *arg) { dump_flags_t flags; - int optgroup_flags; + optgroup_dump_flags_t optgroup_flags; char *filename; static char *file_seen = NULL; gcc::dump_manager *dumps = g->get_dumps (); @@ -971,7 +1056,7 @@ opt_info_switch_p (const char *arg) if (!flags) flags = MSG_OPTIMIZED_LOCATIONS; if (!optgroup_flags) - optgroup_flags = OPTGROUP_ALL; + optgroup_flags = optgroup_dump_flags_t::get_all (); return dumps->opt_info_enable_passes (optgroup_flags, flags, filename); } diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h index 76183e3eede..67da7003331 100644 --- a/gcc/dumpfile.h +++ b/gcc/dumpfile.h @@ -90,20 +90,134 @@ enum tree_dump_index #define MSG_ALL (MSG_OPTIMIZED_LOCATIONS | MSG_MISSED_OPTIMIZATION \ | MSG_NOTE) +/* Dump option node is a tree structure that implements + parsing of suboptions and provides mapping between a given enum type E + and unsigned integer masks that are encapsulated in dump_flags_type type. */ -/* Flags to control high-level -fopt-info dumps. Usually these flags - define a group of passes. An optimization pass can be part of - multiple groups. */ -#define OPTGROUP_NONE (0) -#define OPTGROUP_IPA (1 << 1) /* IPA optimization passes */ -#define OPTGROUP_LOOP (1 << 2) /* Loop optimization passes */ -#define OPTGROUP_INLINE (1 << 3) /* Inlining passes */ -#define OPTGROUP_OMP (1 << 4) /* OMP (Offloading and Multi - Processing) transformations */ -#define OPTGROUP_VEC (1 << 5) /* Vectorization passes */ -#define OPTGROUP_OTHER (1 << 6) /* All other passes */ -#define OPTGROUP_ALL (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE \ - | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER) +template <typename E> +struct dump_option_node +{ + /* Constructor. */ + dump_option_node (const char *name, E enum_value); + + /* Initialize hierarchy and fill up a MASK_TRANLATION table. */ + void initialize (uint64_t *mask_translation); + + /* Parse a given option string and return mask. */ + uint64_t parse (const char *token); + + /* Register a SUBOPTION for a dump option node. */ + void register_suboption (dump_option_node<E> *suboption) + { + m_children.safe_push (suboption); + } + +private: + /* Initialize masks for internal nodes. CURRENT is a counter with first + free mask. MASK_TRANSLATION is table that is filled up. */ + uint64_t initialize_masks (unsigned *current, uint64_t *mask_translation); + + /* Parse a given option string and return mask. */ + uint64_t parse (char *token); + + /* Name of the option. */ + const char *m_name; + + /* Enum value of the option. */ + E m_enum_value; + + /* Children options. */ + vec<dump_option_node *> m_children; + + /* Mask that represents the option. */ + uint64_t m_mask; +}; + +/* Size of possible valid leaf options. */ +#define OPT_MASK_SIZE (CHAR_BIT * sizeof (uint64_t)) + +/* Dump flags type represents a set of selected options for + a given enum type E. */ + +template <typename E> +struct dump_flags_type +{ + /* Constructor. */ + dump_flags_type<E> (): m_mask (0) + {} + + /* Constructor for a MASK. */ + dump_flags_type<E> (uint64_t mask): m_mask (mask) + {} + + /* Constructor for a enum value E. */ + dump_flags_type<E> (E enum_value) + { + gcc_checking_assert ((unsigned)enum_value <= OPT_MASK_SIZE); + m_mask = m_mask_translation[enum_value]; + } + + /* OR operator for OTHER dump_flags_type. */ + inline void operator|= (dump_flags_type other) + { + m_mask |= other.m_mask; + } + + /* AND operator for OTHER dump_flags_type. */ + inline void operator&= (dump_flags_type other) + { + m_mask &= other.m_mask; + } + + /* AND operator for OTHER dump_flags_type. */ + inline bool operator& (dump_flags_type other) + { + return m_mask & other.m_mask; + } + + /* Bool operator that is typically used to test whether an option is set. */ + inline operator bool () const + { + return m_mask; + } + + /* Return mask that represents all selected options. */ + static inline dump_flags_type get_all () + { + return m_mask_translation[0]; + } + + /* Initialize. */ + static dump_flags_type parse (char *option); + + /* Selected mask of options. */ + uint64_t m_mask; + + /* Translation table between enum values and masks. */ + static uint64_t m_mask_translation[OPT_MASK_SIZE]; +}; + +/* Flags used for -fopt-info groups. */ + +enum optgroup_types +{ + OPTGROUP_NONE, + OPTGROUP_IPA, + OPTGROUP_LOOP, + OPTGROUP_INLINE, + OPTGROUP_OMP, + OPTGROUP_VEC, + OPTGROUP_OTHER, + OPTGROUP_COUNT +}; + +template<typename E> +uint64_t +dump_flags_type<E>::m_mask_translation[OPT_MASK_SIZE]; + +/* Dump flags type for optgroup_types enum type. */ + +typedef dump_flags_type<optgroup_types> optgroup_dump_flags_t; /* Dump flags type. */ @@ -120,7 +234,7 @@ struct dump_file_info FILE *pstream; /* pass-specific dump stream */ FILE *alt_stream; /* -fopt-info stream */ dump_flags_t pflags; /* dump flags */ - int optgroup_flags; /* optgroup flags for -fopt-info */ + optgroup_dump_flags_t optgroup_flags; /* optgroup flags for -fopt-info */ int alt_flags; /* flags for opt-info */ int pstate; /* state of pass-specific stream */ int alt_state; /* state of the -fopt-info stream */ @@ -187,7 +301,7 @@ public: SUFFIX, SWTCH, and GLOB. */ unsigned int dump_register (const char *suffix, const char *swtch, const char *glob, - dump_flags_t flags, int optgroup_flags, + dump_flags_t flags, optgroup_dump_flags_t optgroup_flags, bool take_ownership); /* Return the dump_file_info for the given phase. */ @@ -232,6 +346,12 @@ public: const char * dump_flag_name (int phase) const; + /* Return optgroup_types dump options. */ + dump_option_node<optgroup_types> *get_optgroup_options () + { + return optgroup_options; + } + private: int @@ -244,8 +364,10 @@ private: dump_enable_all (dump_flags_t flags, const char *filename); int - opt_info_enable_passes (int optgroup_flags, dump_flags_t flags, - const char *filename); + opt_info_enable_passes (optgroup_dump_flags_t optgroup_flags, + dump_flags_t flags, const char *filename); + + void initialize_options (); private: @@ -255,12 +377,14 @@ private: size_t m_extra_dump_files_in_use; size_t m_extra_dump_files_alloced; + /* Dump option node for optgroup_types enum. */ + dump_option_node<optgroup_types> *optgroup_options; + /* Grant access to dump_enable_all. */ friend bool ::enable_rtl_dump_file (void); /* Grant access to opt_info_enable_passes. */ friend int ::opt_info_switch_p (const char *arg); - }; // class dump_manager } // namespace gcc -- 2.12.2