aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2002-04-03 03:21:29 +0000
committerHans-Peter Nilsson <hp@gcc.gnu.org>2002-04-03 03:21:29 +0000
commit5add6d1a6d7221a24424c78a6eff9981e281043c (patch)
tree81d13ae636c1c2ef3fc57e33050a792f8398c3e7 /gcc
parent2e839a04cf14dadf85f376c4e2c6ba13945ff73b (diff)
downloadgcc-5add6d1a6d7221a24424c78a6eff9981e281043c.zip
gcc-5add6d1a6d7221a24424c78a6eff9981e281043c.tar.gz
gcc-5add6d1a6d7221a24424c78a6eff9981e281043c.tar.bz2
combine.c (simplify_comparison): Avoid narrowing a comparison with a paradoxical subreg when...
* combine.c (simplify_comparison): Avoid narrowing a comparison with a paradoxical subreg when doing so would drop signficant bits. Co-Authored-By: Hans-Peter Nilsson <hp@bitrange.com> From-SVN: r51785
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/combine.c64
2 files changed, 47 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5559699..ed2f083 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2002-04-03 Jeffrey A Law (law@redhat.com)
+ Hans-Peter Nilsson <hp@bitrange.com>
+
+ * combine.c (simplify_comparison): Avoid narrowing a comparison
+ with a paradoxical subreg when doing so would drop signficant bits.
+
2002-04-02 Steve Ellcey <sje@cup.hp.com>
* builtins.c (expand_builtin_prefetch): Force op0 pointer to Pmode
diff --git a/gcc/combine.c b/gcc/combine.c
index de3bcef..9a9d648 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -10955,38 +10955,56 @@ simplify_comparison (code, pop0, pop1)
/* Now make any compound operations involved in this comparison. Then,
check for an outmost SUBREG on OP0 that is not doing anything or is
- paradoxical. The latter case can only occur when it is known that the
- "extra" bits will be zero. Therefore, it is safe to remove the SUBREG.
- We can never remove a SUBREG for a non-equality comparison because the
- sign bit is in a different place in the underlying object. */
+ paradoxical. The latter transformation must only be performed when
+ it is known that the "extra" bits will be the same in op0 and op1 or
+ that they don't matter. There are three cases to consider:
+
+ 1. SUBREG_REG (op0) is a register. In this case the bits are don't
+ care bits and we can assume they have any convenient value. So
+ making the transformation is safe.
+
+ 2. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is not defined.
+ In this case the upper bits of op0 are undefined. We should not make
+ the simplification in that case as we do not know the contents of
+ those bits.
+
+ 3. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is defined and not
+ NIL. In that case we know those bits are zeros or ones. We must
+ also be sure that they are the same as the upper bits of op1.
+
+ We can never remove a SUBREG for a non-equality comparison because
+ the sign bit is in a different place in the underlying object. */
op0 = make_compound_operation (op0, op1 == const0_rtx ? COMPARE : SET);
op1 = make_compound_operation (op1, SET);
if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
+ /* Case 3 above, to sometimes allow (subreg (mem x)), isn't
+ implemented. */
+ && GET_CODE (SUBREG_REG (op0)) == REG
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
&& GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
- && (code == NE || code == EQ)
- && ((GET_MODE_SIZE (GET_MODE (op0))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))))
+ && (code == NE || code == EQ))
{
- op0 = SUBREG_REG (op0);
- op1 = gen_lowpart_for_combine (GET_MODE (op0), op1);
- }
+ if (GET_MODE_SIZE (GET_MODE (op0))
+ > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+ {
+ op0 = SUBREG_REG (op0);
+ op1 = gen_lowpart_for_combine (GET_MODE (op0), op1);
+ }
+ else if ((GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && (nonzero_bits (SUBREG_REG (op0),
+ GET_MODE (SUBREG_REG (op0)))
+ & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+ {
+ tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)), op1);
- else if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
- && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
- && (code == NE || code == EQ)
- && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
- <= HOST_BITS_PER_WIDE_INT)
- && (nonzero_bits (SUBREG_REG (op0), GET_MODE (SUBREG_REG (op0)))
- & ~GET_MODE_MASK (GET_MODE (op0))) == 0
- && (tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)),
- op1),
- (nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
- & ~GET_MODE_MASK (GET_MODE (op0))) == 0))
- op0 = SUBREG_REG (op0), op1 = tem;
+ if ((nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
+ & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+ op0 = SUBREG_REG (op0), op1 = tem;
+ }
+ }
/* We now do the opposite procedure: Some machines don't have compare
insns in all modes. If OP0's mode is an integer mode smaller than a