]> gcc.gnu.org Git - gcc.git/commitdiff
combine.c (nonzero_bits, case PLUS): If pointers extend unsigned and this is the...
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>
Tue, 6 Feb 2001 12:39:15 +0000 (12:39 +0000)
committerRichard Kenner <kenner@gcc.gnu.org>
Tue, 6 Feb 2001 12:39:15 +0000 (07:39 -0500)
* combine.c (nonzero_bits, case PLUS): If pointers extend unsigned
and this is the sum of a pointer and a constant, we know the result
did not overflow.
(num_sign_bit_copies, case PLUS): Likewise.
* explow.c (convert_memory_address): Remove opposite SUBREG.
* function.c (instantiate_new_reg): New function (from common code).
(instantiate_virtual_regs_1): Call it.
For PLUS, handle if (plus (subreg (virt-reg) (const_int))
if pointers sign- or zero-extend.
* simplify-rtx.c (simplify_unary_operation, case ZERO_EXTEND):
If pointers extend unsigned, use inside of SUBREG.
(simplify_unary_operation, case SIGN_EXTEND): Likewise, if sign extend.

From-SVN: r39489

gcc/ChangeLog
gcc/combine.c
gcc/explow.c
gcc/function.c
gcc/simplify-rtx.c

index 547f50fad7d559123eabeec57a1b4b755034804d..f0c7159456bef9cf0fdb9b4e178f88133db798a8 100644 (file)
@@ -1,3 +1,18 @@
+Mon Feb  5 21:56:16 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * combine.c (nonzero_bits, case PLUS): If pointers extend unsigned
+       and this is the sum of a pointer and a constant, we know the result
+       did not overflow.
+       (num_sign_bit_copies, case PLUS): Likewise.
+       * explow.c (convert_memory_address): Remove opposite SUBREG.
+       * function.c (instantiate_new_reg): New function (from common code).
+       (instantiate_virtual_regs_1): Call it.
+       For PLUS, handle if (plus (subreg (virt-reg) (const_int))
+       if pointers sign- or zero-extend.
+       * simplify-rtx.c (simplify_unary_operation, case ZERO_EXTEND):
+       If pointers extend unsigned, use inside of SUBREG.
+       (simplify_unary_operation, case SIGN_EXTEND): Likewise, if sign extend.
+
 2001-02-05  Benjamin Kosnik  <bkoz@redhat.com>
 
        * Makefile.in (-DGPLUSPLUS_TOOL_INCLUDE_DIR): Change to target
index 74b02b55a472a99cd56a68b94950dac85a95a2e1..662f05f2240f730770b1a691daca8a04c3e86d0f 100644 (file)
@@ -8308,6 +8308,16 @@ nonzero_bits (x, mode)
 
        if (result_low > 0)
          nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+       /* If pointers extend unsigned and this is an addition or subtraction
+          to a pointer in Pmode, all the bits above ptr_mode are known to be
+          zero.  */
+       if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+           && (code == PLUS || code == MINUS)
+           && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
+         nonzero &= GET_MODE_MASK (ptr_mode);
+#endif
       }
       break;
 
@@ -8646,7 +8656,20 @@ num_sign_bit_copies (x, mode)
 
       num0 = num_sign_bit_copies (XEXP (x, 0), mode);
       num1 = num_sign_bit_copies (XEXP (x, 1), mode);
-      return MAX (1, MIN (num0, num1) - 1);
+      result = MAX (1, MIN (num0, num1) - 1);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+      /* If pointers extend signed and this is an addition or subtraction
+        to a pointer in Pmode, all the bits above ptr_mode are known to be
+        sign bit copies.  */
+      if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+         && (code == PLUS || code == MINUS)
+         && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
+       result = MAX ((GET_MODE_BITSIZE (Pmode)
+                      - GET_MODE_BITSIZE (ptr_mode) + 1),
+                     result);
+#endif
+      return result;
 
     case MULT:
       /* The number of bits of the product is the sum of the number of
index d36ceffa440fb65acdcd7a2a6c62419d2231be28..b7c0bb9f6d96970543a97626870dabdffec64b8a 100644 (file)
@@ -386,6 +386,11 @@ convert_memory_address (to_mode, x)
     case CONST_DOUBLE:
       return x;
 
+    case SUBREG:
+      if (GET_MODE (SUBREG_REG (x)) == to_mode)
+       return SUBREG_REG (x);
+      break;
+
     case LABEL_REF:
       temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
       LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
index 5421450c4a818628ae5ad3423483002bee3affff..259ccca4fb0e038e81c99b1d18e1ff2c1864f1a9 100644 (file)
@@ -269,6 +269,7 @@ static void optimize_bit_field      PARAMS ((rtx, rtx, rtx *));
 static void instantiate_decls  PARAMS ((tree, int));
 static void instantiate_decls_1        PARAMS ((tree, int));
 static void instantiate_decl   PARAMS ((rtx, HOST_WIDE_INT, int));
+static rtx instantiate_new_reg PARAMS ((rtx, HOST_WIDE_INT *));
 static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
 static void delete_handlers    PARAMS ((void));
 static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
@@ -3680,6 +3681,35 @@ instantiate_decl (x, size, valid_only)
   XEXP (x, 0) = addr;
 }
 \f
+/* Given a piece of RTX and a pointer to a HOST_WIDE_INT, if the RTX
+   is a virtual register, return the requivalent hard register and set the
+   offset indirectly through the pointer.  Otherwise, return 0.  */
+
+static rtx
+instantiate_new_reg (x, poffset)
+     rtx x;
+     HOST_WIDE_INT *poffset;
+{
+  rtx new;
+  HOST_WIDE_INT offset;
+
+  if (x == virtual_incoming_args_rtx)
+    new = arg_pointer_rtx, offset = in_arg_offset;
+  else if (x == virtual_stack_vars_rtx)
+    new = frame_pointer_rtx, offset = var_offset;
+  else if (x == virtual_stack_dynamic_rtx)
+    new = stack_pointer_rtx, offset = dynamic_offset;
+  else if (x == virtual_outgoing_args_rtx)
+    new = stack_pointer_rtx, offset = out_arg_offset;
+  else if (x == virtual_cfa_rtx)
+    new = arg_pointer_rtx, offset = cfa_offset;
+  else
+    return 0;
+
+  *poffset = offset;
+  return new;
+}
+\f
 /* Given a pointer to a piece of rtx and an optional pointer to the
    containing object, instantiate any virtual registers present in it.
 
@@ -3739,21 +3769,14 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
         the actual register should receive the source minus the
         appropriate offset.  This is used, for example, in the handling
         of non-local gotos.  */
-      if (SET_DEST (x) == virtual_incoming_args_rtx)
-       new = arg_pointer_rtx, offset = -in_arg_offset;
-      else if (SET_DEST (x) == virtual_stack_vars_rtx)
-       new = frame_pointer_rtx, offset = -var_offset;
-      else if (SET_DEST (x) == virtual_stack_dynamic_rtx)
-       new = stack_pointer_rtx, offset = -dynamic_offset;
-      else if (SET_DEST (x) == virtual_outgoing_args_rtx)
-       new = stack_pointer_rtx, offset = -out_arg_offset;
-      else if (SET_DEST (x) == virtual_cfa_rtx)
-       new = arg_pointer_rtx, offset = -cfa_offset;
-
-      if (new)
+      if ((new = instantiate_new_reg (SET_DEST (x), &offset)) != 0)
        {
          rtx src = SET_SRC (x);
 
+         /* We are setting the register, not using it, so the relevant
+            offset is the negative of the offset to use were we using
+            the register.  */
+         offset = - offset;
          instantiate_virtual_regs_1 (&src, NULL_RTX, 0);
 
          /* The only valid sources here are PLUS or REG.  Just do
@@ -3793,40 +3816,37 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
          /* Check for (plus (plus VIRT foo) (const_int)) first.  */
          if (GET_CODE (XEXP (x, 0)) == PLUS)
            {
-             rtx inner = XEXP (XEXP (x, 0), 0);
-
-             if (inner == virtual_incoming_args_rtx)
-               new = arg_pointer_rtx, offset = in_arg_offset;
-             else if (inner == virtual_stack_vars_rtx)
-               new = frame_pointer_rtx, offset = var_offset;
-             else if (inner == virtual_stack_dynamic_rtx)
-               new = stack_pointer_rtx, offset = dynamic_offset;
-             else if (inner == virtual_outgoing_args_rtx)
-               new = stack_pointer_rtx, offset = out_arg_offset;
-             else if (inner == virtual_cfa_rtx)
-               new = arg_pointer_rtx, offset = cfa_offset;
+             if ((new = instantiate_new_reg (XEXP (XEXP (x, 0), 0), &offset)))
+               {
+                 instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
+                                             extra_insns);
+                 new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1));
+               }
              else
                {
                  loc = &XEXP (x, 0);
                  goto restart;
                }
-
-             instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
-                                         extra_insns);
-             new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1));
            }
 
-         else if (XEXP (x, 0) == virtual_incoming_args_rtx)
-           new = arg_pointer_rtx, offset = in_arg_offset;
-         else if (XEXP (x, 0) == virtual_stack_vars_rtx)
-           new = frame_pointer_rtx, offset = var_offset;
-         else if (XEXP (x, 0) == virtual_stack_dynamic_rtx)
-           new = stack_pointer_rtx, offset = dynamic_offset;
-         else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
-           new = stack_pointer_rtx, offset = out_arg_offset;
-         else if (XEXP (x, 0) == virtual_cfa_rtx)
-           new = arg_pointer_rtx, offset = cfa_offset;
-         else
+#ifdef POINTERS_EXTEND_UNSIGNED
+         /* If we have (plus (subreg (virtual-reg)) (const_int)), we know
+            we can commute the PLUS and SUBREG because pointers into the
+            frame are well-behaved.  */
+         else if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_MODE (x) == ptr_mode
+                  && GET_CODE (XEXP (x, 1)) == CONST_INT
+                  && 0 != (new
+                           = instantiate_new_reg (SUBREG_REG (XEXP (x, 0)),
+                                                  &offset))
+                  && validate_change (object, loc,
+                                      plus_constant (gen_lowpart (ptr_mode,
+                                                                  new),
+                                                     offset
+                                                     + INTVAL (XEXP (x, 1))),
+                                      0))
+               return 1;
+#endif
+         else if ((new = instantiate_new_reg (XEXP (x, 0), &offset)) == 0)
            {
              /* We know the second operand is a constant.  Unless the
                 first operand is a REG (which has been already checked),
@@ -4025,18 +4045,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
     case REG:
       /* Try to replace with a PLUS.  If that doesn't work, compute the sum
         in front of this insn and substitute the temporary.  */
-      if (x == virtual_incoming_args_rtx)
-       new = arg_pointer_rtx, offset = in_arg_offset;
-      else if (x == virtual_stack_vars_rtx)
-       new = frame_pointer_rtx, offset = var_offset;
-      else if (x == virtual_stack_dynamic_rtx)
-       new = stack_pointer_rtx, offset = dynamic_offset;
-      else if (x == virtual_outgoing_args_rtx)
-       new = stack_pointer_rtx, offset = out_arg_offset;
-      else if (x == virtual_cfa_rtx)
-       new = arg_pointer_rtx, offset = cfa_offset;
-
-      if (new)
+      if ((new = instantiate_new_reg (x, &offset)) != 0)
        {
          temp = plus_constant (new, offset);
          if (!validate_change (object, loc, temp, 0))
index 6ae44b237a03f528ce85d73d9102b34bdad9e1ba..afd8d264b62500d66b741aa04bbc7de30b3adf9b 100644 (file)
@@ -623,7 +623,11 @@ simplify_unary_operation (code, mode, op, op_mode)
 #ifdef POINTERS_EXTEND_UNSIGNED
          if (! POINTERS_EXTEND_UNSIGNED
              && mode == Pmode && GET_MODE (op) == ptr_mode
-             && CONSTANT_P (op))
+             && (CONSTANT_P (op)
+                 || (GET_CODE (op) == SUBREG
+                     && GET_CODE (SUBREG_REG (op)) == REG
+                     && REG_POINTER (SUBREG_REG (op))
+                     && GET_MODE (SUBREG_REG (op)) == Pmode)))
            return convert_memory_address (Pmode, op);
 #endif
          break;
@@ -632,7 +636,11 @@ simplify_unary_operation (code, mode, op, op_mode)
        case ZERO_EXTEND:
          if (POINTERS_EXTEND_UNSIGNED
              && mode == Pmode && GET_MODE (op) == ptr_mode
-             && CONSTANT_P (op))
+             && (CONSTANT_P (op)
+                 || (GET_CODE (op) == SUBREG
+                     && GET_CODE (SUBREG_REG (op)) == REG
+                     && REG_POINTER (SUBREG_REG (op))
+                     && GET_MODE (SUBREG_REG (op)) == Pmode)))
            return convert_memory_address (Pmode, op);
          break;
 #endif
This page took 0.10645 seconds and 5 git commands to generate.