diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-09-23 12:37:17 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-09-23 12:37:17 +0000 |
commit | 5f00d31b3511b980ba6cce712687aad1fff1209b (patch) | |
tree | e2de6d398c204c91c81cb25db0379e97dbb4ae96 /gcc | |
parent | f93344c894d392d4ea52965d371a9ce918aee69e (diff) | |
download | gcc-5f00d31b3511b980ba6cce712687aad1fff1209b.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202826 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr58464.C | 268 | ||||
-rw-r--r-- | gcc/tree-ssa-pre.c | 109 |
4 files changed, 331 insertions, 65 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 15369d6bbe9..ae7308d7164 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 330bb1cc86a..bd6998f77a7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/torture/pr58464.C b/gcc/testsuite/g++.dg/torture/pr58464.C new file mode 100644 index 00000000000..3d9a2279d99 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr58464.C @@ -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; +} diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index c53ec44913a..6c813270eb6 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -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); - - slot = phi_translate_table.find_slot_with_hash (new_pair, - new_pair->hashcode, INSERT); - free (*slot); - *slot = new_pair; + 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; + } + + *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; |