summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-21 15:47:49 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-21 15:47:49 +0000
commit7e6fef85fa30a2efcb3424ac4c4580ece43f6b70 (patch)
tree62b12d022d86e21d5d3cc6b6d10dd4d31dd8afe3
parent00f6295120f341592f13b7526e1dddf1dc91fe73 (diff)
downloadgcc-7e6fef85fa30a2efcb3424ac4c4580ece43f6b70.tar.gz
PR target/64669
* ccmp.c (used_in_cond_stmt_p): Remove. (expand_ccmp_expr): Don't use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219951 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/ccmp.c41
-rw-r--r--gcc/testsuite/g++.dg/torture/pr64669.C63
3 files changed, 71 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eda4b2d72fb..3f1dda4188d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2015-01-21 Richard Henderson <rth@redhat.com>
+
+ PR target/64669
+ * ccmp.c (used_in_cond_stmt_p): Remove.
+ (expand_ccmp_expr): Don't use it.
+
2015-01-21 Nick Clifton <nickc@redhat.com>
* config/rl78/rl78.c (rl78_calculate_death_notes): Look inside
diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index 903d5a865de..5d1755402d1 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 00000000000..b207739e6d3
--- /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");
+ }
+}