https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89505

            Bug ID: 89505
           Summary: [9 Regression] LibreOffice miscompilation starting
                    with r260383
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

Created attachment 45823
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45823&action=edit
rh1682941.ii.xz

The attached testcase from LibreOffice is miscompiled starting with r260383
with
-O2 -fPIC -std=c++2a, unfortunately don't have a smaller testcase so far and
haven't succeeded in coming up with a reduced one.

In the dumps, look for case 263392: or 263392 and in *.optimized dump it should
look like:
  _59 = rtl_str_toInt32 (_58, 10);
  _148 = MIN_EXPR <_59, 1024>;
  _73 = MAX_EXPR <_148, 1>;
  this_12(D)->nColCount = _73;
but starting with r260383 it is not.

We have before dse1 code like:
  D.857771 = 1;
...
  _129 = rtl_str_toInt32 (_128, 10);
  D.857770 = _129;
  if (_129 <= 0)
    goto <bb 8>; [34.00%]
  else
    goto <bb 9>; [66.00%]

  <bb 8> :

  <bb 9> :
  # _119 = PHI <&D.857770(7), &D.857771(8)>
  _12 = *_119;
  this_29(D)->nColCount = _12;
  D.857770 ={v} {CLOBBER};
  D.857771 ={v} {CLOBBER};
  D.857772 = 1024;
  _13 = &this_29(D)->nColCount;
  if (_12 > 1024)
    goto <bb 10>; [34.00%]
  else
    goto <bb 11>; [66.00%]

  <bb 10> :

  <bb 11> :
  # _116 = PHI <_13(9), &D.857772(10)>
  _15 = *_116;
  this_29(D)->nColCount = _15;

In *.mergephi1 with -alias-vops the difference (trunk vs. trunk with r260383
reverted) is:
   # .MEM_55 = VDEF <.MEM_23>
   D.857771 = 1;
...
   # .MEM_206 = VDEF <.MEM_55>
-  # USE = nonlocal null { D.112965 D.113017 D.857775 D.857777 D.857779 }
(nonlocal, escaped, interposable)
-  # CLB = nonlocal null { D.112965 D.113017 D.857775 D.857777 D.857779 }
(nonlocal, escaped, interposable)
+  # USE = nonlocal null { D.112965 D.113017 D.857775 D.857777 D.857779
D.1010617 } (nonlocal, escaped, restrict, interposable)
+  # CLB = nonlocal null { D.112965 D.113017 D.857775 D.857777 D.857779
D.1010617 } (nonlocal, escaped, restrict, interposable)
   _129 = rtl_str_toInt32 (_128, 10);
   # .MEM_57 = VDEF <.MEM_206>
   D.857770 = _129;
   if (_129 <= 0)
     goto <bb 8>; [34.00%]
   else
     goto <bb 9>; [66.00%]

   <bb 8> :

   <bb 9> :
   # PT = { D.857770 D.857771 }
   # ALIGN = 4, MISALIGN = 0
   # _119 = PHI <&D.857770(7), &D.857771(8)>
   # VUSE <.MEM_57>
-  _12 = *_119;
+  _12 = MEM[(const int &)_119 clique 1 base 0];
   # .MEM_59 = VDEF <.MEM_57>
-  this_29(D)->nColCount = _12;
+  MEM[(struct ScXMLTableColContext *)this_29(D) clique 1 base 1].nColCount =
_12;
   # .MEM_60 = VDEF <.MEM_59>
   D.857770 ={v} {CLOBBER};
   # .MEM_61 = VDEF <.MEM_60>
   D.857771 ={v} {CLOBBER};
   # .MEM_62 = VDEF <.MEM_61>
   D.857772 = 1024;
-  # PT = nonlocal 
+  # PT = { D.1010617 } (nonlocal, escaped)
   _13 = &this_29(D)->nColCount;
   if (_12 > 1024)
     goto <bb 10>; [34.00%]
   else
     goto <bb 11>; [66.00%]

   <bb 10> :

   <bb 11> :
-  # PT = nonlocal { D.857772 }
+  # PT = { D.857772 D.1010617 } (nonlocal, escaped)
   # _116 = PHI <_13(9), &D.857772(10)>
   # VUSE <.MEM_62>
-  _15 = *_116;
+  _15 = MEM[(const int &)_116 clique 1 base 0];
   # .MEM_64 = VDEF <.MEM_62>
-  this_29(D)->nColCount = _15;
+  MEM[(struct ScXMLTableColContext *)this_29(D) clique 1 base 1].nColCount =
_15;

and DSE1 removes the nColCount store:
   <bb 9> :
   # _119 = PHI <&D.857770(7), &D.857771(8)>
   _12 = *_119;
-  this_29(D)->nColCount = _12;
   D.857770 ={v} {CLOBBER};
   D.857771 ={v} {CLOBBER};
   D.857772 = 1024;
...
   <bb 11> :
   # _116 = PHI <_13(9), &D.857772(10)>
   _15 = *_116;
-  this_29(D)->nColCount = _15;
+  *this_29(D).nColCount = _15;
   D.857772 ={v} {CLOBBER};
   goto <bb 18>; [INV]

I've tried to reduce this to:
template<typename _Tp> constexpr inline const _Tp&
min (const _Tp& __a, const _Tp& __b) { if (__b < __a) return __b; return __a; }
template<typename _Tp> constexpr inline const _Tp&
max (const _Tp& __a, const _Tp& __b) { if (__a < __b) return __b; return __a; }
template<typename _Tp, typename _Compare> constexpr inline const _Tp&
min (const _Tp& __a, const _Tp& __b, _Compare __comp) { if (__comp(__b, __a))
return __b; return __a; }
template<typename _Tp, typename _Compare> constexpr inline const _Tp&
max (const _Tp& __a, const _Tp& __b, _Compare __comp) { if (__comp(__a, __b))
return __b; return __a; }
int foo () throw ();
struct S { char pad[80]; int nColCount; S (); };
const signed short m = 1024;
int v;
S::S ()
{
  nColCount = 1;
  if (v)
    {
      nColCount = max<int> (foo (), 1);
      nColCount = min<int> (nColCount, m);
    }
}
but that doesn't reproduce this.

Reply via email to