]> gcc.gnu.org Git - gcc.git/commitdiff
*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Fri, 26 Jun 1992 11:06:07 +0000 (07:06 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Fri, 26 Jun 1992 11:06:07 +0000 (07:06 -0400)
From-SVN: r1296

gcc/combine.c
gcc/cse.c
gcc/fold-const.c
gcc/genoutput.c
gcc/stmt.c

index 79cc7e14822f01387fedc11fd324e6604a1efdae..eeea4bce52ebbde3f696b21189699f0cca228115 100644 (file)
@@ -1471,17 +1471,31 @@ try_combine (i3, i2, i1)
       && asm_noperands (newpat) < 0)
     {
       rtx m_split, *split;
+      rtx ni2dest = i2dest;
 
       /* See if the MD file can split NEWPAT.  If it can't, see if letting it
-        use I2DEST as a scratch register will help.  */
+        use I2DEST as a scratch register will help.  In the latter case,
+        convert I2DEST to the mode of the source of NEWPAT if we can.  */
 
       m_split = split_insns (newpat, i3);
       if (m_split == 0)
-       m_split = split_insns (gen_rtx (PARALLEL, VOIDmode,
-                                       gen_rtvec (2, newpat,
-                                                  gen_rtx (CLOBBER, VOIDmode,
-                                                           i2dest))),
-                              i3);
+       {
+         /* If I2DEST is a hard register or the only use of a pseudo,
+            we can change its mode.  */
+         if (GET_MODE (SET_DEST (newpat)) != GET_MODE (i2dest)
+             && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER
+                 || (reg_n_sets[REGNO (i2dest)] == 1 && ! added_sets_2
+                     && ! REG_USERVAR_P (i2dest))))
+           ni2dest = gen_rtx (REG, GET_MODE (SET_DEST (newpat)),
+                              REGNO (i2dest));
+
+         m_split = split_insns (gen_rtx (PARALLEL, VOIDmode,
+                                         gen_rtvec (2, newpat,
+                                                    gen_rtx (CLOBBER,
+                                                             VOIDmode,
+                                                             ni2dest))),
+                                i3);
+       }
 
       if (m_split && GET_CODE (m_split) == SEQUENCE
          && XVECLEN (m_split, 0) == 2
@@ -1492,6 +1506,13 @@ try_combine (i3, i2, i1)
          newi2pat = PATTERN (XVECEXP (m_split, 0, 0));
          newpat = PATTERN (XVECEXP (m_split, 0, 1));
 
+         /* In case we changed the mode of I2DEST, replace it in the
+            pseudo-register table here.  We can't do it above in case this
+            code doesn't get executed and we do a split the other way.  */
+
+         if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
+           SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
+
          i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
          if (i2_code_number >= 0)
            insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
@@ -2945,6 +2966,18 @@ subst (x, from, to, in_dest, unique_copy)
                                      - INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
          goto restart;
        }
+
+      /* If we are adding two things that have no bits in common, convert
+        the addition into an IOR.  This will often be further simplified,
+        for example in cases like ((a & 1) + (a & 2)), which can
+        become a & 3.  */
+
+      if ((significant_bits (XEXP (x, 0), mode)
+          & significant_bits (XEXP (x, 1), mode)) == 0)
+       {
+         x = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+         goto restart;
+       }
       break;
 
     case MULT:
@@ -4194,8 +4227,8 @@ make_extraction (mode, inner, pos, pos_rtx, len,
    We try, as much as possible, to re-use rtl expressions to save memory.
 
    IN_CODE says what kind of expression we are processing.  Normally, it is
-   SET.  In a memory address (inside a MEM or PLUS, the latter being a
-   kludge), it is MEM.  When processing the arguments of a comparison
+   SET.  In a memory address (inside a MEM, PLUS or minus, the latter two
+   being kludges), it is MEM.  When processing the arguments of a comparison
    or a COMPARE against zero, it is COMPARE.  */
 
 static rtx
@@ -4215,7 +4248,7 @@ make_compound_operation (x, in_code)
      address, we stay there.  If we have a comparison, set to COMPARE,
      but once inside, go back to our default of SET.  */
 
-  next_code = (code == MEM || code == PLUS ? MEM
+  next_code = (code == MEM || code == PLUS || code == MINUS ? MEM
               : ((code == COMPARE || GET_RTX_CLASS (code) == '<')
                  && XEXP (x, 1) == const0_rtx) ? COMPARE
               : in_code == COMPARE ? SET : in_code);
index b05f014989256660ebd3a4e442e5b786c9d9feb5..c39174d89df218b711868f34863125f3e09b3281 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2451,8 +2451,9 @@ find_best_addr (insn, loc)
       && validate_change (insn, loc, fold_rtx (addr, insn), 0))
     addr = *loc;
        
-  /* If this address is not in the hash table, we can't do any better.
-     Also, ignore if volatile.  */
+  /* If this address is not in the hash table, we can't look for equivalences
+     of the whole address.  Also, ignore if volatile.  */
+
   do_not_record = 0;
   hash_code = HASH (addr, Pmode);
   addr_volatile = do_not_record;
@@ -2465,56 +2466,138 @@ find_best_addr (insn, loc)
 
   elt = lookup (addr, hash_code, Pmode);
 
-  if (elt == 0)
-    return;
-
 #ifndef ADDRESS_COST
-  our_cost = elt->cost;
-
-  /* Find the lowest cost below ours that works.  */
-  for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
-    if (elt->cost < our_cost
-       && (GET_CODE (elt->exp) == REG || exp_equiv_p (elt->exp, elt->exp, 1, 0))
-       && validate_change (insn, loc, canon_reg (copy_rtx (elt->exp), 0), 0))
-      return;
+  if (elt)
+    {
+      our_cost = elt->cost;
 
+      /* Find the lowest cost below ours that works.  */
+      for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
+       if (elt->cost < our_cost
+           && (GET_CODE (elt->exp) == REG
+               || exp_equiv_p (elt->exp, elt->exp, 1, 0))
+           && validate_change (insn, loc,
+                               canon_reg (copy_rtx (elt->exp), 0), 0))
+         return;
+    }
 #else
 
-  /* We need to find the best (under the criteria documented above) entry in
-     the class that is valid.  We use the `flag' field to indicate choices
-     that were invalid and iterate until we can't find a better one that
-     hasn't already been tried.  */
+  if (elt)
+    {
+      /* We need to find the best (under the criteria documented above) entry
+        in the class that is valid.  We use the `flag' field to indicate
+        choices that were invalid and iterate until we can't find a better
+        one that hasn't already been tried.  */
 
-  for (p = elt->first_same_value; p; p = p->next_same_value)
-    p->flag = 0;
+      for (p = elt->first_same_value; p; p = p->next_same_value)
+       p->flag = 0;
 
-  while (found_better)
+      while (found_better)
+       {
+         int best_addr_cost = ADDRESS_COST (*loc);
+         int best_rtx_cost = (elt->cost + 1) >> 1;
+         struct table_elt *best_elt = elt; 
+
+         found_better = 0;
+         for (p = elt->first_same_value; p; p = p->next_same_value)
+           if (! p->flag
+               && (GET_CODE (p->exp) == REG
+                   || exp_equiv_p (p->exp, p->exp, 1, 0))
+               && (ADDRESS_COST (p->exp) < best_addr_cost
+                   || (ADDRESS_COST (p->exp) == best_addr_cost
+                       && (p->cost + 1) >> 1 > best_rtx_cost)))
+             {
+               found_better = 1;
+               best_addr_cost = ADDRESS_COST (p->exp);
+               best_rtx_cost = (p->cost + 1) >> 1;
+               best_elt = p;
+             }
+
+         if (found_better)
+           {
+             if (validate_change (insn, loc,
+                                  canon_reg (copy_rtx (best_elt->exp), 0), 0))
+               return;
+             else
+               best_elt->flag = 1;
+           }
+       }
+    }
+
+  /* If the address is a binary operation with the first operand a register
+     and the second a constant, do the same as above, but looking for
+     equivalences of the register.  Then try to simplify before checking for
+     the best address to use.  This catches a few cases:  First is when we
+     have REG+const and the register is another REG+const.  We can often merge
+     the constants and eliminate one insn and one register.  It may also be
+     that a machine has a cheap REG+REG+const.  Finally, this improves the
+     code on the Alpha for unaligned byte stores.  */
+
+  if (flag_expensive_optimizations
+      && (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
+         || GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
+      && GET_CODE (XEXP (*loc, 0)) == REG
+      && GET_CODE (XEXP (*loc, 1)) == CONST_INT)
     {
-      int best_addr_cost = ADDRESS_COST (*loc);
-      int best_rtx_cost = (elt->cost + 1) >> 1;
-      struct table_elt *best_elt = elt; 
+      rtx c = XEXP (*loc, 1);
+
+      do_not_record = 0;
+      hash_code = HASH (XEXP (*loc, 0), Pmode);
+      do_not_record = save_do_not_record;
+      hash_arg_in_memory = save_hash_arg_in_memory;
+      hash_arg_in_struct = save_hash_arg_in_struct;
+
+      elt = lookup (XEXP (*loc, 0), hash_code, Pmode);
+      if (elt == 0)
+       return;
+
+      /* We need to find the best (under the criteria documented above) entry
+        in the class that is valid.  We use the `flag' field to indicate
+        choices that were invalid and iterate until we can't find a better
+        one that hasn't already been tried.  */
 
-      found_better = 0;
       for (p = elt->first_same_value; p; p = p->next_same_value)
-       if (! p->flag
-           && (GET_CODE (p->exp) == REG || exp_equiv_p (p->exp, p->exp, 1, 0))
-           && (ADDRESS_COST (p->exp) < best_addr_cost
-               || (ADDRESS_COST (p->exp) == best_addr_cost
-                   && (p->cost + 1) >> 1 > best_rtx_cost)))
-         {
-           found_better = 1;
-           best_addr_cost = ADDRESS_COST (p->exp);
-           best_rtx_cost = (p->cost + 1) >> 1;
-           best_elt = p;
-         }
+       p->flag = 0;
 
-      if (found_better)
+      while (found_better)
        {
-         if (validate_change (insn, loc,
-                              canon_reg (copy_rtx (best_elt->exp), 0), 0))
-           return;
-         else
-           best_elt->flag = 1;
+         int best_addr_cost = ADDRESS_COST (*loc);
+         int best_rtx_cost = (COST (*loc) + 1) >> 1;
+         struct table_elt *best_elt = elt; 
+         rtx best_rtx = *loc;
+
+         found_better = 0;
+         for (p = elt->first_same_value; p; p = p->next_same_value)
+           if (! p->flag
+               && (GET_CODE (p->exp) == REG
+                   || exp_equiv_p (p->exp, p->exp, 1, 0)))
+             {
+               rtx new = simplify_binary_operation (GET_CODE (*loc), Pmode,
+                                                    p->exp, c);
+
+               if (new == 0)
+                 new = gen_rtx (GET_CODE (*loc), Pmode, p->exp, c);
+
+               if ((ADDRESS_COST (new) < best_addr_cost
+                   || (ADDRESS_COST (new) == best_addr_cost
+                       && (COST (new) + 1) >> 1 > best_rtx_cost)))
+                 {
+                   found_better = 1;
+                   best_addr_cost = ADDRESS_COST (new);
+                   best_rtx_cost = (COST (new) + 1) >> 1;
+                   best_elt = p;
+                   best_rtx = new;
+                 }
+             }
+
+         if (found_better)
+           {
+             if (validate_change (insn, loc,
+                                  canon_reg (copy_rtx (best_rtx), 0), 0))
+               return;
+             else
+               best_elt->flag = 1;
+           }
        }
     }
 #endif
index a2691096ba1649eb7da4958b130b4a5c0419a453..99d347db63f9f27112c70f76e4672e90cb7afc6e 100644 (file)
@@ -2134,7 +2134,6 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
 
 #if BYTES_BIG_ENDIAN
   lbitpos = lnbitsize - lbitsize - lbitpos;
-  rbitpos = rnbitsize - rbitsize - rbitpos;
 #endif
 
   /* Make the mask to be used against the extracted field.  */
index 70173dc97a308a2820213a026a01e56dcb2b41f1..96cad8c4b9abe46a62757e66d7e90c5075928a04 100644 (file)
@@ -846,6 +846,7 @@ gen_split (split)
   mybzero (d->strict_low, sizeof strict_low);
 
   d->n_dups = 0;
+  d->n_alternatives = 0;
   d->template = 0;
   d->outfun = 0;
   d->n_alternatives = 0;
index d9e49bdad5f06312aee12a19bef169508da84304..7abf935f407bf2f199c7e3d53c7b11ba4b68c936 100644 (file)
@@ -2546,16 +2546,35 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
 #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
       if (fixed_regs[ARG_POINTER_REGNUM])
        {
-         /* Now restore our arg pointer from the address at which it was saved
-            in our stack frame.
-            If there hasn't be space allocated for it yet, make some now.  */
-         if (arg_pointer_save_area == 0)
-           arg_pointer_save_area
-             = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
-         emit_move_insn (virtual_incoming_args_rtx,
-                         /* We need a pseudo here,
-                            or else instantiate_virtual_regs_1 complains.  */
-                         copy_to_reg (arg_pointer_save_area));
+#ifdef ELIMINABLE_REGS
+         /* If the argument pointer can be eliminated in favor of the
+            frame pointer, we don't need to restore it.  We assume here
+            that if such an elimination is present, it can always be used.
+            This is the case on all known machines; if we don't make this
+            assumption, we do unnecessary saving on many machines.  */
+         static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
+         int i;
+
+         for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
+           if (elim_regs[i].from == ARG_POINTER_REGNUM
+               && elim_regs[i].to == FRAME_POINTER_REGNUM)
+             break;
+
+         if (i == sizeof elim_regs / sizeof elim_regs [0])
+#endif
+           {
+             /* Now restore our arg pointer from the address at which it
+                was saved in our stack frame.
+                If there hasn't be space allocated for it yet, make
+                some now.  */
+             if (arg_pointer_save_area == 0)
+               arg_pointer_save_area
+                 = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+             emit_move_insn (virtual_incoming_args_rtx,
+                             /* We need a pseudo here, or else
+                                instantiate_virtual_regs_1 complains.  */
+                             copy_to_reg (arg_pointer_save_area));
+           }
        }
 #endif
 
This page took 0.072928 seconds and 5 git commands to generate.