Bug 111780 - Missed optimization of '(t*4)/(t*2) -> 2'
Summary: Missed optimization of '(t*4)/(t*2) -> 2'
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2023-10-12 07:56 UTC by Yi
Modified: 2023-10-12 08:34 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-10-12 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yi 2023-10-12 07:56:54 UTC
Hello, we found some optimizations (regarding Arithmetic optimization) that GCC may have missed. We would greatly appreicate if you can take a look and let us know what you think.

Given the following code:
https://godbolt.org/z/G9rWK7c3q
int n1;
void func1(int a){
    if(a>1&&a<4) n1=(a+a+a+a)/(a+a);
}

Different from PR 111718, this missed optimization appears to be due to a missed pattern: (t*4)/(t*2) -> 2

  # DEBUG BEGIN_STMT
  # RANGE [irange] int [8, 8][12, 12] NONZERO 0xc
  _3 = a_7(D) * 4;
  # RANGE [irange] int [4, 4][6, 6] NONZERO 0x6
  _4 = a_7(D) * 2;
  # RANGE [irange] int [1, 3] NONZERO 0x3
  _5 = _3 / _4;
  # .MEM_9 = VDEF <.MEM_8(D)>
  n1D.2761 = _5;

Or a more general pattern: (t*m)/(t*n) -> m/n , where m and n are constants.

Thank you very much for your time and effort! We look forward to hearing from you.
Comment 1 Richard Biener 2023-10-12 08:34:44 UTC
Confirmed.  Same for

int foo (int a, int b, int c)
{
  return 2*c*(a*b) / (a*b);
}

note when we cannot remove the division like for

 c*a / d*a

we have to watch out for -INT_MIN / -1, but I think the only way
this would not invoke undefined behavior before the transform is
when the factor is equal to -1 but then c*a cannot be -INT_MIN so
it should be safe in general, not only when m and n are constants?

Note we cannot re-associate for the transform.

We only have

/* Simplify (t * 2) / 2) -> t.  */
(for div (trunc_div ceil_div floor_div round_div exact_div)
 (simplify
  (div (mult:c @0 @1) @1)
  (if (ANY_INTEGRAL_TYPE_P (type))
   (if (TYPE_OVERFLOW_UNDEFINED (type))
    @0
#if GIMPLE
    (with {value_range vr0, vr1;}
     (if (INTEGRAL_TYPE_P (type)
          && get_range_query (cfun)->range_of_expr (vr0, @0)
          && get_range_query (cfun)->range_of_expr (vr1, @1)
          && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1))
      @0))
#endif
   ))))

but not the case with two multiplies.