view gcc/testsuite/gcc.dg/strlenopt-54.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents
children 1830386684a0
line wrap: on
line source

/* PR tree-optimization/86042 - missing strlen optimization after second strcpy
   { dg-do compile }
   { dg-options "-O2 -Wall -fdump-tree-optimized" } */

#include "strlenopt.h"

#define CAT(x, y) x ## y
#define CONCAT(x, y) CAT (x, y)
#define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)

#define FAIL(name) do {				\
    extern void FAILNAME (name) (void);		\
    FAILNAME (name)();				\
  } while (0)

/* Macro to emit a call to function named
   call_in_true_branch_not_eliminated_on_line_NNN()
   for each call that's expected to be eliminated.  The dg-final
   scan-tree-dump-time directive at the bottom of the test verifies
   that no such call appears in output.  */
#define ELIM(expr)							\
  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0

void elim_after_duplicate_strcpy (void)
{
#define T(N, assign, off, str, r0, r1)		\
  do {						\
    char a[N];					\
    strcpy (a, assign);				\
    unsigned n0 = strlen (a);			\
    strcpy (a + off, str);			\
    unsigned n1 = strlen (a);			\
    ELIM (n0 == r0 && n1 == r1);		\
  } while (0)

  T (2, "",   0, "1",   0, 1);

  T (2, "1",  0, "2",   1, 1);
  T (2, "1",  1, "",    1, 1);

  T (3, "\0", 0, "1",   0, 1);
  T (3, "1",  1, "2",   1, 2);

  T (3, "12", 0, "23",  2, 2);
  T (3, "12", 1, "3",   2, 2);
  T (3, "12", 2, "",    2, 2);

  T (4, "1",   1, "23",  1, 3);
  T (4, "12",  1, "23",  2, 3);

  T (4, "123", 0, "234", 3, 3);
  T (4, "123", 1, "34",  3, 3);
  T (4, "123", 2, "4",   3, 3);
  T (4, "123", 3, "",    3, 3);

  T (5, "1234", 0, "1",    4, 1);
  T (5, "1234", 0, "12",   4, 2);
  T (5, "1234", 0, "123",  4, 3);
  T (5, "1234", 0, "1234", 4, 4);

  T (5, "123",  1, "234", 3, 4);
  T (6, "123",  2, "234", 3, 5);
}

void elim_after_init_memcpy (void)
{
#undef T
#define T(init, off, str, n, res)		\
  do {						\
    char a[] = init;				\
    memcpy (a + off, str, n);			\
    ELIM (strlen (a) == res);			\
  } while (0)

  T ("\0",   0, "1",    2, 1);
  T ("\0\0", 0, "12",   3, 2);

#define INIT { '1', '2', '3', '4' }
  T (INIT,   0, "",     1, 0);
  T (INIT,   0, "1",    2, 1);
  T (INIT,   0, "12",   3, 2);
  T (INIT,   0, "123",  4, 3);

  T ("1234", 0, "2",    1, 4);
  T ("1234", 0, "23",   2, 4);
  T ("1234", 0, "234",  3, 4);
  T ("1234", 0, "2345", 4, 4);
  T ("1234", 0, "2345", 5, 4);

  T ("1234", 1, "2",    1, 4);
  T ("1234", 1, "23",   2, 4);
  T ("1234", 1, "234",  3, 4);
  T ("1234", 1, "234",  4, 4);

  T ("1234", 2, "3",    1, 4);
  T ("1234", 2, "3",    2, 3);
  T ("1234", 2, "34",   2, 4);
  T ("1234", 2, "34",   3, 4);

  T ("12\00034", 0, "1", 1, 2);
  T ("12\00034", 0, "1", 2, 1);

  T ("AB\000CD", 0, "ab", 2, 2);
  T ("AB\000CD", 0, "ab", 3, 2);
  T ("AB\000CD", 0, "ab\000c", 4, 2);
}

/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */