]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cse.c
(call_insn_operand): New funcion.
[gcc.git] / gcc / cse.c
index bb290910e78b10bd673ccbc9a9eb2ec670ac3b26..3d2702fbbe3c3ccc093d3acaead7038a3b5d9261 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1,5 +1,5 @@
 /* Common subexpression elimination for GNU compiler.
-   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992. 1993 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -453,8 +453,9 @@ struct table_elt
 #define CHEAP_REG(N) \
   ((N) == FRAME_POINTER_REGNUM || (N) == STACK_POINTER_REGNUM \
    || (N) == ARG_POINTER_REGNUM                                \
-   || (N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER  \
-   || (FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
+   || ((N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER) \
+   || ((N) < FIRST_PSEUDO_REGISTER                     \
+       && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
 
 #define COST(X)                                                \
   (GET_CODE (X) == REG                                 \
@@ -983,9 +984,14 @@ insert_regs (x, classp, modified)
     {
       register int regno = REGNO (x);
 
-      if (modified
-         || ! (REGNO_QTY_VALID_P (regno)
-               && qty_mode[reg_qty[regno]] == GET_MODE (x)))
+      /* If REGNO is in the equivalence table already but is of the
+        wrong mode for that equivalence, don't do anything here.  */
+
+      if (REGNO_QTY_VALID_P (regno)
+         && qty_mode[reg_qty[regno]] != GET_MODE (x))
+       return 0;
+
+      if (modified || ! REGNO_QTY_VALID_P (regno))
        {
          if (classp)
            for (classp = classp->first_same_value;
@@ -1490,7 +1496,8 @@ invalidate (x)
        remove_from_table (lookup_for_remove (x, hash, GET_MODE (x)), hash);
       else
        {
-         int in_table = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
+         HOST_WIDE_INT in_table
+           = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
          int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
          int tregno, tendregno;
          register struct table_elt *p, *next;
@@ -2307,7 +2314,7 @@ refers_to_mem_p (x, base, start, end)
       /* refers_to_mem_p is never called with varying addresses. 
         If the base addresses are not equal, there is no chance
         of the memory addresses conflicting.  */
-      if (mybase != base)
+      if (! rtx_equal_p (mybase, base))
        return 0;
 
       return myend > start && mystart < end;
@@ -3116,7 +3123,7 @@ simplify_unary_operation (code, mode, op, op_mode)
          break;
 
        case FLOAT_TRUNCATE:
-         d = (double) real_value_truncate (mode, d);
+         d = real_value_truncate (mode, d);
          break;
 
        case FLOAT_EXTEND:
@@ -3124,11 +3131,11 @@ simplify_unary_operation (code, mode, op, op_mode)
          break;
 
        case FIX:
-         d = (double) REAL_VALUE_FIX_TRUNCATE (d);
+         d = REAL_VALUE_RNDZINT (d);
          break;
 
        case UNSIGNED_FIX:
-         d = (double) REAL_VALUE_UNSIGNED_FIX_TRUNCATE (d);
+         d = REAL_VALUE_UNSIGNED_RNDZINT (d);
          break;
 
        case SQRT:
@@ -3262,7 +3269,7 @@ simplify_binary_operation (code, mode, op0, op1)
       f1 = real_value_truncate (mode, f1);
 
 #ifdef REAL_ARITHMETIC
-      REAL_ARITHMETIC (value, code, f0, f1);
+      REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
 #else
       switch (code)
        {
@@ -3559,15 +3566,23 @@ simplify_binary_operation (code, mode, op0, op1)
              && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT)
            {
              REAL_VALUE_TYPE d;
+             jmp_buf handler;
+             int op1is2, op1ism1;
+
+             if (setjmp (handler))
+               return 0;
+
+             set_float_handler (handler);
              REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
+             op1is2 = REAL_VALUES_EQUAL (d, dconst2);
+             op1ism1 = REAL_VALUES_EQUAL (d, dconstm1);
+             set_float_handler (NULL_PTR);
 
              /* x*2 is x+x and x*(-1) is -x */
-             if (REAL_VALUES_EQUAL (d, dconst2)
-                 && GET_MODE (op0) == mode)
+             if (op1is2 && GET_MODE (op0) == mode)
                return gen_rtx (PLUS, mode, op0, copy_rtx (op0));
 
-             else if (REAL_VALUES_EQUAL (d, dconstm1)
-                      && GET_MODE (op0) == mode)
+             else if (op1ism1 && GET_MODE (op0) == mode)
                return gen_rtx (NEG, mode, op0);
            }
          break;
@@ -3583,7 +3598,8 @@ simplify_binary_operation (code, mode, op0, op1)
          /* A | (~A) -> -1 */
          if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
               || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
-             && ! side_effects_p (op0))
+             && ! side_effects_p (op0)
+             && GET_MODE_CLASS (mode) != MODE_CC)
            return constm1_rtx;
          break;
 
@@ -3593,7 +3609,8 @@ simplify_binary_operation (code, mode, op0, op1)
          if (GET_CODE (op1) == CONST_INT
              && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
            return gen_rtx (NOT, mode, op0);
-         if (op0 == op1 && ! side_effects_p (op0))
+         if (op0 == op1 && ! side_effects_p (op0)
+             && GET_MODE_CLASS (mode) != MODE_CC)
            return const0_rtx;
          break;
 
@@ -3603,12 +3620,14 @@ simplify_binary_operation (code, mode, op0, op1)
          if (GET_CODE (op1) == CONST_INT
              && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
            return op0;
-         if (op0 == op1 && ! side_effects_p (op0))
+         if (op0 == op1 && ! side_effects_p (op0)
+             && GET_MODE_CLASS (mode) != MODE_CC)
            return op0;
          /* A & (~A) -> 0 */
          if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
               || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
-             && ! side_effects_p (op0))
+             && ! side_effects_p (op0)
+             && GET_MODE_CLASS (mode) != MODE_CC)
            return const0_rtx;
          break;
 
@@ -3644,7 +3663,7 @@ simplify_binary_operation (code, mode, op0, op1)
              if (REAL_VALUES_EQUAL (d, dconst0))
                abort();
 #if defined (REAL_ARITHMETIC)
-             REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
+             REAL_ARITHMETIC (d, (int) RDIV_EXPR, dconst1, d);
              return gen_rtx (MULT, mode, op0, 
                              CONST_DOUBLE_FROM_REAL_VALUE (d, mode));
 #else
@@ -3701,7 +3720,8 @@ simplify_binary_operation (code, mode, op0, op1)
           
        case SMAX:
          if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
-             && INTVAL (op1) == (unsigned) GET_MODE_MASK (mode) >> 1
+             && (INTVAL (op1)
+                 == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
              && ! side_effects_p (op0))
            return op1;
          else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
@@ -3928,9 +3948,9 @@ simplify_plus_minus (code, mode, op0, op1)
   rtx ops[8];
   int negs[8];
   rtx result, tem;
-  int n_ops = 2;
-  int i, j;
+  int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0;
   int first = 1, negate = 0, changed;
+  int i, j;
 
   bzero (ops, sizeof ops);
   
@@ -3956,6 +3976,7 @@ simplify_plus_minus (code, mode, op0, op1)
            ops[n_ops] = XEXP (ops[i], 1);
            negs[n_ops++] = GET_CODE (ops[i]) == MINUS ? !negs[i] : negs[i];
            ops[i] = XEXP (ops[i], 0);
+           input_ops++;
            changed = 1;
            break;
 
@@ -3967,6 +3988,7 @@ simplify_plus_minus (code, mode, op0, op1)
 
          case CONST:
            ops[i] = XEXP (ops[i], 0);
+           input_consts++;
            changed = 1;
            break;
 
@@ -3975,7 +3997,7 @@ simplify_plus_minus (code, mode, op0, op1)
            if (n_ops != 7)
              {
                ops[n_ops] = constm1_rtx;
-               negs[n_ops++] = negs[i];
+               negs[n_ops++] = negs[i];
                ops[i] = XEXP (ops[i], 0);
                negs[i] = ! negs[i];
                changed = 1;
@@ -4032,12 +4054,21 @@ simplify_plus_minus (code, mode, op0, op1)
     }
 
   /* Pack all the operands to the lower-numbered entries and give up if
-     we didn't reduce the number of operands we had.  */
+     we didn't reduce the number of operands we had.  Make sure we
+     count a CONST as two operands.  If we have the same number of
+     operands, but have made more CONSTs than we had, this is also
+     an improvement, so accept it.  */
+
   for (i = 0, j = 0; j < n_ops; j++)
     if (ops[j] != 0)
-      ops[i] = ops[j], negs[i++] = negs[j];
+      {
+       ops[i] = ops[j], negs[i++] = negs[j];
+       if (GET_CODE (ops[j]) == CONST)
+         n_consts++;
+      }
 
-  if (i >= n_ops)
+  if (i + n_consts > input_ops
+      || (i + n_consts == input_ops && n_consts <= input_consts))
     return 0;
 
   n_ops = i;
@@ -4132,6 +4163,11 @@ simplify_relational_operation (code, mode, op0, op1)
   if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
     op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
 
+  /* What to do with MODE_CC isn't clear yet.
+     Let's make sure nothing erroneous is done.  */
+  if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
+    return 0;
+
   /* Unlike the arithmetic operations, we can do the comparison whether
      or not WIDTH is larger than HOST_BITS_PER_WIDE_INT because the
      CONST_INTs are to be understood as being infinite precision as
@@ -4466,8 +4502,8 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
    modified by recursive calls to this function.
 
    If X is a register whose contents are known, we do NOT
-   return those contents.  This is because an instruction that
-   uses a register is usually faster than one that uses a constant.
+   return those contents here.  equiv_constant is called to
+   perform that task.
 
    INSN is the insn that we may be modifying.  If it is 0, make a copy
    of X before modifying it.  */
@@ -5454,8 +5490,10 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
      true for all smaller modes whether or not there is a SUBREG, but
      is not worth testing for with no SUBREG.  */
 
+  /* Note that GET_MODE (op0) may not equal MODE.  */
   if (code == EQ && GET_CODE (op0) == SUBREG
-      && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+      && (GET_MODE_SIZE (GET_MODE (op0))
+         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
       rtx tem = gen_lowpart_if_possible (inner_mode, op1);
@@ -5466,7 +5504,8 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
     }
 
   if (code == EQ && GET_CODE (op1) == SUBREG
-      && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))))
+      && (GET_MODE_SIZE (GET_MODE (op1))
+         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
       rtx tem = gen_lowpart_if_possible (inner_mode, op0);
@@ -5479,9 +5518,14 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
   /* Similarly, if this is an NE comparison, and either is a SUBREG 
      making a smaller mode, we know the whole thing is also NE.  */
 
+  /* Note that GET_MODE (op0) may not equal MODE;
+     if we test MODE instead, we can get an infinite recursion
+     alternating between two modes each wider than MODE.  */
+
   if (code == NE && GET_CODE (op0) == SUBREG
       && subreg_lowpart_p (op0)
-      && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+      && (GET_MODE_SIZE (GET_MODE (op0))
+         < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
       rtx tem = gen_lowpart_if_possible (inner_mode, op1);
@@ -5493,7 +5537,8 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
 
   if (code == NE && GET_CODE (op1) == SUBREG
       && subreg_lowpart_p (op1)
-      && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))))
+      && (GET_MODE_SIZE (GET_MODE (op1))
+         < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
       rtx tem = gen_lowpart_if_possible (inner_mode, op0);
@@ -6568,6 +6613,13 @@ cse_insn (insn, in_libcall_block)
              delete_insn (insn);
              insn = new;
            }
+         else
+           /* Otherwise, force rerecognition, since it probably had
+              a different pattern before.
+              This shouldn't really be necessary, since whatever
+              changed the source value above should have done this.
+              Until the right place is found, might as well do this here.  */
+           INSN_CODE (insn) = -1;
 
          /* Now that we've converted this jump to an unconditional jump,
             there is dead code after it.  Delete the dead code until we
@@ -7161,7 +7213,7 @@ cse_process_notes (x, object)
   for (i = 0; i < GET_RTX_LENGTH (code); i++)
     if (fmt[i] == 'e')
       validate_change (object, &XEXP (x, i),
-                      cse_process_notes (XEXP (x, i), object), NULL_RTX);
+                      cse_process_notes (XEXP (x, i), object), 0);
 
   return x;
 }
This page took 1.498143 seconds and 5 git commands to generate.