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

            Bug ID: 79028
           Summary: Un-optimal/ incorrect forward propagation
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pitchumani.s at hotmail dot com
  Target Milestone: ---

test case: (options: -Os)
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));                 
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef struct rpl_instance rpl_instance_t;
struct rpl_instance {
  uint8_t dio_intcurrent;
  uint32_t dio_next_delay;
};
unsigned short random_rand(void);

void
new_dio_interval(rpl_instance_t *instance)
{
  uint32_t time;
  uint32_t ticks;
  time = 1UL << instance->dio_intcurrent;
  ticks = (time * 128) / 1000;
  instance->dio_next_delay = ticks;
  ticks = ticks / 2 + (ticks / 2 * (uint32_t)random_rand()) / 65535U;
  instance->dio_next_delay -= ticks;
}

tree dump before and after optimizations
(snip from ssa dump)
 _1 = instance_14(D)->dio_intcurrent;
 _2 = (int) _1;
 _3 = 1 << _2;
 time_15 = (uint32_t) _3;
 _4 = time_15 * 128;
 ticks_16 = _4 / 1000;
 instance_14(D)->dio_next_delay = ticks_16;
 _5 = ticks_16 / 2;
 _6 = ticks_16 / 2;
 _7 = random_rand ();
 _8 = (unsigned int) _7;
 _9 = _6 * _8;
 _10 = _9 / 65535;
 ticks_19 = _5 + _10;
 _11 = instance_14(D)->dio_next_delay;
 _12 = _11 - ticks_19;
 instance_14(D)->dio_next_delay = _12;
 return;
(snip)

gcc-7 propagates ticks_16 to definitions of _5 and _6 as part of forwprop1
pass. It contradicts the  descriptions "substituting variables that are used
once into the expression".

(snip from optimized dump)
  <bb 2> [100.00%]:
  _1 = instance_13(D)->dio_intcurrent;
  _2 = (int) _1;
  _3 = 1 << _2;
  time_14 = (uint32_t) _3;
  _4 = time_14 * 128;
  ticks_15 = _4 / 1000;
  instance_13(D)->dio_next_delay = ticks_15;
  _5 = _4 / 2000;
  _6 = random_rand ();
  _7 = (unsigned int) _6;
  _8 = _5 * _7;
  _9 = _8 / 65535;
  _10 = instance_13(D)->dio_next_delay;
  _23 = _10 - _5;
  _11 = _23 - _9;
  instance_13(D)->dio_next_delay = _11;
  return;
(snip)

Without that forward propagation, _5 would be _5 = ticks_15 >> 1, that is
optimal than the current code.
Till gcc-4 it was optimal for this case, got changed gcc-5 onwards.

Reply via email to