This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug other/44011] New: missed optimization of min/max_expr or strict overflow warnings for intended code.


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.


-- 
           Summary: missed optimization of  min/max_expr or strict overflow
                    warnings for intended code.
           Product: gcc
           Version: 4.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: pluto at agmk dot net


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44011


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]