As discussed in the PR, we're committing a layering violation here. Removing that violation fixes the ICE, which is the most important thing for the moment.
Reviewing objdump of the stage3 cc1plus, about 90% of the instances of ccmp instruction are followed by a conditional branch, so combine is usually performing the optimization that the code being removed indended. But there are some instances that aren't optimized, so I opened pr64713 to track that. r~
PR target/64669 * ccmp.c (used_in_cond_stmt_p): Remove. (expand_ccmp_expr): Don't use it. diff --git a/gcc/ccmp.c b/gcc/ccmp.c index 903d5a8..5d17554 100644 --- a/gcc/ccmp.c +++ b/gcc/ccmp.c @@ -90,9 +90,8 @@ along with GCC; see the file COPYING3. If not see - gen_ccmp_first expands the first compare in CCMP. - gen_ccmp_next expands the following compares. - * If the final result is not used in a COND_EXPR (checked by function - used_in_cond_stmt_p), it calls cstorecc4 pattern to store the CC to a - general register. + * We use cstorecc4 pattern to convert the CCmode intermediate to + the integer mode result that expand_normal is expecting. Since the operands of the later compares might clobber CC reg, we do not emit the insns during expand. We keep the insn sequences in two seq @@ -156,31 +155,6 @@ ccmp_candidate_p (gimple g) return false; } -/* Check whether EXP is used in a GIMPLE_COND statement or not. */ -static bool -used_in_cond_stmt_p (tree exp) -{ - bool expand_cond = false; - imm_use_iterator ui; - gimple use_stmt; - FOR_EACH_IMM_USE_STMT (use_stmt, ui, exp) - if (gimple_code (use_stmt) == GIMPLE_COND) - { - tree op1 = gimple_cond_rhs (use_stmt); - if (integer_zerop (op1)) - expand_cond = true; - BREAK_FROM_IMM_USE_STMT (ui); - } - else if (gimple_code (use_stmt) == GIMPLE_ASSIGN - && gimple_expr_code (use_stmt) == COND_EXPR) - { - if (gimple_assign_rhs1 (use_stmt) == exp) - expand_cond = true; - } - - return expand_cond; -} - /* PREV is the CC flag from precvious compares. The function expands the next compare based on G which ops previous compare with CODE. PREP_SEQ returns all insns to prepare opearands for compare. @@ -301,20 +275,9 @@ expand_ccmp_expr (gimple g) enum machine_mode cc_mode = CCmode; tree lhs = gimple_assign_lhs (g); - /* TMP should be CC. If it is used in a GIMPLE_COND, just return it. - Note: Target needs to define "cbranchcc4". */ - if (used_in_cond_stmt_p (lhs)) - { - emit_insn (prep_seq); - emit_insn (gen_seq); - return tmp; - } - #ifdef SELECT_CC_MODE cc_mode = SELECT_CC_MODE (NE, tmp, const0_rtx); #endif - /* If TMP is not used in a GIMPLE_COND, store it with a csctorecc4_optab. - Note: Target needs to define "cstorecc4". */ icode = optab_handler (cstore_optab, cc_mode); if (icode != CODE_FOR_nothing) { diff --git a/gcc/testsuite/g++.dg/torture/pr64669.C b/gcc/testsuite/g++.dg/torture/pr64669.C new file mode 100644 index 0000000..b207739 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr64669.C @@ -0,0 +1,63 @@ +typedef unsigned int source_location; +typedef source_location location_t; +extern void error_at (location_t, const char *, ...) + __attribute__ ((__format__ (__gcc_tdiag__, 2, 3))) + __attribute__ ((__nonnull__ (2))); + +class Lex +{ + static int fetch_char (const char *str, unsigned int *value); + location_t location () const; + const char *advance_one_utf8_char (const char *, unsigned int *, bool *); + const char *advance_one_char (const char *, bool, unsigned int *, bool *); + int lineoff_; + int lineno_; +}; + +int +Lex::fetch_char (const char *p, unsigned int *value) +{ + unsigned char c = *p; + if (c <= 0x7f) + { + return 1; + } + else if ((c & 0xe0) == 0xc0 && (p[1] & 0xc0) == 0x80) + { + *value = (((c & 0x1f) << 6) + (p[1] & 0x3f)); + } + { + *value = (((c & 0xf) << 12) + (p[2] & 0x3f)); + } +} + +const char * +Lex::advance_one_utf8_char (const char *p, unsigned int *value, + bool * issued_error) +{ + *issued_error = false; + if (*p == '\0') + { + *issued_error = true; + return p + 1; + } + int adv = Lex::fetch_char (p, value); + if (*value == 0xfeff && (this->lineno_ != 1 || this->lineoff_ != 0)) + { + *issued_error = true; + } + return p + adv; +} + +const char * +Lex::advance_one_char (const char *p, bool is_single_quote, + unsigned int *value, bool * is_character) +{ + { + bool issued_error; + const char *ret = this->advance_one_utf8_char (p, value, &issued_error); + if (is_single_quote + && (*value == '\'' || *value == '\n') && !issued_error) + error_at (this->location (), "invalid character literal"); + } +}