https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109058
Bug ID: 109058 Summary: RFE: analyzer should elide repeated calls to strcmp in execution paths Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: dmalcolm at gcc dot gnu.org Target Milestone: --- Seen on a diagnostic in haproxy's cfgparse-global.c: cfg_parse_global Consider: -------------------------------------------------------------------------- #include <string.h> #include "analyzer-decls.h" int test (char **args) { if (strcmp (args[0], "opt-001") == 0) { do_opt (1); } else if (strcmp (args[0], "opt-002") == 0) { do_opt (2); } else if (strcmp (args[0], "opt-003") == 0) { do_opt (3); } else if (strcmp (args[0], "opt-004") == 0) { do_opt (4); } else if (strcmp (args[0], "opt-005") == 0) { do_opt (5); } else if (strcmp (args[0], "opt-006") == 0) { do_opt (6); } else if (strcmp (args[0], "opt-007") == 0) { do_opt (7); } else if (strcmp (args[0], "opt-008") == 0) { do_opt (8); } else if (strcmp (args[0], "opt-009") == 0) { do_opt (9); } else if (strcmp (args[0], "opt-010") == 0) { do_opt (10); __analyzer_dump_path (); } } -------------------------------------------------------------------------- for which we currently emit: -------------------------------------------------------------------------- ../../src/gcc/testsuite/gcc.dg/analyzer/strcmp-path-1.c:27:5: note: path 27 | __analyzer_dump_path (); | ^~~~~~~~~~~~~~~~~~~~~~~ ‘test’: events 1-21 | | 7 | if (strcmp (args[0], "opt-001") == 0) { | | ^ | | | | | (1) following ‘false’ branch (when the strings are non-equal)... | 8 | do_opt (1); | 9 | } else if (strcmp (args[0], "opt-002") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(2) ...to here | | (3) following ‘false’ branch (when the strings are non-equal)... | 10 | do_opt (2); | 11 | } else if (strcmp (args[0], "opt-003") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(4) ...to here | | (5) following ‘false’ branch (when the strings are non-equal)... | 12 | do_opt (3); | 13 | } else if (strcmp (args[0], "opt-004") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(6) ...to here | | (7) following ‘false’ branch (when the strings are non-equal)... | 14 | do_opt (4); | 15 | } else if (strcmp (args[0], "opt-005") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(8) ...to here | | (9) following ‘false’ branch (when the strings are non-equal)... | 16 | do_opt (5); | 17 | } else if (strcmp (args[0], "opt-006") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(10) ...to here | | (11) following ‘false’ branch (when the strings are non-equal)... | 18 | do_opt (6); | 19 | } else if (strcmp (args[0], "opt-007") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(12) ...to here | | (13) following ‘false’ branch (when the strings are non-equal)... | 20 | do_opt (7); | 21 | } else if (strcmp (args[0], "opt-008") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(14) ...to here | | (15) following ‘false’ branch (when the strings are non-equal)... | 22 | do_opt (8); | 23 | } else if (strcmp (args[0], "opt-009") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(16) ...to here | | (17) following ‘false’ branch (when the strings are non-equal)... | 24 | do_opt (9); | 25 | } else if (strcmp (args[0], "opt-010") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | || | | |(18) ...to here | | (19) following ‘true’ branch (when the strings are equal)... | 26 | do_opt (10); | | ~~~~~~~~~~~ | | | | | (20) ...to here | 27 | __analyzer_dump_path (); | | ~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (21) here | -------------------------------------------------------------------------- We should probably elide all the repeated : following ‘false’ branch (when the strings are non-equal)... ...to here events before the: following ‘true’ branch (when the strings are equal)... assuming that all they're checking the same string against a series of possible values. This would simplify the execution path to just: -------------------------------------------------------------------------- ../../src/gcc/testsuite/gcc.dg/analyzer/strcmp-path-1.c:27:5: note: path 27 | __analyzer_dump_path (); | ^~~~~~~~~~~~~~~~~~~~~~~ ‘test’: events 1-3 | | 25 | } else if (strcmp (args[0], "opt-010") == 0) { | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (1) following ‘true’ branch (when the strings are equal)... | 26 | do_opt (10); | | ~~~~~~~~~~~ | | | | | (2) ...to here | 27 | __analyzer_dump_path (); | | ~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (3) here | --------------------------------------------------------------------------