re PR tree-optimization/84478 (pdftex miscompilation on i386)
PR tree-optimization/84478 * gimple-fold.h (get_range_strlen): Add a bool argument defaulted to false. * gimple-fold.c (get_range_strlen): Make minlen const and assume it can't be NULL. Change FUZZY from bool to int, for 1 add PHI/COND_EXPR support which is conservatively correct, for 2 only stay conservative for maxlen. Formatting and comment capitalization fixes. Add STRICT argument to the 2 argument get_range_strlen, adjust 6 arg get_range_strlen caller and clear minmaxlen[0] and [1] if it returned false. (get_maxval_strlen): Adjust 6 arg get_range_strlen caller. (gimple_fold_builtin_strlen): Pass true as last argument to get_range_strlen. * gcc.c-torture/execute/pr84478.c: New test. Co-Authored-By: Martin Sebor <msebor@redhat.com> From-SVN: r257870
This commit is contained in:
parent
b22dbd03f0
commit
c8602fe612
5 changed files with 120 additions and 32 deletions
|
@ -1,3 +1,20 @@
|
|||
2018-02-21 Jakub Jelinek <jakub@redhat.com>
|
||||
Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/84478
|
||||
* gimple-fold.h (get_range_strlen): Add a bool argument defaulted to
|
||||
false.
|
||||
* gimple-fold.c (get_range_strlen): Make minlen const and assume it
|
||||
can't be NULL. Change FUZZY from bool to int, for 1 add PHI/COND_EXPR
|
||||
support which is conservatively correct, for 2 only stay conservative
|
||||
for maxlen. Formatting and comment capitalization fixes. Add STRICT
|
||||
argument to the 2 argument get_range_strlen, adjust 6 arg
|
||||
get_range_strlen caller and clear minmaxlen[0] and [1] if it returned
|
||||
false.
|
||||
(get_maxval_strlen): Adjust 6 arg get_range_strlen caller.
|
||||
(gimple_fold_builtin_strlen): Pass true as last argument to
|
||||
get_range_strlen.
|
||||
|
||||
2018-02-20 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR middle-end/84095
|
||||
|
|
|
@ -1283,13 +1283,16 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
|
|||
value of ARG in LENGTH[0] and LENGTH[1], respectively.
|
||||
If ARG is an SSA name variable, follow its use-def chains. When
|
||||
TYPE == 0, if LENGTH[1] is not equal to the length we determine or
|
||||
if we are unable to determine the length or value, return False.
|
||||
if we are unable to determine the length or value, return false.
|
||||
VISITED is a bitmap of visited variables.
|
||||
TYPE is 0 if string length should be obtained, 1 for maximum string
|
||||
length and 2 for maximum value ARG can have.
|
||||
When FUZZY is set and the length of a string cannot be determined,
|
||||
When FUZZY is non-zero and the length of a string cannot be determined,
|
||||
the function instead considers as the maximum possible length the
|
||||
size of a character array it may refer to.
|
||||
size of a character array it may refer to. If FUZZY is 2, it will handle
|
||||
PHIs and COND_EXPRs optimistically, if we can determine string length
|
||||
minimum and maximum, it will use the minimum from the ones where it
|
||||
can be determined.
|
||||
Set *FLEXP to true if the range of the string lengths has been
|
||||
obtained from the upper bound of an array at the end of a struct.
|
||||
Such an array may hold a string that's longer than its upper bound
|
||||
|
@ -1297,14 +1300,13 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
|
|||
|
||||
static bool
|
||||
get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
||||
bool fuzzy, bool *flexp)
|
||||
int fuzzy, bool *flexp)
|
||||
{
|
||||
tree var, val = NULL_TREE;
|
||||
gimple *def_stmt;
|
||||
|
||||
/* The minimum and maximum length. The MAXLEN pointer stays unchanged
|
||||
but MINLEN may be cleared during the execution of the function. */
|
||||
tree *minlen = length;
|
||||
/* The minimum and maximum length. */
|
||||
tree *const minlen = length;
|
||||
tree *const maxlen = length + 1;
|
||||
|
||||
if (TREE_CODE (arg) != SSA_NAME)
|
||||
|
@ -1445,12 +1447,11 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
if (!val)
|
||||
return false;
|
||||
|
||||
if (minlen
|
||||
&& (!*minlen
|
||||
|| (type > 0
|
||||
&& TREE_CODE (*minlen) == INTEGER_CST
|
||||
&& TREE_CODE (val) == INTEGER_CST
|
||||
&& tree_int_cst_lt (val, *minlen))))
|
||||
if (!*minlen
|
||||
|| (type > 0
|
||||
&& TREE_CODE (*minlen) == INTEGER_CST
|
||||
&& TREE_CODE (val) == INTEGER_CST
|
||||
&& tree_int_cst_lt (val, *minlen)))
|
||||
*minlen = val;
|
||||
|
||||
if (*maxlen)
|
||||
|
@ -1501,20 +1502,26 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
}
|
||||
else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
|
||||
{
|
||||
tree op2 = gimple_assign_rhs2 (def_stmt);
|
||||
tree op3 = gimple_assign_rhs3 (def_stmt);
|
||||
return get_range_strlen (op2, length, visited, type, fuzzy, flexp)
|
||||
&& get_range_strlen (op3, length, visited, type, fuzzy, flexp);
|
||||
tree ops[2] = { gimple_assign_rhs2 (def_stmt),
|
||||
gimple_assign_rhs3 (def_stmt) };
|
||||
|
||||
for (unsigned int i = 0; i < 2; i++)
|
||||
if (!get_range_strlen (ops[i], length, visited, type, fuzzy,
|
||||
flexp))
|
||||
{
|
||||
if (fuzzy == 2)
|
||||
*maxlen = build_all_ones_cst (size_type_node);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case GIMPLE_PHI:
|
||||
{
|
||||
/* All the arguments of the PHI node must have the same constant
|
||||
length. */
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < gimple_phi_num_args (def_stmt); i++)
|
||||
/* All the arguments of the PHI node must have the same constant
|
||||
length. */
|
||||
for (unsigned i = 0; i < gimple_phi_num_args (def_stmt); i++)
|
||||
{
|
||||
tree arg = gimple_phi_arg (def_stmt, i)->def;
|
||||
|
||||
|
@ -1529,13 +1536,12 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
|
||||
if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp))
|
||||
{
|
||||
if (fuzzy)
|
||||
if (fuzzy == 2)
|
||||
*maxlen = build_all_ones_cst (size_type_node);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -1549,15 +1555,21 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
character arrays, use the upper bound of the array as the maximum
|
||||
length. For example, given an expression like 'x ? array : "xyz"'
|
||||
and array declared as 'char array[8]', MINMAXLEN[0] will be set
|
||||
to 3 and MINMAXLEN[1] to 7, the longest string that could be
|
||||
to 0 and MINMAXLEN[1] to 7, the longest string that could be
|
||||
stored in array.
|
||||
Return true if the range of the string lengths has been obtained
|
||||
from the upper bound of an array at the end of a struct. Such
|
||||
an array may hold a string that's longer than its upper bound
|
||||
due to it being used as a poor-man's flexible array member. */
|
||||
due to it being used as a poor-man's flexible array member.
|
||||
|
||||
STRICT is true if it will handle PHIs and COND_EXPRs conservatively
|
||||
and false if PHIs and COND_EXPRs are to be handled optimistically,
|
||||
if we can determine string length minimum and maximum; it will use
|
||||
the minimum from the ones where it can be determined.
|
||||
STRICT false should be only used for warning code. */
|
||||
|
||||
bool
|
||||
get_range_strlen (tree arg, tree minmaxlen[2])
|
||||
get_range_strlen (tree arg, tree minmaxlen[2], bool strict)
|
||||
{
|
||||
bitmap visited = NULL;
|
||||
|
||||
|
@ -1565,7 +1577,12 @@ get_range_strlen (tree arg, tree minmaxlen[2])
|
|||
minmaxlen[1] = NULL_TREE;
|
||||
|
||||
bool flexarray = false;
|
||||
get_range_strlen (arg, minmaxlen, &visited, 1, true, &flexarray);
|
||||
if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
|
||||
&flexarray))
|
||||
{
|
||||
minmaxlen[0] = NULL_TREE;
|
||||
minmaxlen[1] = NULL_TREE;
|
||||
}
|
||||
|
||||
if (visited)
|
||||
BITMAP_FREE (visited);
|
||||
|
@ -1580,7 +1597,7 @@ get_maxval_strlen (tree arg, int type)
|
|||
tree len[2] = { NULL_TREE, NULL_TREE };
|
||||
|
||||
bool dummy;
|
||||
if (!get_range_strlen (arg, len, &visited, type, false, &dummy))
|
||||
if (!get_range_strlen (arg, len, &visited, type, 0, &dummy))
|
||||
len[1] = NULL_TREE;
|
||||
if (visited)
|
||||
BITMAP_FREE (visited);
|
||||
|
@ -3534,7 +3551,7 @@ gimple_fold_builtin_strlen (gimple_stmt_iterator *gsi)
|
|||
wide_int maxlen;
|
||||
|
||||
tree lenrange[2];
|
||||
if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange)
|
||||
if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange, true)
|
||||
&& lenrange[0] && TREE_CODE (lenrange[0]) == INTEGER_CST
|
||||
&& lenrange[1] && TREE_CODE (lenrange[1]) == INTEGER_CST)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
extern tree create_tmp_reg_or_ssa_name (tree, gimple *stmt = NULL);
|
||||
extern tree canonicalize_constructor_val (tree, tree);
|
||||
extern tree get_symbol_constant_value (tree);
|
||||
extern bool get_range_strlen (tree, tree[2]);
|
||||
extern bool get_range_strlen (tree, tree[2], bool = false);
|
||||
extern tree get_maxval_strlen (tree, int);
|
||||
extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
|
||||
extern bool fold_stmt (gimple_stmt_iterator *);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2018-02-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/84478
|
||||
* gcc.c-torture/execute/pr84478.c: New test.
|
||||
|
||||
2018-02-20 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR middle-end/84095
|
||||
|
|
49
gcc/testsuite/gcc.c-torture/execute/pr84478.c
Normal file
49
gcc/testsuite/gcc.c-torture/execute/pr84478.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* PR tree-optimization/84478 */
|
||||
|
||||
long poolptr;
|
||||
unsigned char *strpool;
|
||||
static const char *poolfilearr[] = {
|
||||
"mu",
|
||||
"",
|
||||
#define A "x",
|
||||
#define B A "xx", A A "xxx", A A A A A
|
||||
#define C B B B B B B B B B B
|
||||
#define D C C C C C C C C C C
|
||||
D C C C C C C C B B B
|
||||
((void *)0)
|
||||
};
|
||||
|
||||
__attribute__((noipa)) long
|
||||
makestring (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((noipa)) long
|
||||
loadpoolstrings (long spare_size)
|
||||
{
|
||||
const char *s;
|
||||
long g = 0;
|
||||
int i = 0, j = 0;
|
||||
while ((s = poolfilearr[j++]))
|
||||
{
|
||||
int l = __builtin_strlen (s);
|
||||
i += l;
|
||||
if (i >= spare_size) return 0;
|
||||
while (l-- > 0) strpool[poolptr++] = *s++;
|
||||
g = makestring ();
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
strpool = __builtin_malloc (4000);
|
||||
if (!strpool)
|
||||
return 0;
|
||||
asm volatile ("" : : : "memory");
|
||||
volatile int r = loadpoolstrings (4000);
|
||||
__builtin_free (strpool);
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue