Bug 44011 - missed optimization of min/max_expr or strict overflow warnings for intended code.
Summary: missed optimization of min/max_expr or strict overflow warnings for intended...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.5.0
: P3 enhancement
Target Milestone: 5.0
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2010-05-06 09:35 UTC by Pawel Sikora
Modified: 2021-11-25 06:54 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-05-06 10:14:19


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pawel Sikora 2010-05-06 09:35:59 UTC
hi,

please consider following code snippet from large CairoMM base application.
it creates a planar region with top left and bottom right points from two
points passed to RegionT constructor.

$ cat 0.cpp

        static inline int min( int a, int b ) {
                if ( a < b ) return a;
                return b;
        }
        static inline int max( int a, int b ) {
                if ( a > b ) return a;
                return b;
        }
        struct PointT {
                explicit PointT () { x = 0; y = 0; }
                explicit PointT ( int xVal, int yVal ) : x( xVal ), y( yVal ) {}
                int x, y;
        };
        struct RegionT {
                explicit RegionT ( PointT const& p1, PointT const& p2 ) {
                        // calculate top_left and bottom_right coordinates.
                        // (0,0) ---> X
                        //  |
                        //  |
                        //  \/
                        //  Y
#ifdef WARN_AND_OPTIMIZE
                        if ( p1.x < p2.x ) {
                                tl.x = p1.x;
                                br.x = p2.x;
                        } else {
                                tl.x = p2.x;
                                br.x = p1.x;
                        }
                        if ( p1.y < p2.y ) {
                                tl.y = p1.y;
                                br.y = p2.y;
                        } else {
                                tl.y = p2.y;
                                br.y = p1.y;
                        }
#else
                        tl.x = min( p1.x, p2.x );
                        tl.y = min( p1.y, p2.y );
                        br.x = max( p1.x, p2.x );
                        br.y = max( p1.y, p2.y );
#endif
                }
                PointT tl, br;
        };

the application contains lots of places where a region is created
from one base point and constant offsets, e.g.:

        RegionT foo ( PointT const& p ) {
                RegionT r ( p, PointT ( p.x - 2, p.y + 2 ) );
                return r;
        }

for such constructions and -DWARN_AND_OPTIMIZE gcc optimizes RegionT
coordinates calculation at compile time and produces warnings about
strict overflow assumptions.

$ g++ 0.cpp -c -Wall -O2 -fdump-tree-optimized --save-temps -DWARN_AND_OPTIMIZE
0.cpp: In function 'RegionT foo(const PointT&)':
0.cpp:23:4: warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
0.cpp:30:4: warning: assuming signed overflow does not occur when assuming that (X + c) >= X is always true

RegionT foo(const PointT&) (const struct PointT & p)
{
  int r$tl$y;
  int r$tl$x;
  struct RegionT D.2181;
<bb 2>:
  r$tl$y_2 = p_1(D)->y;
  r$tl$y_3 = r$tl$y_2 + 2;
  r$tl$x_4 = p_1(D)->x;
  r$tl$x_5 = r$tl$x_4 + -2;
  D.2181.tl.x = r$tl$x_5;
  D.2181.tl.y = r$tl$y_2;
  D.2181.br.x = r$tl$x_4;
  D.2181.br.y = r$tl$y_3;
  return D.2181;
}

i known signed integer overflow rules but such construction is human
readable and intended, so i would like to still have '-Wall -Werror'
in action for all code and avoid disabling strict-overflow warings for
*global* scope (originally RegionT is implemented as a template in header).

for now, i've hacked in ugly way the if-logic in RegionT constructor
to std::min/max variant. it doesn't warn but produces unoptimal code
with CMOVs for compile time constants.

RegionT foo(const PointT&) (const struct PointT & p)
{
  int a;
  int a;
  struct RegionT D.2182;
  const int D.2178;

<bb 2>:
  D.2178_2 = p_1(D)->y;
  a_3 = D.2178_2 + 2;
  a_4 = p_1(D)->x;
  a_7 = a_4 + -2;
  a_41 = MIN_EXPR <a_7, a_4>;
  a_45 = MIN_EXPR <a_3, D.2178_2>;
  a_42 = MAX_EXPR <a_7, a_4>;
  a_46 = MAX_EXPR <a_3, D.2178_2>;
  D.2182.tl.x = a_41;
  D.2182.tl.y = a_45;
  D.2182.br.x = a_42;
  D.2182.br.y = a_46;
  return D.2182;
}

_Z3fooRK6PointT:
        movl    (%rdi), %edx
        movl    4(%rdi), %eax
        leal    -2(%rdx), %esi
        leal    2(%rax), %ecx
        movl    %edx, %edi
        cmpl    %edx, %esi
        cmovle  %esi, %edi
        cmpl    %eax, %ecx
        movl    %edi, -24(%rsp)
        movl    %eax, %edi
        cmovle  %ecx, %edi
        cmpl    %edx, %esi
        cmovge  %esi, %edx
        cmpl    %eax, %ecx
        movl    %edi, -20(%rsp)
        cmovge  %ecx, %eax
        movl    %edx, -16(%rsp)
        movl    %eax, -12(%rsp)
        movq    -24(%rsp), %rax
        movq    -16(%rsp), %rdx
        ret


how can i disable these warnings for intended part of source code
and get nicely optimized binaries? the gcc rejects my attempts to
'#pragma GCC diagnostic ignore' inside RegionT contstructor with
error: #pragma GCC diagnostic not allowed inside functions :/

thanks in advance for creative hints.
Comment 1 Richard Biener 2010-05-06 10:14:19 UTC
Place the pragma outside of the function (though it'll probably not help
due to the inlining).

The min/max expression missed-optimization is due to the lack of a
tree combiner.  tree forwprop would be the natural candidate to
optimize them.
Comment 2 Pawel Sikora 2010-05-06 11:27:08 UTC
(In reply to comment #1)
> Place the pragma outside of the function (though it'll probably not help
> due to the inlining).

with new function attribute "warning(string...)" similary to existing
"target" and "optimize" atributtes/pragmas it would be possible to manage
warnings for intended parts of code. currently diagnostic system reports
the location of strict-overflow, so i suppose it's able to check a function
attributes and skip some warnings. am i right?
Comment 3 Richard Biener 2010-05-06 11:30:08 UTC
(In reply to comment #2)
> (In reply to comment #1)
> > Place the pragma outside of the function (though it'll probably not help
> > due to the inlining).
> 
> with new function attribute "warning(string...)" similary to existing
> "target" and "optimize" atributtes/pragmas it would be possible to manage
> warnings for intended parts of code. currently diagnostic system reports
> the location of strict-overflow, so i suppose it's able to check a function
> attributes and skip some warnings. am i right?

Huh.  In theory yes.
Comment 4 Andrew Pinski 2021-11-25 06:54:53 UTC
So the missed optimization with -UWARN_AND_OPTIMIZE is fixed in GCC 5.
The warning is fully gone in GCC 8 for both cases since moving over to match and simplify.