re PR tree-optimization/58464 (Crashes with SIGSEGV (infinite recursion in phi_translate))
2013-09-23 Richard Biener <rguenther@suse.de> PR tree-optimization/58464 * tree-ssa-pre.c (phi_trans_lookup): Remove. (phi_trans_add): Change to add conditionally on being not present. (phi_translate_1): Remove recursion detection here. (phi_translate): Pre-seed the cache with NULL to catch recursion here in a more generic way. (bitmap_find_leader): Adjust comment. (get_representative_for): Dump value-numbers. (create_expression_by_pieces): Likewise. (insert_into_preds_of_block): Likewise. * g++.dg/torture/pr58464.C: New testcase. From-SVN: r202826
This commit is contained in:
parent
0e26cf7972
commit
984af6ac75
@ -1,3 +1,17 @@
|
||||
2013-09-23 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/58464
|
||||
* tree-ssa-pre.c (phi_trans_lookup): Remove.
|
||||
(phi_trans_add): Change to add conditionally on being not
|
||||
present.
|
||||
(phi_translate_1): Remove recursion detection here.
|
||||
(phi_translate): Pre-seed the cache with NULL to catch
|
||||
recursion here in a more generic way.
|
||||
(bitmap_find_leader): Adjust comment.
|
||||
(get_representative_for): Dump value-numbers.
|
||||
(create_expression_by_pieces): Likewise.
|
||||
(insert_into_preds_of_block): Likewise.
|
||||
|
||||
2013-09-23 Christian Bruel <christian.bruel@st.com>
|
||||
|
||||
PR target/58475
|
||||
|
@ -1,3 +1,8 @@
|
||||
2013-09-23 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/58464
|
||||
* g++.dg/torture/pr58464.C: New testcase.
|
||||
|
||||
2013-09-23 Christian Bruel <christian.bruel@st.com>
|
||||
|
||||
PR target/58475
|
||||
|
268
gcc/testsuite/g++.dg/torture/pr58464.C
Normal file
268
gcc/testsuite/g++.dg/torture/pr58464.C
Normal file
@ -0,0 +1,268 @@
|
||||
// { dg-do compile }
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
extern "C" void *memcpy(void *, const void *, size_t);
|
||||
void *xmalloc(size_t);
|
||||
enum {
|
||||
_sch_isdigit, _sch_isidst, _sch_isidnum
|
||||
};
|
||||
extern const unsigned _sch_istable[256];
|
||||
typedef struct ht cpp_hash_table;
|
||||
typedef struct ht_identifier *hashnode;
|
||||
enum ht_lookup_option {
|
||||
HT_NO_INSERT
|
||||
};
|
||||
struct ht {
|
||||
struct cpp_reader *pfile;
|
||||
};
|
||||
hashnode ht_lookup_with_hash(cpp_hash_table *, unsigned char *, size_t, unsigned, ht_lookup_option);
|
||||
typedef unsigned source_location;
|
||||
enum cpp_ttype {
|
||||
CPP_OTHER, CPP_STRING, CPP_STRING16, CPP_UTF8STRING
|
||||
};
|
||||
struct cpp_token {
|
||||
source_location src_loc;
|
||||
};
|
||||
typedef int cppchar_t;
|
||||
struct cpp_options {
|
||||
char user_literals;
|
||||
unsigned warn_literal_suffix;
|
||||
};
|
||||
enum node_type { };
|
||||
struct cpp_hashnode {
|
||||
node_type type:6;
|
||||
};
|
||||
enum {
|
||||
CPP_DL_ERROR
|
||||
};
|
||||
enum {
|
||||
CPP_W_LITERAL_SUFFIX
|
||||
};
|
||||
bool cpp_error_with_line(cpp_reader *, int, source_location, unsigned, ...);
|
||||
bool cpp_warning_with_line(cpp_reader *, int, source_location, unsigned, const char *);
|
||||
cpp_ttype cpp_userdef_string_add_type(cpp_ttype);
|
||||
cpp_ttype cpp_userdef_char_add_type(cpp_ttype);
|
||||
typedef unsigned char uchar;
|
||||
struct _cpp_buff {
|
||||
_cpp_buff *next;
|
||||
unsigned char *base, *cur, *limit;
|
||||
};
|
||||
_cpp_buff *_cpp_get_buff(cpp_reader *, size_t);
|
||||
void _cpp_release_buff(cpp_reader *, _cpp_buff *);
|
||||
unsigned char *_cpp_unaligned_alloc(cpp_reader *, size_t);
|
||||
struct lexer_state {
|
||||
unsigned skipping;
|
||||
unsigned angled_headers;
|
||||
};
|
||||
struct _cpp_line_note {
|
||||
unsigned pos;
|
||||
unsigned type;
|
||||
};
|
||||
struct cpp_buffer {
|
||||
unsigned char *cur;
|
||||
unsigned char *line_base;
|
||||
_cpp_line_note *notes;
|
||||
unsigned cur_note;
|
||||
};
|
||||
struct cpp_reader {
|
||||
cpp_buffer *buffer;
|
||||
lexer_state state;
|
||||
_cpp_buff *u_buff;
|
||||
_cpp_buff *free_buffs;
|
||||
ht *hash_table;
|
||||
cpp_options opts;
|
||||
};
|
||||
static void create_literal(cpp_reader *pfile, cpp_token *, uchar *, unsigned len, cpp_ttype type)
|
||||
{
|
||||
uchar *dest = _cpp_unaligned_alloc(pfile, len + 1);
|
||||
dest[len] = type;
|
||||
}
|
||||
static void bufring_append(cpp_reader *pfile, uchar *base, size_t len, _cpp_buff **first_buff_p, _cpp_buff **last_buff_p)
|
||||
{
|
||||
_cpp_buff *first_buff = *first_buff_p;
|
||||
_cpp_buff *last_buff = *last_buff_p;
|
||||
if (!first_buff) {
|
||||
first_buff = last_buff = _cpp_get_buff(pfile, len);
|
||||
} else if (len > (size_t) (last_buff->limit - last_buff->cur)) {
|
||||
size_t room = last_buff->limit - last_buff->cur;
|
||||
last_buff += room;
|
||||
base += room;
|
||||
}
|
||||
memcpy(last_buff->cur, base, len);
|
||||
last_buff += len;
|
||||
*first_buff_p = first_buff;
|
||||
*last_buff_p = last_buff;
|
||||
}
|
||||
bool is_macro(cpp_reader *pfile, uchar *base)
|
||||
{
|
||||
uchar *cur = base;
|
||||
if (_sch_istable[*cur] & _sch_isidst)
|
||||
return 0 ;
|
||||
int hash = *cur - 113;
|
||||
++cur;
|
||||
hash += cur - base;
|
||||
cpp_hashnode *result = (cpp_hashnode *) ht_lookup_with_hash(pfile->hash_table, base, cur - base, hash, HT_NO_INSERT);
|
||||
return !result ? 0 : result->type;
|
||||
}
|
||||
static void lex_raw_string(cpp_reader *pfile, cpp_token *token, uchar *base, uchar *cur)
|
||||
{
|
||||
uchar raw_prefix[17];
|
||||
uchar temp_buffer[18];
|
||||
uchar *orig_base;
|
||||
unsigned raw_prefix_len = 0, raw_suffix_len;
|
||||
enum raw_str_phase { RAW_STR_PREFIX, RAW_STR };
|
||||
raw_str_phase phase = RAW_STR_PREFIX;
|
||||
cpp_ttype type;
|
||||
size_t total_len;
|
||||
size_t temp_buffer_len = 0;
|
||||
_cpp_buff *first_buff = 0, *last_buff = 0;
|
||||
size_t raw_prefix_start;
|
||||
_cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note];
|
||||
raw_prefix_start = cur - base;
|
||||
for (;;) {
|
||||
cppchar_t c;
|
||||
while (note->pos)
|
||||
++note;
|
||||
for (; note->pos; ++note) {
|
||||
switch (note->type) {
|
||||
case ' ':
|
||||
bufring_append(pfile, base, cur - base, &first_buff, &last_buff);
|
||||
base = cur;
|
||||
bufring_append(pfile, (uchar *) "\\", 1, &first_buff, &last_buff);
|
||||
if (__builtin_expect(temp_buffer_len < 17, 0) && base) {
|
||||
memcpy(temp_buffer + temp_buffer_len, "\\", 1);
|
||||
temp_buffer_len++;
|
||||
}
|
||||
if (note->type) {
|
||||
if (__builtin_expect(temp_buffer_len < 17, 0)) {
|
||||
memcpy(temp_buffer + temp_buffer_len, " ", 1);
|
||||
temp_buffer_len++;
|
||||
}
|
||||
}
|
||||
bufring_append(pfile, (uchar *) "\n", 1, &first_buff, &last_buff);
|
||||
memcpy(temp_buffer + temp_buffer_len, "\n", 1);
|
||||
temp_buffer_len++;
|
||||
}
|
||||
}
|
||||
temp_buffer[temp_buffer_len++] = c;
|
||||
if (phase == RAW_STR_PREFIX) {
|
||||
while (raw_prefix_len < temp_buffer_len) {
|
||||
switch (raw_prefix[raw_prefix_len]) {
|
||||
case '\'':
|
||||
raw_prefix_len++;
|
||||
}
|
||||
if (raw_prefix[raw_prefix_len]) {
|
||||
int col = cur - pfile->buffer->line_base + 1;
|
||||
if (raw_prefix_len)
|
||||
cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col);
|
||||
else if (raw_prefix[raw_prefix_len] == '\n')
|
||||
cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col);
|
||||
else
|
||||
cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col, (size_t) raw_prefix);
|
||||
pfile->buffer->cur = orig_base + 1;
|
||||
create_literal(pfile, token, orig_base, raw_prefix_start, CPP_OTHER);
|
||||
_cpp_release_buff(pfile, first_buff);
|
||||
return;
|
||||
}
|
||||
phase = RAW_STR;
|
||||
}
|
||||
continue;
|
||||
(void) raw_suffix_len;
|
||||
}
|
||||
while (_sch_istable[*cur] & _sch_isidnum)
|
||||
++cur;
|
||||
}
|
||||
create_literal(pfile, token, base, cur - base, type);
|
||||
uchar *dest = _cpp_unaligned_alloc(pfile, total_len + (cur - base));
|
||||
dest[cur - base] = '\0';
|
||||
}
|
||||
void lex_string(cpp_reader *pfile, cpp_token *token, uchar *base)
|
||||
{
|
||||
bool saw_NUL = 0;
|
||||
uchar *cur;
|
||||
cppchar_t terminator;
|
||||
cpp_ttype type;
|
||||
cur = base;
|
||||
terminator = *cur++;
|
||||
if (terminator == 'L' || terminator == 'U') {
|
||||
terminator = *cur++;
|
||||
} else if (terminator == 'u') {
|
||||
terminator = *cur++;
|
||||
if (terminator == '8')
|
||||
terminator = *cur++;
|
||||
}
|
||||
if (terminator == 'R') {
|
||||
lex_raw_string(pfile, token, base, cur);
|
||||
return;
|
||||
}
|
||||
if (terminator)
|
||||
type = base ? (base[1] ? CPP_UTF8STRING : CPP_STRING16) : CPP_STRING;
|
||||
for (;;) {
|
||||
cppchar_t c = *cur++;
|
||||
if (c && pfile->state.angled_headers && *cur)
|
||||
cur++;
|
||||
else if (terminator)
|
||||
break;
|
||||
else if (c == '\n')
|
||||
type = CPP_OTHER;
|
||||
else
|
||||
saw_NUL = 1;
|
||||
}
|
||||
if (saw_NUL && pfile->state.skipping)
|
||||
if (pfile->opts.user_literals) {
|
||||
if (is_macro(pfile, cur))
|
||||
if (pfile->opts.warn_literal_suffix)
|
||||
cpp_warning_with_line(pfile, CPP_W_LITERAL_SUFFIX, token->src_loc, 0, "invalid suffix on literal; C++11 requires ");
|
||||
if (_sch_istable[*cur] & _sch_isidst) {
|
||||
type = cpp_userdef_char_add_type(type);
|
||||
type = cpp_userdef_string_add_type(type);
|
||||
++cur;
|
||||
while (_sch_istable[*cur] & _sch_isidnum)
|
||||
++cur;
|
||||
}
|
||||
}
|
||||
pfile->buffer->cur = cur;
|
||||
create_literal(pfile, token, base, cur - base, type);
|
||||
}
|
||||
_cpp_buff *new_buff(size_t len)
|
||||
{
|
||||
_cpp_buff *result;
|
||||
unsigned char *base;
|
||||
if (len < 8000)
|
||||
len = 8000;
|
||||
base = (unsigned char *) xmalloc(sizeof(char) * (len + sizeof(_cpp_buff)));
|
||||
result = (_cpp_buff *) (base + len);
|
||||
result->cur = base;
|
||||
return result;
|
||||
}
|
||||
void _cpp_release_buff(cpp_reader *pfile, _cpp_buff *buff)
|
||||
{
|
||||
_cpp_buff *end = buff;
|
||||
while (end->next)
|
||||
end = end->next;
|
||||
end->next = pfile->free_buffs;
|
||||
}
|
||||
_cpp_buff *_cpp_get_buff(cpp_reader *pfile, size_t min_size)
|
||||
{
|
||||
_cpp_buff *result, **p = &pfile->free_buffs;
|
||||
for (;;) {
|
||||
size_t size;
|
||||
if (*p)
|
||||
return new_buff(min_size);
|
||||
size = result->limit - result->base;
|
||||
if (size && size + min_size * 3 / 2)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
unsigned char *_cpp_unaligned_alloc(cpp_reader *pfile, size_t len)
|
||||
{
|
||||
_cpp_buff *buff = pfile->u_buff;
|
||||
unsigned char *result = buff->cur;
|
||||
if (len > (size_t) (buff->limit - result)) {
|
||||
buff = _cpp_get_buff(pfile, len);
|
||||
buff->next = pfile->u_buff;
|
||||
result = buff->cur;
|
||||
}
|
||||
buff->cur = result + len;
|
||||
return result;
|
||||
}
|
@ -525,46 +525,31 @@ expr_pred_trans_d::equal (const value_type *ve1,
|
||||
expression and predecessor. */
|
||||
static hash_table <expr_pred_trans_d> phi_translate_table;
|
||||
|
||||
/* Search in the phi translation table for the translation of
|
||||
expression E in basic block PRED.
|
||||
Return the translated value, if found, NULL otherwise. */
|
||||
|
||||
static inline pre_expr
|
||||
phi_trans_lookup (pre_expr e, basic_block pred)
|
||||
{
|
||||
expr_pred_trans_t *slot;
|
||||
struct expr_pred_trans_d ept;
|
||||
|
||||
ept.e = e;
|
||||
ept.pred = pred;
|
||||
ept.hashcode = iterative_hash_hashval_t (pre_expr_d::hash (e), pred->index);
|
||||
slot = phi_translate_table.find_slot_with_hash (&ept, ept.hashcode,
|
||||
NO_INSERT);
|
||||
if (!slot)
|
||||
return NULL;
|
||||
else
|
||||
return (*slot)->v;
|
||||
}
|
||||
|
||||
|
||||
/* Add the tuple mapping from {expression E, basic block PRED} to
|
||||
value V, to the phi translation table. */
|
||||
the phi translation table and return whether it pre-existed. */
|
||||
|
||||
static inline void
|
||||
phi_trans_add (pre_expr e, pre_expr v, basic_block pred)
|
||||
static inline bool
|
||||
phi_trans_add (expr_pred_trans_t *entry, pre_expr e, basic_block pred)
|
||||
{
|
||||
expr_pred_trans_t *slot;
|
||||
expr_pred_trans_t new_pair = XNEW (struct expr_pred_trans_d);
|
||||
new_pair->e = e;
|
||||
new_pair->pred = pred;
|
||||
new_pair->v = v;
|
||||
new_pair->hashcode = iterative_hash_hashval_t (pre_expr_d::hash (e),
|
||||
pred->index);
|
||||
expr_pred_trans_d tem;
|
||||
hashval_t hash = iterative_hash_hashval_t (pre_expr_d::hash (e),
|
||||
pred->index);
|
||||
tem.e = e;
|
||||
tem.pred = pred;
|
||||
tem.hashcode = hash;
|
||||
slot = phi_translate_table.find_slot_with_hash (&tem, hash, INSERT);
|
||||
if (*slot)
|
||||
{
|
||||
*entry = *slot;
|
||||
return true;
|
||||
}
|
||||
|
||||
slot = phi_translate_table.find_slot_with_hash (new_pair,
|
||||
new_pair->hashcode, INSERT);
|
||||
free (*slot);
|
||||
*slot = new_pair;
|
||||
*entry = *slot = XNEW (struct expr_pred_trans_d);
|
||||
(*entry)->e = e;
|
||||
(*entry)->pred = pred;
|
||||
(*entry)->hashcode = hash;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -1420,7 +1405,7 @@ get_representative_for (const pre_expr e)
|
||||
print_generic_expr (dump_file, name, 0);
|
||||
fprintf (dump_file, " for expression:");
|
||||
print_pre_expr (dump_file, e);
|
||||
fprintf (dump_file, "\n");
|
||||
fprintf (dump_file, " (%04d)\n", value_id);
|
||||
}
|
||||
|
||||
return name;
|
||||
@ -1561,23 +1546,16 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
|
||||
leader = find_leader_in_sets (op_val_id, set1, set2);
|
||||
if (!leader)
|
||||
break;
|
||||
/* Make sure we do not recursively translate ourselves
|
||||
like for translating a[n_1] with the leader for
|
||||
n_1 being a[n_1]. */
|
||||
if (get_expression_id (leader) != get_expression_id (expr))
|
||||
opresult = phi_translate (leader, set1, set2, pred, phiblock);
|
||||
if (!opresult)
|
||||
break;
|
||||
if (opresult != leader)
|
||||
{
|
||||
opresult = phi_translate (leader, set1, set2,
|
||||
pred, phiblock);
|
||||
if (!opresult)
|
||||
tree name = get_representative_for (opresult);
|
||||
if (!name)
|
||||
break;
|
||||
if (opresult != leader)
|
||||
{
|
||||
tree name = get_representative_for (opresult);
|
||||
if (!name)
|
||||
break;
|
||||
changed |= name != op[n];
|
||||
op[n] = name;
|
||||
}
|
||||
changed |= name != op[n];
|
||||
op[n] = name;
|
||||
}
|
||||
}
|
||||
if (n != 3)
|
||||
@ -1751,6 +1729,7 @@ static pre_expr
|
||||
phi_translate (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
|
||||
basic_block pred, basic_block phiblock)
|
||||
{
|
||||
expr_pred_trans_t slot = NULL;
|
||||
pre_expr phitrans;
|
||||
|
||||
if (!expr)
|
||||
@ -1763,21 +1742,21 @@ phi_translate (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
|
||||
if (value_id_constant_p (get_expr_value_id (expr)))
|
||||
return expr;
|
||||
|
||||
/* Don't add translations of NAMEs as those are cheap to translate. */
|
||||
if (expr->kind != NAME)
|
||||
{
|
||||
phitrans = phi_trans_lookup (expr, pred);
|
||||
if (phitrans)
|
||||
return phitrans;
|
||||
if (phi_trans_add (&slot, expr, pred))
|
||||
return slot->v;
|
||||
/* Store NULL for the value we want to return in the case of
|
||||
recursing. */
|
||||
slot->v = NULL;
|
||||
}
|
||||
|
||||
/* Translate. */
|
||||
phitrans = phi_translate_1 (expr, set1, set2, pred, phiblock);
|
||||
|
||||
/* Don't add empty translations to the cache. Neither add
|
||||
translations of NAMEs as those are cheap to translate. */
|
||||
if (phitrans
|
||||
&& expr->kind != NAME)
|
||||
phi_trans_add (expr, phitrans, pred);
|
||||
if (slot)
|
||||
slot->v = phitrans;
|
||||
|
||||
return phitrans;
|
||||
}
|
||||
@ -1822,9 +1801,8 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, basic_block pred,
|
||||
}
|
||||
|
||||
/* Find the leader for a value (i.e., the name representing that
|
||||
value) in a given set, and return it. If STMT is non-NULL it
|
||||
makes sure the defining statement for the leader dominates it.
|
||||
Return NULL if no leader is found. */
|
||||
value) in a given set, and return it. Return NULL if no leader
|
||||
is found. */
|
||||
|
||||
static pre_expr
|
||||
bitmap_find_leader (bitmap_set_t set, unsigned int val)
|
||||
@ -3005,7 +2983,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
|
||||
{
|
||||
fprintf (dump_file, "Inserted ");
|
||||
print_gimple_stmt (dump_file, newstmt, 0, 0);
|
||||
fprintf (dump_file, " in predecessor %d\n", block->index);
|
||||
fprintf (dump_file, " in predecessor %d (%04d)\n",
|
||||
block->index, value_id);
|
||||
}
|
||||
|
||||
return name;
|
||||
@ -3280,7 +3259,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
|
||||
{
|
||||
fprintf (dump_file, "Created phi ");
|
||||
print_gimple_stmt (dump_file, phi, 0, 0);
|
||||
fprintf (dump_file, " in block %d\n", block->index);
|
||||
fprintf (dump_file, " in block %d (%04d)\n", block->index, val);
|
||||
}
|
||||
pre_stats.phis++;
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user