191 lines
5.7 KiB
C
191 lines
5.7 KiB
C
/* PR tree-optimization/90662 - strlen of a string in a vla plus offset
|
|
not folded
|
|
{ dg-do compile }
|
|
{ dg-require-effective-target alloca }
|
|
{ dg-options "-O2 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
|
|
|
|
#include "strlenopt.h"
|
|
|
|
typedef __INT16_TYPE__ int16_t;
|
|
typedef __INT32_TYPE__ int32_t;
|
|
|
|
#define CONCAT(x, y) x ## y
|
|
#define CAT(x, y) CONCAT (x, y)
|
|
#define FAILNAME(name, counter) \
|
|
CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
|
|
|
|
#define FAIL(name, counter) do { \
|
|
extern void FAILNAME (name, counter) (void); \
|
|
FAILNAME (name, counter)(); \
|
|
} while (0)
|
|
|
|
/* Macro to emit a call to funcation 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, __COUNTER__); else (void)0
|
|
|
|
#define ARGS(...) __VA_ARGS__
|
|
|
|
void sink (void*, ...);
|
|
|
|
|
|
#define T(Type, expect, init, p) \
|
|
do { \
|
|
Type vla[n]; \
|
|
char *ptr = strcpy ((char*)vla, init); \
|
|
ELIM (expect == strlen (p)); \
|
|
sink (ptr); \
|
|
} while (0)
|
|
|
|
void test_char_vla_local (int n)
|
|
{
|
|
T (char, 0, "", vla);
|
|
T (char, 0, "\0", vla);
|
|
T (char, 1, "1", vla);
|
|
T (char, 2, "12", vla);
|
|
T (char, 3, "123", vla);
|
|
|
|
T (char, 2, "123", vla + 1);
|
|
T (char, 1, "123", &vla[2]);
|
|
T (char, 0, "123", &vla[1] + 2);
|
|
|
|
T (char, 2, "123", &vla[2] - 1);
|
|
T (char, 3, "123", &vla[1] - 1);
|
|
|
|
T (char, 0, "", ptr);
|
|
T (char, 0, "\0", ptr);
|
|
T (char, 1, "1", ptr);
|
|
T (char, 2, "12", ptr);
|
|
T (char, 3, "123", ptr);
|
|
|
|
T (char, 2, "123", ptr + 1);
|
|
T (char, 1, "123", &ptr[2]);
|
|
T (char, 0, "123", &ptr[1] + 2);
|
|
}
|
|
|
|
void test_int16_vla_local (int n)
|
|
{
|
|
T (int16_t, 0, "", (char*)vla);
|
|
T (int16_t, 0, "\0", (char*)vla);
|
|
T (int16_t, 1, "1", (char*)vla);
|
|
T (int16_t, 2, "12", (char*)vla);
|
|
T (int16_t, 3, "123", (char*)vla);
|
|
|
|
T (int16_t, 2, "1234", (char*)(vla + 1));
|
|
T (int16_t, 2, "123456", (char*)&vla[2]);
|
|
T (int16_t, 1, "123456", (char*)&vla[2] + 1);
|
|
T (int16_t, 0, "123456", (char*)&vla[2] + 2);
|
|
T (int16_t, 0, "123456", (char*)(&vla[1] + 2));
|
|
|
|
T (int16_t, 3, "123456", (char*)&vla[2] - 1);
|
|
T (int16_t, 4, "123456", (char*)&vla[2] - 2);
|
|
|
|
T (int16_t, 0, "", ptr);
|
|
T (int16_t, 0, "\0", ptr);
|
|
T (int16_t, 1, "1", ptr);
|
|
T (int16_t, 2, "12", ptr);
|
|
T (int16_t, 3, "123", ptr);
|
|
|
|
T (int16_t, 2, "123", ptr + 1);
|
|
T (int16_t, 1, "123", &ptr[2]);
|
|
T (int16_t, 0, "123", &ptr[1] + 2);
|
|
}
|
|
|
|
void test_int_vla_local (int n)
|
|
{
|
|
T (int16_t, 0, "", (char*)vla);
|
|
T (int16_t, 0, "\0", (char*)vla);
|
|
T (int16_t, 1, "1", (char*)vla);
|
|
T (int16_t, 2, "12", (char*)vla);
|
|
T (int16_t, 3, "123", (char*)vla);
|
|
|
|
T (int16_t, 2, "1234", (char*)(vla + 1));
|
|
T (int16_t, 2, "123456", (char*)&vla[2]);
|
|
T (int16_t, 1, "123456", (char*)&vla[2] + 1);
|
|
T (int16_t, 0, "123456", (char*)&vla[2] + 2);
|
|
T (int16_t, 0, "123456", (char*)(&vla[1] + 2));
|
|
|
|
T (int, 0, "", ptr);
|
|
T (int, 0, "\0", ptr);
|
|
T (int, 1, "1", ptr);
|
|
T (int, 2, "12", ptr);
|
|
T (int, 3, "123", ptr);
|
|
|
|
T (int, 2, "123", ptr + 1);
|
|
T (int, 1, "123", &ptr[2]);
|
|
T (int, 0, "123", &ptr[1] + 2);
|
|
}
|
|
|
|
|
|
#undef T
|
|
#define T(Type, expect, parr, init, p) \
|
|
do { \
|
|
Type (*parray)[] = *ppa++; \
|
|
char *ptr = strcpy ((char*)parr, init); \
|
|
(void)&ptr; \
|
|
ELIM (expect == strlen (p)); \
|
|
} while (0)
|
|
|
|
/* Have the function take a pointer to pointers to arrays so that each
|
|
test case can use its own pointer to avoid interference between. */
|
|
|
|
void test_char_array_ptr (char (**ppa)[])
|
|
{
|
|
T (char, 0, *parray, "", *parray);
|
|
T (char, 0, *parray, "", &(*parray)[0]);
|
|
|
|
T (char, 1, *parray, "1", &(*parray)[0]);
|
|
T (char, 0, *parray, "1", &(*parray)[1]);
|
|
|
|
T (char, 2, *parray, "12", &(*parray)[0]);
|
|
T (char, 1, *parray, "12", &(*parray)[1]);
|
|
T (char, 0, *parray, "12", &(*parray)[2]);
|
|
|
|
T (char, 3, *parray, "123", &(*parray)[0]);
|
|
T (char, 2, *parray, "123", &(*parray)[1]);
|
|
T (char, 1, *parray, "123", &(*parray)[2]);
|
|
T (char, 0, *parray, "123", &(*parray)[3]);
|
|
|
|
T (char, 3, *parray, "123", ptr);
|
|
T (char, 2, *parray, "123", &ptr[1]);
|
|
T (char, 1, *parray, "123", &ptr[2]);
|
|
T (char, 0, *parray, "123", &ptr[3]);
|
|
}
|
|
|
|
void test_int16_array_ptr (int16_t (**ppa)[])
|
|
{
|
|
T (int16_t, 0, *parray, "", (char*)*parray);
|
|
T (int16_t, 0, *parray, "", (char*)&(*parray)[0]);
|
|
|
|
T (int16_t, 1, *parray, "1", (char*)&(*parray)[0]);
|
|
T (int16_t, 0, *parray, "12", (char*)&(*parray)[1]);
|
|
|
|
T (int16_t, 2, *parray, "12", (char*)&(*parray)[0]);
|
|
T (int16_t, 1, *parray, "12", (char*)&(*parray)[0] + 1);
|
|
T (int16_t, 2, *parray, "1234", (char*)&(*parray)[1]);
|
|
T (int16_t, 1, *parray, "1234", (char*)&(*parray)[1] + 1);
|
|
T (int16_t, 0, *parray, "1234", (char*)&(*parray)[2]);
|
|
|
|
T (int16_t, 6, *parray, "123456", (char*)&(*parray)[0]);
|
|
T (int16_t, 5, *parray, "123456", (char*)&(*parray)[0] + 1);
|
|
T (int16_t, 0, *parray, "123456", (char*)&(*parray)[0] + 6);
|
|
T (int16_t, 4, *parray, "123456", (char*)&(*parray)[1]);
|
|
T (int16_t, 3, *parray, "123456", (char*)&(*parray)[1] + 1);
|
|
T (int16_t, 0, *parray, "123456", (char*)&(*parray)[1] + 4);
|
|
T (int16_t, 2, *parray, "123456", (char*)&(*parray)[2]);
|
|
T (int16_t, 1, *parray, "123456", (char*)&(*parray)[2] + 1);
|
|
T (int16_t, 0, *parray, "123456", (char*)&(*parray)[2] + 2);
|
|
T (int16_t, 0, *parray, "123456", (char*)&(*parray)[3]);
|
|
|
|
T (int16_t, 3, *parray, "123", (char*)ptr);
|
|
T (int16_t, 2, *parray, "123", (char*)&ptr[1]);
|
|
T (int16_t, 1, *parray, "123", (char*)&ptr[2]);
|
|
T (int16_t, 0, *parray, "123", (char*)&ptr[3]);
|
|
}
|
|
|
|
/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
|
|
{ dg-final { scan-tree-dump-times "not_eliminated" 0 "optimized" } } */
|