aboutsummaryrefslogtreecommitdiff
path: root/gcc/compare-elim.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2018-11-19 10:25:35 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2018-11-19 10:25:35 +0000
commit0ea52812a8a6c60c580529d1d3dbe144f8e6fc2f (patch)
tree6c9ca6f8eaa675d23da1de4346ac91ba6454a6bb /gcc/compare-elim.c
parentfc315b476948df23d6d9594b0d0107daafeaf8a7 (diff)
downloadgcc-0ea52812a8a6c60c580529d1d3dbe144f8e6fc2f.zip
gcc-0ea52812a8a6c60c580529d1d3dbe144f8e6fc2f.tar.gz
gcc-0ea52812a8a6c60c580529d1d3dbe144f8e6fc2f.tar.bz2
compare-elim.c (struct comparison): Add not_in_a field.
* compare-elim.c (struct comparison): Add not_in_a field. (is_not): New static function. (strip_not): Likewise. (conforming_compare): Handle a NOT in the first operand. (can_eliminate_compare): Likewise. (find_comparison_dom_walker::before_dom_children): Likewise. (try_eliminate_compare): Likewise. * config/visium/visium.md (negsi2_insn_set_carry): Turn into... (neg<mode>2_insn_set_carry): ...this and add missing NEG operation. From-SVN: r266268
Diffstat (limited to 'gcc/compare-elim.c')
-rw-r--r--gcc/compare-elim.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index 8afbe76..f38e576 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -123,10 +123,32 @@ struct comparison
/* True if its inputs are still valid at the end of the block. */
bool inputs_valid;
+
+ /* Whether IN_A is wrapped in a NOT before being compared. */
+ bool not_in_a;
};
static vec<comparison *> all_compares;
+/* Return whether X is a NOT unary expression. */
+
+static bool
+is_not (rtx x)
+{
+ return GET_CODE (x) == NOT;
+}
+
+/* Strip a NOT unary expression around X, if any. */
+
+static rtx
+strip_not (rtx x)
+{
+ if (is_not (x))
+ return XEXP (x, 0);
+
+ return x;
+}
+
/* Look for a "conforming" comparison, as defined above. If valid, return
the rtx for the COMPARE itself. */
@@ -147,7 +169,7 @@ conforming_compare (rtx_insn *insn)
if (!REG_P (dest) || REGNO (dest) != targetm.flags_regnum)
return NULL;
- if (!REG_P (XEXP (src, 0)))
+ if (!REG_P (strip_not (XEXP (src, 0))))
return NULL;
if (CONSTANT_P (XEXP (src, 1)) || REG_P (XEXP (src, 1)))
@@ -278,10 +300,13 @@ can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
return false;
/* Make sure the compare is redundant with the previous. */
- if (!rtx_equal_p (XEXP (compare, 0), cmp->in_a)
+ if (!rtx_equal_p (strip_not (XEXP (compare, 0)), cmp->in_a)
|| !rtx_equal_p (XEXP (compare, 1), cmp->in_b))
return false;
+ if (is_not (XEXP (compare, 0)) != cmp->not_in_a)
+ return false;
+
/* New mode must be compatible with the previous compare mode. */
machine_mode new_mode
= targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode);
@@ -365,8 +390,9 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
last_cmp = XCNEW (struct comparison);
last_cmp->insn = insn;
last_cmp->prev_clobber = last_clobber;
- last_cmp->in_a = XEXP (src, 0);
+ last_cmp->in_a = strip_not (XEXP (src, 0));
last_cmp->in_b = XEXP (src, 1);
+ last_cmp->not_in_a = is_not (XEXP (src, 0));
last_cmp->eh_note = eh_note;
last_cmp->orig_mode = GET_MODE (src);
if (last_cmp->in_b == const0_rtx
@@ -837,7 +863,9 @@ try_eliminate_compare (struct comparison *cmp)
flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum);
/* Generate a new comparison for installation in the setter. */
- rtx y = copy_rtx (cmp_a);
+ rtx y = cmp->not_in_a
+ ? gen_rtx_NOT (GET_MODE (cmp_a), copy_rtx (cmp_a))
+ : copy_rtx (cmp_a);
y = gen_rtx_COMPARE (GET_MODE (flags), y, copy_rtx (cmp_b));
y = gen_rtx_SET (flags, y);