reload1.c (reload_cse_simplify_set): Respect LOAD_EXTEND_OP when replacing a memory...
authorRichard Henderson <rth@redhat.com>
Sat, 17 Feb 2001 23:07:06 +0000 (15:07 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 17 Feb 2001 23:07:06 +0000 (15:07 -0800)
        * reload1.c (reload_cse_simplify_set): Respect LOAD_EXTEND_OP
        when replacing a memory load with a register.

From-SVN: r39805

gcc/ChangeLog
gcc/reload1.c

index 11e9a8e..d24594b 100644 (file)
@@ -1,3 +1,8 @@
+2001-02-17  Richard Henderson  <rth@redhat.com>
+
+       * reload1.c (reload_cse_simplify_set): Respect LOAD_EXTEND_OP
+       when replacing a memory load with a register.
+
 Sat Feb 17 14:48:30 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
                          Jan Hubicka  <jh@suse.cz>
 
index 368cfb2..a10a12a 100644 (file)
@@ -6665,7 +6665,7 @@ emit_output_reload_insns (chain, rl, j)
 
                  /* Copy primary reload reg to secondary reload reg.
                     (Note that these have been swapped above, then
-                    secondary reload reg to OLD using our insn.  */
+                    secondary reload reg to OLD using our insn.)  */
 
                  /* If REAL_OLD is a paradoxical SUBREG, remove it
                     and try to put the opposite SUBREG on
@@ -8172,6 +8172,9 @@ reload_cse_simplify_set (set, insn)
   int old_cost;
   cselib_val *val;
   struct elt_loc_list *l;
+#ifdef LOAD_EXTEND_OP
+  enum rtx_code extend_op = NIL;
+#endif
 
   dreg = true_regnum (SET_DEST (set));
   if (dreg < 0)
@@ -8183,6 +8186,18 @@ reload_cse_simplify_set (set, insn)
 
   dclass = REGNO_REG_CLASS (dreg);
 
+#ifdef LOAD_EXTEND_OP
+  /* When replacing a memory with a register, we need to honor assumptions
+     that combine made wrt the contents of sign bits.  We'll do this by
+     generating an extend instruction instead of a reg->reg copy.  Thus 
+     the destination must be a register that we can widen.  */
+  if (GET_CODE (src) == MEM
+      && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
+      && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != NIL
+      && GET_CODE (SET_DEST (set)) != REG)
+    return 0;
+#endif
+
   /* If memory loads are cheaper than register copies, don't change them.  */
   if (GET_CODE (src) == MEM)
     old_cost = MEMORY_MOVE_COST (GET_MODE (src), dclass, 1);
@@ -8200,23 +8215,72 @@ reload_cse_simplify_set (set, insn)
     return 0;
   for (l = val->locs; l; l = l->next)
     {
+      rtx this_rtx = l->loc;
       int this_cost;
-      if (CONSTANT_P (l->loc) && ! references_value_p (l->loc, 0))
-       this_cost = rtx_cost (l->loc, SET);
-      else if (GET_CODE (l->loc) == REG)
-       this_cost = REGISTER_MOVE_COST (GET_MODE (l->loc),
-                                       REGNO_REG_CLASS (REGNO (l->loc)),
-                                       dclass);
+
+      if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
+       {
+#ifdef LOAD_EXTEND_OP
+         if (extend_op != NIL)
+           {
+             HOST_WIDE_INT this_val;
+
+             /* ??? I'm lazy and don't wish to handle CONST_DOUBLE.  Other
+                constants, such as SYMBOL_REF, cannot be extended.  */
+             if (GET_CODE (this_rtx) != CONST_INT)
+               continue;
+
+             this_val = INTVAL (this_rtx);
+             switch (extend_op)
+               {
+               case ZERO_EXTEND:
+                 this_val &= GET_MODE_MASK (GET_MODE (src));
+                 break;
+               case SIGN_EXTEND:
+                 /* ??? In theory we're already extended.  */
+                 if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
+                   break;
+               default:
+                 abort ();
+               }
+             this_val = GEN_INT (this_val);
+           }
+#endif
+         this_cost = rtx_cost (this_rtx, SET);
+       }
+      else if (GET_CODE (this_rtx) == REG)
+       {
+#ifdef LOAD_EXTEND_OP
+         if (extend_op != NIL)
+           {
+             this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
+             this_cost = rtx_cost (this_rtx, SET);
+           }
+         else
+#endif
+           this_cost = REGISTER_MOVE_COST (GET_MODE (this_rtx),
+                                           REGNO_REG_CLASS (REGNO (this_rtx)),
+                                           dclass);
+       }
       else
        continue;
-      /* If equal costs, prefer registers over anything else.  That tends to
-        lead to smaller instructions on some machines.  */
-      if ((this_cost < old_cost
-          || (this_cost == old_cost
-              && GET_CODE (l->loc) == REG
-              && GET_CODE (SET_SRC (set)) != REG))
-         && validate_change (insn, &SET_SRC (set), copy_rtx (l->loc), 1))
-       old_cost = this_cost, did_change = 1;
+
+      /* If equal costs, prefer registers over anything else.  That
+        tends to lead to smaller instructions on some machines.  */
+      if (this_cost < old_cost
+         || (this_cost == old_cost
+             && GET_CODE (this_rtx) == REG
+             && GET_CODE (SET_SRC (set)) != REG))
+       {
+#ifdef LOAD_EXTEND_OP
+         rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
+         ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
+         validate_change (insn, &SET_DEST (set), wide_dest, 1);
+#endif
+
+         validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1);
+         old_cost = this_cost, did_change = 1;
+       }
     }
 
   return did_change;