(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-82.c
       1  /* PR tree-optimization/83821 - local aggregate initialization defeats
       2     strlen optimization
       3  
       4     Avoid exercising targets other than x86_64 in LP64 mode due to PR 83543
       5     - strlen of a local array member not optimized on some targets
       6     { dg-do compile { target { { i?86-*-* x86_64-*-* } && lp64 } } }
       7  
       8     { dg-options "-O2 -Wall -fdump-tree-optimized" } */
       9  
      10  #include "strlenopt.h"
      11  
      12  #define CAT(x, y) x ## y
      13  #define CONCAT(x, y) CAT (x, y)
      14  #define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
      15  
      16  #define FAIL(name) do {				\
      17      extern void FAILNAME (name) (void);		\
      18      FAILNAME (name)();				\
      19    } while (0)
      20  
      21  /* Macro to emit a call to function named
      22       call_in_true_branch_not_eliminated_on_line_NNN()
      23     for each call that's expected to be eliminated.  The dg-final
      24     scan-tree-dump-time directive at the bottom of the test verifies
      25     that no such call appears in output.  */
      26  #define ELIM(expr) \
      27    if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
      28  
      29  /* Macro to emit a call to a function named
      30       call_made_in_{true,false}_branch_on_line_NNN()
      31     for each call that's expected to be retained.  The dg-final
      32     scan-tree-dump-time directive at the bottom of the test verifies
      33     that the expected number of both kinds of calls appears in output
      34     (a pair for each line with the invocation of the KEEP() macro.  */
      35  #define KEEP(expr)				\
      36    if (expr)					\
      37      FAIL (made_in_true_branch);			\
      38    else						\
      39      FAIL (made_in_false_branch)
      40  
      41  #define STR10 "0123456789"
      42  #define STR20 STR10 STR10
      43  #define STR30 STR20 STR10
      44  #define STR40 STR20 STR20
      45  
      46  void elim_char_array_init_consecutive (void)
      47  {
      48    char a[][10] = { "1", "12", "123", "1234", "12345", "12345" };
      49  
      50    ELIM (strlen (a[0]) == 1);
      51    ELIM (strlen (a[1]) == 2);
      52    ELIM (strlen (a[2]) == 3);
      53    ELIM (strlen (a[3]) == 4);
      54    ELIM (strlen (a[4]) == 5);
      55  }
      56  
      57  void elim_char_array_cpy_consecutive (void)
      58  {
      59    char a[5][10];
      60  
      61    strcpy (a[0], "12345");
      62    strcpy (a[1], "1234");
      63    strcpy (a[2], "123");
      64    strcpy (a[3], "12");
      65    strcpy (a[4], "1");
      66  
      67    ELIM (strlen (a[0]) == 5);
      68    ELIM (strlen (a[1]) == 4);
      69    ELIM (strlen (a[2]) == 3);
      70    ELIM (strlen (a[3]) == 2);
      71    ELIM (strlen (a[4]) == 1);
      72  }
      73  
      74  void elim_clear_char_array_cpy_consecutive (void)
      75  {
      76    char a[5][10] = { };
      77  
      78    strcpy (a[0], "12345");
      79    strcpy (a[1], "1234");
      80    strcpy (a[2], "123");
      81    strcpy (a[3], "12");
      82    strcpy (a[4], "1");
      83  
      84    ELIM (strlen (a[0]) == 5);
      85    ELIM (strlen (a[1]) == 4);
      86    ELIM (strlen (a[2]) == 3);
      87    ELIM (strlen (a[3]) == 2);
      88    ELIM (strlen (a[4]) == 1);
      89  }
      90  
      91  struct Consec
      92  {
      93    char s1[sizeof STR40];
      94    char s2[sizeof STR40];
      95    const char *p1;
      96    const char *p2;
      97  };
      98  
      99  void elim_struct_init_consecutive (void)
     100  {
     101    struct Consec a = { STR10, STR10, STR10, STR10 };
     102  
     103    ELIM (strlen (a.s1) == sizeof STR10 - 1);
     104    ELIM (strlen (a.s2) == sizeof STR10 - 1);
     105    ELIM (strlen (a.p1) == sizeof STR10 - 1);
     106    ELIM (strlen (a.p2) == sizeof STR10 - 1);
     107  }
     108  
     109  void elim_struct_array_init_consecutive (void)
     110  {
     111    struct Consec a[2] = {
     112      { STR10, STR20, STR30, STR40 },
     113      { STR40, STR30, STR20, STR10 }
     114    };
     115  
     116    ELIM (strlen (a[0].s1) == sizeof STR10 - 1);
     117    ELIM (strlen (a[0].s2) == sizeof STR20 - 1);
     118    ELIM (strlen (a[0].p1) == sizeof STR30 - 1);
     119    ELIM (strlen (a[0].p2) == sizeof STR40 - 1);
     120  
     121    ELIM (strlen (a[1].s1) == sizeof STR40 - 1);
     122    ELIM (strlen (a[1].s2) == sizeof STR30 - 1);
     123    ELIM (strlen (a[1].p1) == sizeof STR20 - 1);
     124    ELIM (strlen (a[1].p2) == sizeof STR10 - 1);
     125  }
     126  
     127  struct NonConsec
     128  {
     129    char s1[sizeof STR40];
     130    int i1;
     131    char s2[sizeof STR40];
     132    int i2;
     133    const char *p1;
     134    int i3;
     135    const char *p2;
     136    int i4;
     137  };
     138  
     139  void elim_struct_init_nonconsecutive (void)
     140  {
     141    struct NonConsec b = { STR10, 123, STR20, 456, b.s1, 789, b.s2, 123 };
     142  
     143    ELIM (strlen (b.s1) == sizeof STR10 - 1);
     144    ELIM (strlen (b.s2) == sizeof STR20 - 1);
     145    ELIM (strlen (b.p1) == sizeof STR10 - 1);
     146    ELIM (strlen (b.p2) == sizeof STR20 - 1);
     147  }
     148  
     149  void elim_struct_assign_tmp_nonconsecutive (void)
     150  {
     151    struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d", 4 };
     152  
     153    b = (struct NonConsec){ STR10, 123, STR20, 456, STR30, 789, STR40, 123 };
     154  
     155    ELIM (strlen (b.s1) == sizeof STR10 - 1);
     156    ELIM (strlen (b.s2) == sizeof STR20 - 1);
     157    ELIM (strlen (b.p1) == sizeof STR30 - 1);
     158    ELIM (strlen (b.p2) == sizeof STR40 - 1);
     159  }
     160  
     161  const struct NonConsec bcst = {
     162    STR40, -1, STR30, -2, STR20, -3, STR10, -4
     163  };
     164  
     165  void elim_struct_assign_cst_nonconsecutive (void)
     166  {
     167    struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d" };
     168  
     169    b = bcst;
     170  
     171    ELIM (strlen (b.s1) == sizeof STR40 - 1);
     172    ELIM (strlen (b.s2) == sizeof STR30 - 1);
     173    ELIM (strlen (b.p1) == sizeof STR20 - 1);
     174    ELIM (strlen (b.p2) == sizeof STR10 - 1);
     175  }
     176  
     177  void elim_struct_copy_cst_nonconsecutive (void)
     178  {
     179    struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d" };
     180    memcpy (&b, &bcst, sizeof b);
     181  
     182    /* ELIM (strlen (b.s1) == sizeof STR40 - 1);
     183       ELIM (strlen (b.s2) == sizeof STR30 - 1); */
     184    ELIM (strlen (b.p1) == sizeof STR20 - 1);
     185    ELIM (strlen (b.p2) == sizeof STR10 - 1);
     186  }
     187  
     188  
     189  #line 1000
     190  
     191  int sink (void*);
     192  
     193  void keep_init_nonconsecutive (void)
     194  {
     195    struct NonConsec b = {
     196      STR10, 123, STR20, 456, b.s1, 789, b.s2,
     197      sink (&b)
     198    };
     199  
     200    KEEP (strlen (b.s1) == sizeof STR10 - 1);
     201    KEEP (strlen (b.s2) == sizeof STR10 - 1);
     202    KEEP (strlen (b.p1) == sizeof STR10 - 1);
     203    KEEP (strlen (b.p2) == sizeof STR10 - 1);
     204  }
     205  
     206  void keep_assign_tmp_nonconsecutive (void)
     207  {
     208    struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d", 4 };
     209  
     210    b = (struct NonConsec){
     211      STR10, 123, STR20, 456, STR30, 789, STR40,
     212      sink (&b)
     213    };
     214  
     215    KEEP (strlen (b.s1) == sizeof STR10 - 1);
     216    KEEP (strlen (b.s2) == sizeof STR20 - 1);
     217    KEEP (strlen (b.p1) == sizeof STR30 - 1);
     218    KEEP (strlen (b.p2) == sizeof STR40 - 1);
     219  }
     220  
     221  /* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
     222  
     223     { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 8 "optimized" } }
     224     { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 8 "optimized" } } */