blob: 9c00a95162f6515910ee07ae0ed4debebea0adaf [file] [log] [blame]
/* PR tree-optimization/91183 - strlen of a strcpy result with a conditional
source not folded
Test to verify that strlen can determine string lengths from wider stores
than narrow characters. This matters because on targets that can handle
unaligned stores and where GCC lowers multi-character stores into smaller
numbers of wider stores.
{ dg-do compile }
{ dg-options "-O2 -fdump-tree-optimized" }
On strictly aligned targets the consecutive char assignments used
by the test aren't merged. When they involve multiple trailing nuls
these assignments then defeat the strlen optimization as a result of
pr83821. When the bug is resolved the directive below can be removed.
{ dg-require-effective-target non_strict_align } */
#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)
/* Macros to emit a call to function named
call_failed_to_be_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 (not_eliminated); else (void)0
#undef T
#define T(N, ncpy, expect, assign) do { \
char a[N], b[N]; \
assign; \
memcpy (b, a, ncpy); \
ELIM (!(expect == strlen (b))); \
} while (0)
void test_copy (void)
{
T (2, 1, 0, (a[0] = 0));
T (2, 2, 0, (a[0] = 0, a[1] = 0));
T (2, 2, 1, (a[0] = '1', a[1] = 0));
T (4, 3, 2, (a[0] = '1', a[1] = '2', a[2] = 0));
// Not handled due to pr83821:
// T (4, 3, 1, (a[0] = '1', a[1] = 0, a[2] = '2'));
T (4, 2, 1, (a[0] = '1', a[1] = 0, a[2] = 0, a[3] = 0));
// Not handled due to pr83821:
// T (4, 3, 1, (a[0] = '1', a[1] = 0, a[2] = 0, a[3] = 0));
T (4, 4, 1, (a[0] = '1', a[1] = 0, a[2] = 0, a[3] = 0));
T (4, 3, 2, (a[0] = '1', a[1] = '2', a[2] = 0, a[3] = 0));
T (4, 4, 2, (a[0] = '1', a[1] = '2', a[2] = 0, a[3] = 0));
T (4, 4, 3, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = 0));
T (5, 4, 1, (a[0] = '1', a[1] = 0, a[2] = 0, a[3] = 0));
T (5, 4, 2, (a[0] = '1', a[1] = '2', a[2] = 0, a[3] = 0));
T (5, 4, 3, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = 0));
// Not handled:
// T (5, 5, 1, (a[0] = '1', a[1] = 0, a[2] = 0, a[3] = 0, a[4] = 0));
// T (5, 5, 2, (a[0] = '1', a[1] = '2', a[2] = 0, a[3] = 0, a[4] = 0));
// T (5, 5, 3, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = 0, a[4] = 0));
T (5, 5, 4, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = '4', a[4] = 0));
}
/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
{ dg-final { scan-tree-dump-times "_not_eliminated_" 0 "optimized" } } */