]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
combine.c (simplify_comparison): Avoid narrowing a comparison with a paradoxical...
authorJeff Law <law@redhat.com>
Wed, 3 Apr 2002 03:21:29 +0000 (03:21 +0000)
committerHans-Peter Nilsson <hp@gcc.gnu.org>
Wed, 3 Apr 2002 03:21:29 +0000 (03:21 +0000)
* 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

gcc/ChangeLog
gcc/combine.c

index 55596999468a64c34cdebdd8b5913c24991dd3f9..ed2f08343946f24ea6ae702f9065ddff6b805209 100644 (file)
@@ -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
index de3bcefc0c5801d670b8834574fc3b9a903a8ba6..9a9d6484f565af85ce284c0210174070d3967807 100644 (file)
@@ -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