[Bug c/87944] Wrong code with LRA pushing stack local variable

2020-01-22 Thread stefan at franke dot ms
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87944

Stefan "Bebbo" Franke  changed:

   What|Removed |Added

 CC|        |stefan at franke dot ms

--- Comment #4 from Stefan "Bebbo" Franke  ---
the problem resides in lra-eliminations.c.

It starts in void eliminate_regs_in_insn where a simple plus bypasses the stack
offset handling:

  /* If we have a nonzero offset, and the source is already a
 simple REG, the following transformation would increase
 the cost of the insn by replacing a simple REG with (plus
 (reg sp) CST).  So try only when we already had a PLUS
 before.  */
  if (known_eq (offset, 0) || plus_src)

because lra_get_insn_recog_data (insn)->sp_offset is not considered.


With the m68k architecture plus using lra you get this problem plus some
similar ones, all related to arg / frame / stack pointer conversion with
incorrect offsets.


I fixed it locally with few more changes in lra-elimintaions.c

[Bug rtl-optimization/70961] Regrename ignores preferred_rename_class

2017-03-21 Thread stefan at franke dot ms
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70961

Stefan "Bebbo" Franke  changed:

   What|Removed |Added

 CC|        |stefan at franke dot ms

--- Comment #6 from Stefan "Bebbo" Franke  ---
Simply remove the outer loop and iterate only once:

  has_preferred_class = (preferred_class != NO_REGS);
  for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
{
  if (has_preferred_class
  && !TEST_HARD_REG_BIT(reg_class_contents[preferred_class],
   new_reg))
continue;

  if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
continue;

  if (!best_rename)
return new_reg;

  /* In the first pass, we force the renaming of registers that
   don't belong to PREFERRED_CLASS to registers that do, even
   though the latters were used not very long ago.
   Also use a register if no best_new_reg was found till now  */
  if ((tick[best_new_reg] > tick[new_reg]
  || (old_reg == best_new_reg && new_reg < old_reg)))
best_new_reg = new_reg;
}

The last "if" is my experimental version. I am also testing (with m68k) an
extended preferred_rename_class2 method, which uses the register to return a
maybe better class:

  preferred_class = (enum reg_class) targetm.preferred_rename_class2 (
  super_class, old_reg);

And yes, the code is smaller and faster.

[Bug rtl-optimization/80126] New: df_ref_change_reg_with_loc does not update hard_regs_live_count

2017-03-21 Thread stefan at franke dot ms
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80126

Bug ID: 80126
   Summary: df_ref_change_reg_with_loc does not update
hard_regs_live_count
   Product: gcc
   Version: 6.3.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: rtl-optimization
  Assignee: unassigned at gcc dot gnu.org
  Reporter: stefan at franke dot ms
  Target Milestone: ---

The method


static void
df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df,
  struct df_reg_info *new_df,
  unsigned int new_regno, rtx loc)

does not update the hard_regs_live_count.

Old:

...
  struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref);

  DF_REF_REGNO (the_ref) = new_regno;
...

Fixed:

...
  struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref);

  if (DF_REF_FLAGS_IS_SET(the_ref, DF_HARD_REG_LIVE))
{
  --df->hard_regs_live_count[DF_REF_REGNO(the_ref)];
  ++df->hard_regs_live_count[new_regno];
}

  DF_REF_REGNO (the_ref) = new_regno;
...

[Bug rtl-optimization/80127] New: regrename_do_replace does not update the df refs

2017-03-21 Thread stefan at franke dot ms
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80127

Bug ID: 80127
   Summary: regrename_do_replace does not update the df refs
   Product: gcc
   Version: 6.3.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: rtl-optimization
  Assignee: unassigned at gcc dot gnu.org
  Reporter: stefan at franke dot ms
  Target Milestone: ---

The method regrename_do_replace does neither update the df refs nor reset the
ever_live flag. Also the passes for stack variables are scheduled to early.

This leads to eliminated variables which are still pushed/popped to/from stack
but are never used.



Old code:

bool
regrename_do_replace (struct du_head *head, int regno)
{
...
  mode = GET_MODE(*head->first->loc);
  head->renamed = 1;
  head->regno = regno;
  head->nregs = hard_regno_nregs[regno][mode];

  return true;
}

My code:

bool
regrename_do_replace (struct du_head *head, int regno)
{
...
  mode = GET_MODE(*head->first->loc);
  head->renamed = 1;
  head->regno = regno;
  head->nregs = hard_regno_nregs[regno][mode];

  /* SBF: also update the current df info, move from base_regno -> regno. */
  if (base_regno < FIRST_PSEUDO_REGISTER && regno < FIRST_PSEUDO_REGISTER)
for (chain = head->first; chain; chain = chain->next_use)
  {
if (DEBUG_INSN_P (chain->insn))
  continue;
/* undo regno patch - will be patched again */
if (REGNO (*chain->loc) == regno)
  SET_REGNO(*chain->loc, base_regno);
df_ref_change_reg_with_loc (*chain->loc, regno);

SET_REGNO(*chain->loc, regno);
  }

  /* SBF: Mark the old regno as no longer used. */
  if (!df->hard_regs_live_count[base_regno])
df_set_regs_ever_live (base_regno, false);

  return true;
}

I also moved the stack creation passed after regrename:

passes.def:

...
  NEXT_PASS (pass_regrename);
  NEXT_PASS (pass_cprop_hardreg);
  NEXT_PASS (pass_thread_prologue_and_epilogue);
  NEXT_PASS (pass_rtl_dse2);
  NEXT_PASS (pass_stack_adjustments);
...


=> No more push/pop for unused variables due to regrename.

[Bug tree-optimization/99364] New: Regression: loops not optimized to count to 0/-1

2021-03-03 Thread stefan at franke dot ms via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99364

Bug ID: 99364
   Summary: Regression: loops not optimized to count to 0/-1
   Product: gcc
   Version: tree-ssa
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: tree-optimization
  Assignee: unassigned at gcc dot gnu.org
  Reporter: stefan at franke dot ms
  Target Milestone: ---

consider this simple loop:
```
void ArrayFill2(int *array, int len) {
  int i = 0;
  for(; i < len; ++i)
array[i] = 50;
}
```

gcc 2.93 was able to convert this into a loop counting to zero.
gcc 6/7/8/9/10/11 can't do that.

if you change the code above:
```
void ArrayFill2(int *array) {
  int i = 0;
  int len = 42;
  for(; i < len; ++i)
array[i] = 50;
}
```
then it works and you get this after ivcanon:
```
  int i;
  unsigned int i.0_4;
  unsigned int _5;
  int * _7;
  unsigned int ivtmp_15;
  unsigned int ivtmp_16;

  :

  :
  # i_13 = PHI 
  # ivtmp_16 = PHI 
  i.0_4 = (unsigned int) i_13;
  _5 = i.0_4 * 4;
  _7 = array_6(D) + _5;
  *_7 = 50;
  i_9 = i_13 + 1;
  ivtmp_15 = ivtmp_16 - 1;
  if (ivtmp_15 != 0)
goto ;
  else
goto ;

  :
  goto ;

  :
  return;

```

so the expected result for the version above, with len as parameter would be
something like this where the constant loop count is replaced by len-1:

```
  int i;
  unsigned int i.0_4;
  unsigned int _5;
  int * _7;
  int ivtmp_14
  unsigned int ivtmp_15;
  unsigned int ivtmp_16;

  :
  ivtmp_14 = len_4(D) - 1;

  :
  # i_13 = PHI 
  # ivtmp_16 = PHI 
  i.0_4 = (unsigned int) i_13;
  _5 = i.0_4 * 4;
  _7 = array_6(D) + _5;
  *_7 = 50;
  i_9 = i_13 + 1;
  ivtmp_15 = ivtmp_16 - 1;
  if (ivtmp_15 != 0)
goto ;
  else
goto ;

  :
  goto ;

  :
  return;
```

To handle this tree-ssa-loop-ivcanon must be able to handle no only const_int
loop limits but also a const loop limit provided in a variable.