On Fri, Apr 10, 2020 at 10:29:29AM +0200, Martin Liška wrote: > +/* Valid pairs of new and delete operators for DCE. */ > +static hash_set<nofree_string_hash> *valid_pairs = NULL; > + > +/* Return that NEW_CALL and DELETE_CALL are a valid pair of new > + and delete operators. */ > + > +static bool > +valid_new_delete_pair_p (gimple *new_call, gimple *delete_call) > +{ > + const char *new_name > + = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (gimple_call_fndecl > (new_call))); > + const char *delete_name > + = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (gimple_call_fndecl > (delete_call))); > + > + if (new_name[0] == '_' and new_name[1] == '_') > + ++new_name; > + if (delete_name[0] == '_' and delete_name[1] == '_') > + ++delete_name; > + > + char *needle = concat (new_name, ":", delete_name, NULL); > + > + if (valid_pairs == NULL) > + { > + valid_pairs = new hash_set<nofree_string_hash> (); > + /* Invalid pairs: > + non-[] and [] > + aligned and non-aligned > + */ > + > + const char *pairs[] = { > + /* non-[] operators. */ > + "_Znwm:_ZdlPv" , > + "_Znwm:_ZdlPvm" ,
Formatting, I think the /* and "_Z should be two columns from const char, and no space before , Not sure I like using the : and using a hash table looks like an overkill to me, don't we have only 8 options, and most of them with different identifier lengths? The concat itself will take a while... And, what's worse, the m in there is really different on different targets. It can be j, m or y depending on what fundamental type size_t is. So why not (completely untested): static bool valid_new_delete_pair_p (gimple *new_call, gimple *delete_call) { tree new_asm = DECL_ASSEMBLER_NAME (gimple_call_fndecl (new_call)); tree delete_asm = DECL_ASSEMBLER_NAME (gimple_call_fndecl (delete_call)); const char *new_name = IDENTIFIER_POINTER (new_asm); const char *delete_name = IDENTIFIER_POINTER (delete_asm); unsigned int new_len = IDENTIFIER_LENGTH (mew_asm); unsigned int delete_len = IDENTIFIER_LENGTH (delete_asm); if (new_name < 5 || delete_len < 6) return false; if (new_name[0] == '_') ++new_name, --new_len; if (new_name[0] == '_') ++new_name, --new_len; if (delete_name[0] == '_') ++delete_name, --delete_len; if (delete_name[0] == '_') ++delete_name, --delete_len; if (new_len < 4 || delete_len < 5) return false; /* *_len is now just the length after initial underscores. */ if (new_name[0] != 'Z' || new_name[1] != 'n') return false; if (delete_name[0] != 'Z' || delete_name[1] != 'd') return false; /* _Znw must match _Zdl, _Zna must match _Zda. */ if ((new_name[2] != 'w' || delete_name[2] != 'l') && (new_name[2] != 'a' || delete_name[2] != 'a')) return false; if (new_name[3] != 'j' && new_name[3] != 'm' && new_name[3] != 'y') return false; if (delete_name[3] != 'P' || delete_name[4] != 'v') return false; if (new_len == 4 || (new_len == 18 && !memcmp (new_name + 4, "RKSt9nothrow_t", 14))) { /* _ZnXY or _ZnXYRKSt9nothrow_t matches _ZdXPv, _ZdXPvY and _ZdXPvRKSt9nothrow_t. */ if (delete_len == 5) return true; if (delete_len == 6 && delete_name[5] == new_name[3]) return true; if (delete_len == 19 && !memcmp (delete_name + 5, "RKSt9nothrow_t", 14)) return true; } else if ((new_len == 19 && !memcmp (new_name + 4, "St11align_val_t", 15)) || (new_len == 33 && !memcmp (new_name + 4, "St11align_val_tRKSt9nothrow_t", 29))) { /* _ZnXYSt11align_val_t or _ZnXYSt11align_val_tRKSt9nothrow_t matches _ZdXPvSt11align_val_t or _ZdXPvYSt11align_val_t or or _ZdXPvSt11align_val_tRKSt9nothrow_t. */ if (delete_len == 20 && !memcmp (delete_name + 5, "St11align_val_t", 15)) return true; if (delete_len == 21 && delete_name[5] == new_name[3] && !memcmp (delete_name + 6, "St11align_val_t", 15)) return true; if (delete_len == 34 && !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29)) return true; } return false; } Jakub