(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-65.c
       1  /* PRE tree-optimization/90626 - fold strcmp(a, b) == 0 to zero when
       2     one string length is exact and the other is unequal
       3     { dg-do compile }
       4     { dg-options "-O2 -Wall -Wno-string-compare -fdump-tree-optimized -ftrack-macro-expansion=0" } */
       5  
       6  #include "strlenopt.h"
       7  
       8  #define CAT(x, y) x ## y
       9  #define CONCAT(x, y) CAT (x, y)
      10  #define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
      11  
      12  #define FAIL(name) do {				\
      13      extern void FAILNAME (name) (void);		\
      14      FAILNAME (name)();				\
      15    } while (0)
      16  
      17  /* Macro to emit a call to function named
      18       call_in_true_branch_not_eliminated_on_line_NNN()
      19     for each call that's expected to be eliminated.  The dg-final
      20     scan-tree-dump-time directive at the bottom of the test verifies
      21     that no such call appears in output.  */
      22  #define ELIM_IF_TRUE(expr)						\
      23    if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
      24  
      25  /* Macro to emit a call to a function named
      26       call_made_in_{true,false}_branch_on_line_NNN()
      27     for each call that's expected to be retained.  The dg-final
      28     scan-tree-dump-time directive at the bottom of the test verifies
      29     that the expected number of both kinds of calls appears in output
      30     (a pair for each line with the invocation of the KEEP() macro.  */
      31  #define TEST_KEEP(expr)				\
      32    if (expr)					\
      33      FAIL (made_in_true_branch);			\
      34    else						\
      35      FAIL (made_in_false_branch)
      36  
      37  #define FOLD(init1, init2, arg1, arg2, bnd)	\
      38    do {							\
      39      char a[8], b[8];					\
      40      sink (a, b);					\
      41      memcpy (a, init1, sizeof init1 - 1);		\
      42      memcpy (b, init2, sizeof init2 - 1);		\
      43      ELIM_IF_TRUE (0 != CMPFUNC (arg1, arg2, bnd));	\
      44    } while (0)
      45  
      46  #define KEEP(init1, init2, arg1, arg2, bnd)	\
      47    do {						\
      48      char a[8], b[8];				\
      49      sink (a, b);				\
      50      memcpy (a, init1, sizeof init1 - 1);	\
      51      memcpy (b, init2, sizeof init2 - 1);	\
      52      TEST_KEEP (0 == CMPFUNC (arg1, arg2, bnd));	\
      53    } while (0)
      54  
      55  const char s0[1] = "";
      56  const char s00[2] = "\0";
      57  const char s10[2] = "1";
      58  const char s20[2] = "2";
      59  
      60  void sink (void*, ...);
      61  
      62  void test_strcmp_elim (void)
      63  {
      64  #undef CMPFUNC
      65  #define CMPFUNC(a, b, dummy) strcmp (a, b)
      66  
      67    FOLD (s00, s10, "\0", "1", -1);
      68    FOLD (s00, s10, "\0", b, -1);
      69    FOLD (s00, s10, "\0", s10, -1);
      70  
      71    FOLD (s00, s10, s0, "1", -1);
      72    FOLD (s00, s10, s0, b, -1);
      73    FOLD (s00, s10, s0, s10, -1);
      74  
      75    FOLD ("\0", "1", s0, "1", -1);
      76    FOLD ("\0", "1", s0, b, -1);
      77    FOLD ("\0", "1", s0, s10, -1);
      78  
      79    FOLD ("2",  "\0", "2", "\0", -1);
      80    FOLD ("2",  "\0", s20, s0, -1);
      81  
      82    FOLD ("\0", "1", a, b, -1);
      83    FOLD ("2",  "\0", a, b, -1);
      84  
      85    FOLD ("4\0", "44", a, b, -1);
      86    FOLD ("55", "5\0", a, b, -1);
      87  
      88    FOLD ("666\0", "6666", a, "6666", -1);
      89    FOLD ("666\0", "6666", a, b, -1);
      90    FOLD ("7777", "777\0", a, b, -1);
      91  
      92    /* Avoid testing substrings of equal length with different characters.
      93       The optimization doesn't have access to the contents of the strings
      94       so it can't determine whether they are equal.
      95  
      96       FOLD ("111\0", "112", a, b, -1);
      97       FOLD ("112", "111\0", a, b, -1);  */
      98  }
      99  
     100  const char s123[] = "123";
     101  const char s1230[] = "123\0";
     102  
     103  const char s1234[] = "1234";
     104  const char s12340[] = "1234\0";
     105  
     106  void test_strncmp_elim (void)
     107  {
     108  #undef CMPFUNC
     109  #define CMPFUNC(a, b, n) strncmp (a, b, n)
     110  
     111    FOLD (s1230, s1234, "123",  "1234", 4);
     112    FOLD (s1234, s1230, "1234", "123",  4);
     113  
     114    FOLD (s1230, s1234, "123",  s1234, 4);
     115    FOLD (s1234, s1230, "1234", s123,  4);
     116  
     117    FOLD (s1230, s1234, s123,  "1234", 4);
     118    FOLD (s1234, s1230, s1234, "123",  4);
     119  
     120    FOLD (s1230, s1234, s123,  b, 4);
     121    FOLD (s1234, s1230, s1234, b, 4);
     122  
     123    FOLD (s1230, s1234, a, b, 4);
     124    FOLD (s1234, s1230, a, b, 4);
     125  
     126    FOLD ("123\0", "1234",  a, b, 5);
     127    FOLD ("1234",  "123\0", a, b, 5);
     128  }
     129  
     130  
     131  #line 1000
     132  
     133  void test_strcmp_keep (const char *s, const char *t)
     134  {
     135  #undef CMPFUNC
     136  #define CMPFUNC(a, b, dummy) strcmp (a, b)
     137  
     138    KEEP ("123", "123\0", a, b, /* bnd = */ -1);
     139    KEEP ("123\0", "123", a, b, -1);
     140  
     141    {
     142      char a[8], b[8];
     143      sink (a, b);
     144      strcpy (a, s);
     145      strcpy (b, t);
     146      TEST_KEEP (0 == strcmp (a, b));
     147    }
     148  }
     149  
     150  
     151  void test_strncmp_keep (const char *s, const char *t)
     152  {
     153  #undef CMPFUNC
     154  #define CMPFUNC(a, b, n) strncmp (a, b, n)
     155  
     156    KEEP ("1", "1", a, b, 2);
     157  
     158    KEEP ("1\0", "1", a, b, 2);
     159    KEEP ("1",   "1\0", a, b, 2);
     160  
     161    KEEP ("12\0", "12", a, b, 2);
     162    KEEP ("12",   "12\0", a, b, 2);
     163  
     164    KEEP ("111\0", "111", a, b, 3);
     165    KEEP ("112", "112\0", a, b, 3);
     166  
     167    {
     168      char a[8], b[8];
     169      sink (a, b);
     170      strcpy (a, s);
     171      strcpy (b, t);
     172      TEST_KEEP (0 == strncmp (a, b, sizeof a));
     173    }
     174  }
     175  
     176  /* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
     177  
     178     { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 11 "optimized" } }
     179     { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 11 "optimized" } } */