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

            Bug ID: 91510
           Summary: r253207 fixed a wrong-code bug
           Product: gcc
           Version: 7.4.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rguenth at gcc dot gnu.org
  Target Milestone: ---

For GCC 8, r253207 fixed a wrong-code bug with SRA where we end up using
the 'double' member in

  union
  {
    unsigned long long int uint_val;
    long long int int_val;
    double double_val;
  };

to copy the aggregate which, when using x87 instructions fldl/fstpl
can alter the bit-pattern.  See also PR88240 for a related issue.
It requires the correct amount of "luck" to hit, the following simplified
testcase doesn't hit it:

struct S
{
  int key;
  union
    {
      unsigned long long int uint_val;
      long long int int_val;
      double double_val;
    } u;
};

struct S get();

void copy (struct S *dst, struct S *src)
{
  struct S tem = get ();
  switch (tem.key)
    {
    case 0:
      dst->u.uint_val = tem.u.uint_val;
      break;
    case 1:
      dst->u.int_val = tem.u.int_val;
      break;
    case 2:
      dst->u.double_val = tem.u.double_val;
      break;
    }
  dst->key = tem.key;
}

while from the full testcase the late SRA dump shows

 value_base* test(std::istream&) (struct istream & source)
 {
+  const double num$D37803$double_val;
   double D.44239;
   long long int D.44232;
   long long unsigned int D.44225;
@@ -733,11 +743,12 @@

   <bb 2> [100.00%]:
   num = parseNumber (source_5(D)); [return slot optimization]
+  num$D37803$double_val_52 = MEM[(struct number_t *)&num + 4B];
   _1 = num.type;
   switch (_1) <default: <L3> [25.00%], case 0: <L14> [25.00%], case 1: <L20>
[25.00%], case 2: <L26> [25.00%]>

 <L14> [25.00%]:
-  _30 = num.D.37803.uint_val;
+  _30 = VIEW_CONVERT_EXPR<long long unsigned int>(num$D37803$double_val_52);
...

 <L26> [25.00%]:
-  _50 = num.D.37803.double_val;
+  _50 = num$D37803$double_val_52;

Reply via email to