diff mbox

[RFC,tentative] Adjust cost for conversion expression

Message ID 90583097-cd60-0152-66a5-e32d6830b776@microchip.com
State New
Headers show

Commit Message

Pitchumani Sivanupandi Nov. 24, 2016, 10:58 a.m. UTC
GCC inlines small functions if the code size after expansion is not 
excedded.
For test case (inline.c, avr-gcc -Os -S inline.c) code size become higher if
'func2' is inlined. It happens because the CONVERT_EXPR/ NOP_EXPR are 
considered
as zero cost expression.

Few conversions will cost additional instructions. For targets like AVR
it will cost considerably as it's register size is just one byte.

Attached the tentative patch that changes the CONVERT_EXPR/ NOP_EXPR cost
to 1 if the LHS is bigger than RHS and target's word_mode.

Is this Ok?

Would it be reasonable if cost evaluated as below instead of constant 1?
   if (LHS PRECISION > RHS PRECISION)
     cost = LHS_PRECISION / word_mode - 1
   else
     cost = 0

Built GCC for native with bootstrap enabled. No issues.

Regards,
Pitchumani

Comments

Richard Biener Nov. 24, 2016, 11:24 a.m. UTC | #1
On Thu, 24 Nov 2016, Pitchumani Sivanupandi wrote:

> GCC inlines small functions if the code size after expansion is not excedded.

> For test case (inline.c, avr-gcc -Os -S inline.c) code size become higher if

> 'func2' is inlined. It happens because the CONVERT_EXPR/ NOP_EXPR are

> considered

> as zero cost expression.

> 

> Few conversions will cost additional instructions. For targets like AVR

> it will cost considerably as it's register size is just one byte.

> 

> Attached the tentative patch that changes the CONVERT_EXPR/ NOP_EXPR cost

> to 1 if the LHS is bigger than RHS and target's word_mode.

> 

> Is this Ok?

> 

> Would it be reasonable if cost evaluated as below instead of constant 1?

>   if (LHS PRECISION > RHS PRECISION)

>     cost = LHS_PRECISION / word_mode - 1

>   else

>     cost = 0

> 

> Built GCC for native with bootstrap enabled. No issues.


I believe a better check would be tree_nop_conversion_p ().  Thus

  CASE_CONVERT:
    return tree_nop_conversion_p (type, TREE_TYPE (op0)) ? 0 : 1;

note that

+      rhs_code = gimple_assign_rhs_code (stmt);
+      if ((rhs_code == NOP_EXPR) || (rhs_code == CONVERT_EXPR))
+      {
+        cost += estimate_operator_cost (rhs_code, weights,
+                     gimple_assign_lhs (stmt),
+                     gimple_assign_rhs1 (stmt));
+      }

is super-ugly - please simply add the type of the expression as an
additional argument (see gimple_expr_type (), but the type of the
LHS would do as well).

Note that doing this change might require some re-tuning of
inliner params, but otherwise it's totally sensible.

Thanks,
Richard.
Jeff Law Nov. 28, 2016, 10:40 p.m. UTC | #2
On 11/24/2016 03:58 AM, Pitchumani Sivanupandi wrote:
> GCC inlines small functions if the code size after expansion is not

> excedded.

> For test case (inline.c, avr-gcc -Os -S inline.c) code size become

> higher if

> 'func2' is inlined. It happens because the CONVERT_EXPR/ NOP_EXPR are

> considered

> as zero cost expression.

>

> Few conversions will cost additional instructions. For targets like AVR

> it will cost considerably as it's register size is just one byte.

>

> Attached the tentative patch that changes the CONVERT_EXPR/ NOP_EXPR cost

> to 1 if the LHS is bigger than RHS and target's word_mode.

>

> Is this Ok?

>

> Would it be reasonable if cost evaluated as below instead of constant 1?

>   if (LHS PRECISION > RHS PRECISION)

>     cost = LHS_PRECISION / word_mode - 1

>   else

>     cost = 0

>

> Built GCC for native with bootstrap enabled. No issues.

My high level worry here is that this introduces a target dependency 
into the early part of the tree optimization pipeline (the test against 
word_mode).

I'd be more open to giving a cost to any widening conversion.    That 
kind of change might have a wide reaching impact though.

jeff
diff mbox

Patch

diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6899d2a..dbb305d 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3867,19 +3867,28 @@  estimate_move_cost (tree type, bool ARG_UNUSED (speed_p))
 
 static int
 estimate_operator_cost (enum tree_code code, eni_weights *weights,
-			tree op1 ATTRIBUTE_UNUSED, tree op2)
+			tree op1, tree op2)
 {
+  unsigned int lhs_prec, rhs_prec;
   switch (code)
     {
     /* These are "free" conversions, or their presumed cost
        is folded into other operations.  */
     case RANGE_EXPR:
-    CASE_CONVERT:
     case COMPLEX_EXPR:
     case PAREN_EXPR:
     case VIEW_CONVERT_EXPR:
       return 0;
-
+    CASE_CONVERT:
+    {
+      if (op1 && op2) {
+        lhs_prec = element_precision (TREE_TYPE (op1));
+        rhs_prec = element_precision (TREE_TYPE (op2));
+        if ((lhs_prec > rhs_prec) && (lhs_prec > word_mode))
+          return 1;
+      }
+      return 0;
+    }
     /* Assign cost of 1 to usual operations.
        ??? We may consider mapping RTL costs to this.  */
     case COND_EXPR:
@@ -4026,6 +4035,7 @@  estimate_num_insns (gimple *stmt, eni_weights *weights)
 {
   unsigned cost, i;
   enum gimple_code code = gimple_code (stmt);
+  enum tree_code rhs_code;
   tree lhs;
   tree rhs;
 
@@ -4064,9 +4074,17 @@  estimate_num_insns (gimple *stmt, eni_weights *weights)
       if (gimple_assign_load_p (stmt))
 	cost += estimate_move_cost (TREE_TYPE (rhs), weights->time_based);
 
-      cost += estimate_operator_cost (gimple_assign_rhs_code (stmt), weights,
+      rhs_code = gimple_assign_rhs_code (stmt);
+      if ((rhs_code == NOP_EXPR) || (rhs_code == CONVERT_EXPR))
+      {
+        cost += estimate_operator_cost (rhs_code, weights,
+                     gimple_assign_lhs (stmt),
+                     gimple_assign_rhs1 (stmt));
+      }
+      else
+        cost += estimate_operator_cost (rhs_code, weights,
       				      gimple_assign_rhs1 (stmt),
-				      get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
+				      get_gimple_rhs_class (rhs_code)
 				      == GIMPLE_BINARY_RHS
 				      ? gimple_assign_rhs2 (stmt) : NULL);
       break;