180 lines
4.7 KiB
C
180 lines
4.7 KiB
C
/* PRE tree-optimization/90626 - fold strcmp(a, b) == 0 to zero when
|
|
one string length is exact and the other is unequal
|
|
{ dg-do compile }
|
|
{ dg-options "-O2 -Wall -Wno-string-compare -fdump-tree-optimized -ftrack-macro-expansion=0" } */
|
|
|
|
#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_IF_TRUE(expr) \
|
|
if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
|
|
|
|
/* Macro to emit a call to a function named
|
|
call_made_in_{true,false}_branch_on_line_NNN()
|
|
for each call that's expected to be retained. The dg-final
|
|
scan-tree-dump-time directive at the bottom of the test verifies
|
|
that the expected number of both kinds of calls appears in output
|
|
(a pair for each line with the invocation of the KEEP() macro. */
|
|
#define TEST_KEEP(expr) \
|
|
if (expr) \
|
|
FAIL (made_in_true_branch); \
|
|
else \
|
|
FAIL (made_in_false_branch)
|
|
|
|
#define FOLD(init1, init2, arg1, arg2, bnd) \
|
|
do { \
|
|
char a[8], b[8]; \
|
|
sink (a, b); \
|
|
memcpy (a, init1, sizeof init1 - 1); \
|
|
memcpy (b, init2, sizeof init2 - 1); \
|
|
ELIM_IF_TRUE (0 != CMPFUNC (arg1, arg2, bnd)); \
|
|
} while (0)
|
|
|
|
#define KEEP(init1, init2, arg1, arg2, bnd) \
|
|
do { \
|
|
char a[8], b[8]; \
|
|
sink (a, b); \
|
|
memcpy (a, init1, sizeof init1 - 1); \
|
|
memcpy (b, init2, sizeof init2 - 1); \
|
|
TEST_KEEP (0 == CMPFUNC (arg1, arg2, bnd)); \
|
|
} while (0)
|
|
|
|
const char s0[1] = "";
|
|
const char s00[2] = "\0";
|
|
const char s10[2] = "1";
|
|
const char s20[2] = "2";
|
|
|
|
void sink (void*, ...);
|
|
|
|
void test_strcmp_elim (void)
|
|
{
|
|
#undef CMPFUNC
|
|
#define CMPFUNC(a, b, dummy) strcmp (a, b)
|
|
|
|
FOLD (s00, s10, "\0", "1", -1);
|
|
FOLD (s00, s10, "\0", b, -1);
|
|
FOLD (s00, s10, "\0", s10, -1);
|
|
|
|
FOLD (s00, s10, s0, "1", -1);
|
|
FOLD (s00, s10, s0, b, -1);
|
|
FOLD (s00, s10, s0, s10, -1);
|
|
|
|
FOLD ("\0", "1", s0, "1", -1);
|
|
FOLD ("\0", "1", s0, b, -1);
|
|
FOLD ("\0", "1", s0, s10, -1);
|
|
|
|
FOLD ("2", "\0", "2", "\0", -1);
|
|
FOLD ("2", "\0", s20, s0, -1);
|
|
|
|
FOLD ("\0", "1", a, b, -1);
|
|
FOLD ("2", "\0", a, b, -1);
|
|
|
|
FOLD ("4\0", "44", a, b, -1);
|
|
FOLD ("55", "5\0", a, b, -1);
|
|
|
|
FOLD ("666\0", "6666", a, "6666", -1);
|
|
FOLD ("666\0", "6666", a, b, -1);
|
|
FOLD ("7777", "777\0", a, b, -1);
|
|
|
|
/* Avoid testing substrings of equal length with different characters.
|
|
The optimization doesn't have access to the contents of the strings
|
|
so it can't determine whether they are equal.
|
|
|
|
FOLD ("111\0", "112", a, b, -1);
|
|
FOLD ("112", "111\0", a, b, -1); */
|
|
}
|
|
|
|
const char s123[] = "123";
|
|
const char s1230[] = "123\0";
|
|
|
|
const char s1234[] = "1234";
|
|
const char s12340[] = "1234\0";
|
|
|
|
void test_strncmp_elim (void)
|
|
{
|
|
#undef CMPFUNC
|
|
#define CMPFUNC(a, b, n) strncmp (a, b, n)
|
|
|
|
FOLD (s1230, s1234, "123", "1234", 4);
|
|
FOLD (s1234, s1230, "1234", "123", 4);
|
|
|
|
FOLD (s1230, s1234, "123", s1234, 4);
|
|
FOLD (s1234, s1230, "1234", s123, 4);
|
|
|
|
FOLD (s1230, s1234, s123, "1234", 4);
|
|
FOLD (s1234, s1230, s1234, "123", 4);
|
|
|
|
FOLD (s1230, s1234, s123, b, 4);
|
|
FOLD (s1234, s1230, s1234, b, 4);
|
|
|
|
FOLD (s1230, s1234, a, b, 4);
|
|
FOLD (s1234, s1230, a, b, 4);
|
|
|
|
FOLD ("123\0", "1234", a, b, 5);
|
|
FOLD ("1234", "123\0", a, b, 5);
|
|
}
|
|
|
|
|
|
#line 1000
|
|
|
|
void test_strcmp_keep (const char *s, const char *t)
|
|
{
|
|
#undef CMPFUNC
|
|
#define CMPFUNC(a, b, dummy) strcmp (a, b)
|
|
|
|
KEEP ("123", "123\0", a, b, /* bnd = */ -1);
|
|
KEEP ("123\0", "123", a, b, -1);
|
|
|
|
{
|
|
char a[8], b[8];
|
|
sink (a, b);
|
|
strcpy (a, s);
|
|
strcpy (b, t);
|
|
TEST_KEEP (0 == strcmp (a, b));
|
|
}
|
|
}
|
|
|
|
|
|
void test_strncmp_keep (const char *s, const char *t)
|
|
{
|
|
#undef CMPFUNC
|
|
#define CMPFUNC(a, b, n) strncmp (a, b, n)
|
|
|
|
KEEP ("1", "1", a, b, 2);
|
|
|
|
KEEP ("1\0", "1", a, b, 2);
|
|
KEEP ("1", "1\0", a, b, 2);
|
|
|
|
KEEP ("12\0", "12", a, b, 2);
|
|
KEEP ("12", "12\0", a, b, 2);
|
|
|
|
KEEP ("111\0", "111", a, b, 3);
|
|
KEEP ("112", "112\0", a, b, 3);
|
|
|
|
{
|
|
char a[8], b[8];
|
|
sink (a, b);
|
|
strcpy (a, s);
|
|
strcpy (b, t);
|
|
TEST_KEEP (0 == strncmp (a, b, sizeof a));
|
|
}
|
|
}
|
|
|
|
/* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
|
|
|
|
{ dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 11 "optimized" } }
|
|
{ dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 11 "optimized" } } */
|