optabs.c (shift_optab_p, [...]): New functions, split out from expand_binop.
authorRichard Sandiford <richard@codesourcery.com>
Fri, 31 Aug 2007 14:10:35 +0000 (14:10 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 31 Aug 2007 14:10:35 +0000 (14:10 +0000)
gcc/
* optabs.c (shift_optab_p, commutative_optab_p): New functions,
split out from expand_binop.
(avoid_expensive_constant): New function.
(expand_binop_directly): Remove commutative_op argument and
call cummutative_optab_p instead.  Do not change op0 or op1
when swapping xop0 and xop1.  Apply avoid_expensive_constant
to each argument after potential swapping.  Enforce the
canonical order of commutative operands.
(expand_binop): Use shift_optab_p and commutative_optab_p.
Update the calls to expand_binop_directly.  Only force constants
into registers when widening an operation.  Only swap operands
once a direct expansion has been rejected.
(expand_twoval_binop): Only force constants into registers when
using a direct expansion.

From-SVN: r127991

gcc/ChangeLog
gcc/optabs.c

index 8e54cb943b2d89fd8be68927527e55b6cccfd6c7..efbaba08c57dd79337be9ca223313acdf8396bf3 100644 (file)
@@ -1,3 +1,20 @@
+2007-08-31  Richard Sandiford  <richard@codesourcery.com>
+
+       * optabs.c (shift_optab_p, commutative_optab_p): New functions,
+       split out from expand_binop.
+       (avoid_expensive_constant): New function.
+       (expand_binop_directly): Remove commutative_op argument and
+       call cummutative_optab_p instead.  Do not change op0 or op1
+       when swapping xop0 and xop1.  Apply avoid_expensive_constant
+       to each argument after potential swapping.  Enforce the
+       canonical order of commutative operands.
+       (expand_binop): Use shift_optab_p and commutative_optab_p.
+       Update the calls to expand_binop_directly.  Only force constants
+       into registers when widening an operation.  Only swap operands
+       once a direct expansion has been rejected.
+       (expand_twoval_binop): Only force constants into registers when
+       using a direct expansion.
+
 2007-08-31  Maxim Kuvyrkov  <maxim@codesourcery.com>
 
        * sched-deps.c (update_dep): Mark arguments with ATTRIBUTE_UNUSED.
index f2b47fc4f685bb9b930597dffbf570afb58cbc1e..6b292638c8967ad56e68fb12d743566e29489bfd 100644 (file)
@@ -1246,6 +1246,56 @@ swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
     return rtx_equal_p (op1, target);
 }
 
+/* Return true if BINOPTAB implements a shift operation.  */
+
+static bool
+shift_optab_p (optab binoptab)
+{
+  switch (binoptab->code)
+    {
+    case ASHIFT:
+    case ASHIFTRT:
+    case LSHIFTRT:
+    case ROTATE:
+    case ROTATERT:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/* Return true if BINOPTAB implements a commutatative binary operation.  */
+
+static bool
+commutative_optab_p (optab binoptab)
+{
+  return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
+         || binoptab == smul_widen_optab
+         || binoptab == umul_widen_optab
+         || binoptab == smul_highpart_optab
+         || binoptab == umul_highpart_optab);
+}
+
+/* X is to be used in mode MODE as an operand to BINOPTAB.  If we're
+   optimizing, and if the operand is a constant that costs more than
+   1 instruction, force the constant into a register and return that
+   register.  Return X otherwise.  UNSIGNEDP says whether X is unsigned.  */
+
+static rtx
+avoid_expensive_constant (enum machine_mode mode, optab binoptab,
+                         rtx x, bool unsignedp)
+{
+  if (optimize
+      && CONSTANT_P (x)
+      && rtx_cost (x, binoptab->code) > COSTS_N_INSNS (1))
+    {
+      if (GET_MODE (x) != VOIDmode)
+       x = convert_modes (mode, VOIDmode, x, unsignedp);
+      x = force_reg (mode, x);
+    }
+  return x;
+}
 
 /* Helper function for expand_binop: handle the case where there
    is an insn that directly implements the indicated operation.
@@ -1254,55 +1304,72 @@ static rtx
 expand_binop_directly (enum machine_mode mode, optab binoptab,
                       rtx op0, rtx op1,
                       rtx target, int unsignedp, enum optab_methods methods,
-                      int commutative_op, rtx last)
+                      rtx last)
 {
   int icode = (int) optab_handler (binoptab, mode)->insn_code;
   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
   enum machine_mode tmp_mode;
+  bool commutative_p;
   rtx pat;
   rtx xop0 = op0, xop1 = op1;
   rtx temp;
+  rtx swap;
   
   if (target)
     temp = target;
   else
     temp = gen_reg_rtx (mode);
-  
+
   /* If it is a commutative operator and the modes would match
      if we would swap the operands, we can save the conversions.  */
-  if (commutative_op)
+  commutative_p = commutative_optab_p (binoptab);
+  if (commutative_p
+      && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1
+      && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1)
     {
-      if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
-         && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
-       {
-         rtx tmp;
-         
-         tmp = op0; op0 = op1; op1 = tmp;
-         tmp = xop0; xop0 = xop1; xop1 = tmp;
-       }
+      swap = xop0;
+      xop0 = xop1;
+      xop1 = swap;
     }
   
+  /* If we are optimizing, force expensive constants into a register.  */
+  xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
+  if (!shift_optab_p (binoptab))
+    xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
+
   /* In case the insn wants input operands in modes different from
      those of the actual operands, convert the operands.  It would
      seem that we don't need to convert CONST_INTs, but we do, so
      that they're properly zero-extended, sign-extended or truncated
      for their mode.  */
   
-  if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
+  if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode)
     xop0 = convert_modes (mode0,
-                         GET_MODE (op0) != VOIDmode
-                         ? GET_MODE (op0)
+                         GET_MODE (xop0) != VOIDmode
+                         ? GET_MODE (xop0)
                          : mode,
                          xop0, unsignedp);
   
-  if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
+  if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode)
     xop1 = convert_modes (mode1,
-                         GET_MODE (op1) != VOIDmode
-                         ? GET_MODE (op1)
+                         GET_MODE (xop1) != VOIDmode
+                         ? GET_MODE (xop1)
                          : mode,
                          xop1, unsignedp);
   
+  /* If operation is commutative,
+     try to make the first operand a register.
+     Even better, try to make it the same as the target.
+     Also try to make the last operand a constant.  */
+  if (commutative_p
+      && swap_commutative_operands_with_target (target, xop0, xop1))
+    {
+      swap = xop1;
+      xop1 = xop0;
+      xop0 = swap;
+    }
+
   /* Now, if insn's predicates don't allow our operands, put them into
      pseudo regs.  */
   
@@ -1375,12 +1442,6 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
   enum mode_class class;
   enum machine_mode wider_mode;
   rtx temp;
-  int commutative_op = 0;
-  int shift_op = (binoptab->code == ASHIFT
-                 || binoptab->code == ASHIFTRT
-                 || binoptab->code == LSHIFTRT
-                 || binoptab->code == ROTATE
-                 || binoptab->code == ROTATERT);
   rtx entry_last = get_last_insn ();
   rtx last;
 
@@ -1395,54 +1456,16 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
       binoptab = add_optab;
     }
 
-  /* If we are inside an appropriately-short loop and we are optimizing,
-     force expensive constants into a register.  */
-  if (CONSTANT_P (op0) && optimize
-      && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
-    {
-      if (GET_MODE (op0) != VOIDmode)
-       op0 = convert_modes (mode, VOIDmode, op0, unsignedp);
-      op0 = force_reg (mode, op0);
-    }
-
-  if (CONSTANT_P (op1) && optimize
-      && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
-    {
-      if (GET_MODE (op1) != VOIDmode)
-       op1 = convert_modes (mode, VOIDmode, op1, unsignedp);
-      op1 = force_reg (mode, op1);
-    }
-
   /* Record where to delete back to if we backtrack.  */
   last = get_last_insn ();
 
-  /* If operation is commutative,
-     try to make the first operand a register.
-     Even better, try to make it the same as the target.
-     Also try to make the last operand a constant.  */
-  if (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
-      || binoptab == smul_widen_optab
-      || binoptab == umul_widen_optab
-      || binoptab == smul_highpart_optab
-      || binoptab == umul_highpart_optab)
-    {
-      commutative_op = 1;
-
-      if (swap_commutative_operands_with_target (target, op0, op1))
-       {
-         temp = op1;
-         op1 = op0;
-         op0 = temp;
-       }
-    }
-
   /* If we can do it with a three-operand insn, do so.  */
 
   if (methods != OPTAB_MUST_WIDEN
       && optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
     {
       temp = expand_binop_directly (mode, binoptab, op0, op1, target,
-                                   unsignedp, methods, commutative_op, last);
+                                   unsignedp, methods, last);
       if (temp)
        return temp;
     }
@@ -1469,8 +1492,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
                               NULL_RTX, unsignedp, OPTAB_DIRECT);
                                   
       temp = expand_binop_directly (mode, otheroptab, op0, newop1,
-                                   target, unsignedp, methods,
-                                   commutative_op, last);
+                                   target, unsignedp, methods, last);
       if (temp)
        return temp;
     }
@@ -1529,7 +1551,14 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
                 || binoptab == add_optab || binoptab == sub_optab
                 || binoptab == smul_optab || binoptab == ashl_optab)
                && class == MODE_INT)
-             no_extend = 1;
+             {
+               no_extend = 1;
+               xop0 = avoid_expensive_constant (mode, binoptab,
+                                                xop0, unsignedp);
+               if (binoptab != ashl_optab)
+                 xop1 = avoid_expensive_constant (mode, binoptab,
+                                                  xop1, unsignedp);
+             }
 
            xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
 
@@ -1558,6 +1587,18 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
          }
       }
 
+  /* If operation is commutative,
+     try to make the first operand a register.
+     Even better, try to make it the same as the target.
+     Also try to make the last operand a constant.  */
+  if (commutative_optab_p (binoptab)
+      && swap_commutative_operands_with_target (target, op0, op1))
+    {
+      temp = op1;
+      op1 = op0;
+      op0 = temp;
+    }
+
   /* These can be done a word at a time.  */
   if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
       && class == MODE_INT
@@ -1980,7 +2021,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       start_sequence ();
 
-      if (shift_op)
+      if (shift_optab_p (binoptab))
        {
          op1_mode = targetm.libgcc_shift_count_mode ();
          /* Specify unsigned here,
@@ -2256,16 +2297,6 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
 
   class = GET_MODE_CLASS (mode);
 
-  /* If we are inside an appropriately-short loop and we are optimizing,
-     force expensive constants into a register.  */
-  if (CONSTANT_P (op0) && optimize
-      && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
-    op0 = force_reg (mode, op0);
-
-  if (CONSTANT_P (op1) && optimize
-      && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
-    op1 = force_reg (mode, op1);
-
   if (!targ0)
     targ0 = gen_reg_rtx (mode);
   if (!targ1)
@@ -2282,6 +2313,10 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
       rtx pat;
       rtx xop0 = op0, xop1 = op1;
 
+      /* If we are optimizing, force expensive constants into a register.  */
+      xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
+      xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
+
       /* In case the insn wants input operands in modes different from
         those of the actual operands, convert the operands.  It would
         seem that we don't need to convert CONST_INTs, but we do, so