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

            Bug ID: 79006
           Summary: [6/7 Regression] Invalid transformation in
                    tree-dominators pass
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wschmidt at gcc dot gnu.org
  Target Milestone: ---

Compile the following with -Os on GCC 6.3 or current trunk:

typedef struct
{
  unsigned long a_type;
  union
  {
    unsigned long a_val;
  } a_un;
} Elf64_auxv_t;

void
auxv_up (Elf64_auxv_t *av, unsigned type, unsigned const value)
{
  if (av)
    for (;; ++av)
      {
        if (av->a_type == type
            || (av->a_type == 1 && type != 0))
          {
            av->a_type = type;
            av->a_un.a_val = value;
            return;
          }
      }
}

The generated code causes av->a_type to receive a wrong value along the
fall-through path.  On powerpc64le, this is what we see:

auxv_up:
        cmpdi 0,3,0
        beqlr 0
        cmpdi 5,4,0
.L6:
        ld 9,0(3)
        cmpld 7,9,4
        bne 7,.L3
.L5:
        std 9,0(3)  <-- Should be std 4,0(3) to store "type"
        std 5,8(3)
        blr
.L7:
        mr 9,4
        b .L5
.L3:
        cmpldi 7,9,1
        bne 7,.L4
        bne 5,.L7
.L4:
        addi 3,3,16
        b .L6

I've narrowed this down to the dom3 pass.  Prior to dom3, the GIMPLE is:

auxv_up (struct Elf64_auxv_t * av, unsigned int type, const unsigned int value)
{
  long unsigned int _1;
  long unsigned int _2;
  long unsigned int _3;
  long unsigned int _4;
  long unsigned int _5;
  long unsigned int _18;

  <bb 2> [13.5%]:
  if (av_8(D) != 0B)
    goto <bb 11>; [73.3%]
  else
    goto <bb 10>; [26.7%]

  <bb 11> [9.9%]:

  <bb 3> [100.0%]:
  # av_6 = PHI <av_8(D)(11), av_11(9)>
  _1 = MEM[base: av_6, offset: 0B];
  _2 = (long unsigned int) type_10(D);
  if (_1 == _2)
    goto <bb 4>; [7.5%]
  else
    goto <bb 6>; [92.5%]

  <bb 4> [7.5%]:
  # _3 = PHI <_2(3)>
  # av_19 = PHI <av_6(3)>

  <bb 5> [9.9%]:
  # _18 = PHI <_3(4), _4(8)>          ; _18 always equal to _2
  # av_15 = PHI <av_19(4), av_16(8)>
  av_15->a_type = _18;
  _5 = (long unsigned int) value_13(D);
  av_15->a_un.a_val = _5;
  goto <bb 10>; [100.0%]

  <bb 6> [92.5%]:
  if (_1 == 1)
    goto <bb 7>; [34.0%]
  else
    goto <bb 9>; [66.0%]

  <bb 7> [31.4%]:
  if (type_10(D) != 0)
    goto <bb 8>; [7.5%]
  else
    goto <bb 9>; [92.5%]

  <bb 8> [2.4%]:
  # _4 = PHI <_2(7)>
  # av_16 = PHI <av_6(7)>
  goto <bb 5>; [100.0%]

  <bb 9> [90.1%]:
  av_11 = av_6 + 16;
  goto <bb 3>; [100.0%]

  <bb 10> [13.5%]:
  return;

}

Following dom3 we have:

auxv_up (struct Elf64_auxv_t * av, unsigned int type, const unsigned int value)
{
  long unsigned int _1;
  long unsigned int _2;
  long unsigned int _3;
  long unsigned int _4;
  long unsigned int _5;
  long unsigned int _18;

  <bb 2> [13.5%]:
  if (av_8(D) != 0B)
    goto <bb 3>; [73.3%]
  else
    goto <bb 10>; [26.7%]

  <bb 3> [100.0%]:
  # av_6 = PHI <av_8(D)(2), av_11(9)>
  _1 = MEM[base: av_6, offset: 0B];
  _2 = (long unsigned int) type_10(D);
  if (_1 == _2)
    goto <bb 4>; [7.5%]
  else
    goto <bb 6>; [92.5%]

  <bb 4> [7.5%]:
  # _3 = PHI <_2(3)>
  # av_19 = PHI <av_6(3)>

  <bb 5> [9.9%]:
  # _18 = PHI <_1(4), _2(8)>             ; _18 can now equal av->a_type instead
  # av_15 = PHI <av_6(4), av_6(8)>
  av_6->a_type = _18;
  _5 = (long unsigned int) value_13(D);
  av_6->a_un.a_val = _5;
  goto <bb 10>; [100.0%]

  <bb 6> [92.5%]:
  if (_1 == 1)
    goto <bb 7>; [34.0%]
  else
    goto <bb 9>; [66.0%]

  <bb 7> [31.4%]:
  if (type_10(D) != 0)
    goto <bb 8>; [7.5%]
  else
    goto <bb 9>; [92.5%]

  <bb 8> [2.4%]:
  # _4 = PHI <_2(7)>
  # av_16 = PHI <av_6(7)>
  goto <bb 5>; [100.0%]

  <bb 9> [90.1%]:
  av_11 = av_6 + 16;
  goto <bb 3>; [100.0%]

  <bb 10> [13.5%]:
  return;

}

Reply via email to