diff mbox

[PR45098,9/10] Cheap shift-add.

Message ID 4DD6323B.6030308@codesourcery.com
State New
Headers show

Commit Message

Tom de Vries May 20, 2011, 9:19 a.m. UTC
Hi,

On 05/18/2011 11:20 PM, Zdenek Dvorak wrote:
>> +  sa_cost = (TREE_CODE (expr) != MINUS_EXPR
>> +             ? shiftadd_cost[speed][mode][m]
>> +             : (mult == op1
>> +                ? shiftsub1_cost[speed][mode][m]
>> +                : shiftsub0_cost[speed][mode][m]));
>> +  res = new_cost (sa_cost, 0);
>> +  res = add_costs (res, mult == op1 ? cost0 : cost1);
> 
> just forgetting the cost of the other operand does not seem correct -- what
> if it contains some more complicated subexpression?
> 

True.  I now added the cost of TREE_OPERAND (mult, 0).

Thanks,
- Tom


2011-05-05  Tom de Vries  <tom@codesourcery.com>

	PR target/45098
	* tree-ssa-loop-ivopts.c: Include expmed.h.
	(get_shiftadd_cost): New function.
	(force_expr_to_var_cost): Declare forward.  Use get_shiftadd_cost.

Comments

Zdenek Dvorak May 20, 2011, 5:06 p.m. UTC | #1
Hi,

> On 05/18/2011 11:20 PM, Zdenek Dvorak wrote:
> >> +  sa_cost = (TREE_CODE (expr) != MINUS_EXPR
> >> +             ? shiftadd_cost[speed][mode][m]
> >> +             : (mult == op1
> >> +                ? shiftsub1_cost[speed][mode][m]
> >> +                : shiftsub0_cost[speed][mode][m]));
> >> +  res = new_cost (sa_cost, 0);
> >> +  res = add_costs (res, mult == op1 ? cost0 : cost1);
> > 
> > just forgetting the cost of the other operand does not seem correct -- what
> > if it contains some more complicated subexpression?
> > 
> 
> True.  I now added the cost of TREE_OPERAND (mult, 0).

OK,

Zdenek
Eric Botcazou May 21, 2011, 7:40 a.m. UTC | #2
> 2011-05-05  Tom de Vries  <tom@codesourcery.com>
>
> 	PR target/45098
> 	* tree-ssa-loop-ivopts.c: Include expmed.h.
> 	(get_shiftadd_cost): New function.
> 	(force_expr_to_var_cost): Declare forward.  Use get_shiftadd_cost.

This breaks the Ada compiler on x86:

/home/eric/build/gcc/native32/./gcc/xgcc -B/home/eric/build/gcc/native32/./gcc/ -B/home/eric/install/gcc/i586-suse-linux/bin/ -B/home/eric/install/gcc/i586-suse-linux/lib/ -isystem /home/eric/install/gcc/i586-suse-linux/include -isystem /home/eric/install/gcc/i586-suse-linux/sys-include    -c -g -O2  -fPIC  -W -Wall -gnatpg   
a-calend.adb -o a-calend.o
+===========================GNAT BUG DETECTED==============================+
| 4.7.0 20110521 (experimental) [trunk revision 173887] (i586-suse-linux-gnu) 
GCC error:|
| in int_cst_value, at tree.c:9970                                         |
| Error detected around a-calend.adb:1254:7          

To reproduce, do:
  gcc/gnat1 gcc/ada/rts/a-calend.adb -gnatg -O -Igcc/ada/rts
in the build dir.
diff mbox

Patch

Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c	(revision 173380)
+++ gcc/tree-ssa-loop-ivopts.c	(working copy)
@@ -92,6 +92,12 @@  along with GCC; see the file COPYING3.  
 #include "tree-inline.h"
 #include "tree-ssa-propagate.h"
 
+/* FIXME: add_cost and zero_cost defined in exprmed.h conflict with local uses.
+ */
+#include "expmed.h"
+#undef add_cost
+#undef zero_cost
+
 /* FIXME: Expressions are expanded to RTL in this pass to determine the
    cost of different addressing modes.  This should be moved to a TBD
    interface between the GIMPLE and RTL worlds.  */
@@ -377,6 +383,8 @@  struct iv_ca_delta
 
 static VEC(tree,heap) *decl_rtl_to_reset;
 
+static comp_cost force_expr_to_var_cost (tree, bool);
+
 /* Number of uses recorded in DATA.  */
 
 static inline unsigned
@@ -3504,6 +3512,42 @@  get_address_cost (bool symbol_present, b
   return new_cost (cost + acost, complexity);
 }
 
+ /* Calculate the SPEED or size cost of shiftadd EXPR in MODE.  MULT is the
+    the EXPR operand holding the shift.  COST0 and COST1 are the costs for
+    calculating the operands of EXPR.  Returns true if successful, and returns
+    the cost in COST.  */
+
+static bool
+get_shiftadd_cost (tree expr, enum machine_mode mode, comp_cost cost0,
+                   comp_cost cost1, tree mult, bool speed, comp_cost *cost)
+{
+  comp_cost res;
+  tree op1 = TREE_OPERAND (expr, 1);
+  tree cst = TREE_OPERAND (mult, 1);
+  tree multop = TREE_OPERAND (mult, 0);
+  int m = exact_log2 (int_cst_value (cst));
+  int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode));
+  int sa_cost;
+
+  if (!(m >= 0 && m < maxm))
+    return false;
+
+  sa_cost = (TREE_CODE (expr) != MINUS_EXPR
+             ? shiftadd_cost[speed][mode][m]
+             : (mult == op1
+                ? shiftsub1_cost[speed][mode][m]
+                : shiftsub0_cost[speed][mode][m]));
+  res = new_cost (sa_cost, 0);
+  res = add_costs (res, mult == op1 ? cost0 : cost1);
+
+  STRIP_NOPS (multop);
+  if (!is_gimple_val (multop))
+    res = add_costs (res, force_expr_to_var_cost (multop, speed));
+
+  *cost = res;
+  return true;
+}
+
 /* Estimates cost of forcing expression EXPR into a variable.  */
 
 static comp_cost
@@ -3629,6 +3673,21 @@  force_expr_to_var_cost (tree expr, bool 
     case MINUS_EXPR:
     case NEGATE_EXPR:
       cost = new_cost (add_cost (mode, speed), 0);
+      if (TREE_CODE (expr) != NEGATE_EXPR)
+        {
+          tree mult = NULL_TREE;
+          comp_cost sa_cost;
+          if (TREE_CODE (op1) == MULT_EXPR)
+            mult = op1;
+          else if (TREE_CODE (op0) == MULT_EXPR)
+            mult = op0;
+
+          if (mult != NULL_TREE
+              && TREE_CODE (TREE_OPERAND (mult, 1)) == INTEGER_CST
+              && get_shiftadd_cost (expr, mode, cost0, cost1, mult, speed,
+                                    &sa_cost))
+            return sa_cost;
+        }
       break;
 
     case MULT_EXPR: