This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug rtl-optimization/58517] icvt (after combine) puts ccreg clobbering insn between ccset insn and ccreg use


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58517

--- Comment #4 from Steven Bosscher <steven at gcc dot gnu.org> ---
So if I understand correctly, this is what happens (sorry, reading
LIPSy RTL is still just too unnatural to me! ;-))

before ifcvt-after-combine:
r147:=(r424>r178)
r190:=r423-r189
if (r147==0) goto L433
{r190:=(~r189)+r424; r147:=X}
L433:

after ifcvt-after-combine:
r147:=(r424>r189)
r190:=r423-r189
{r945:=(~r189)+r424; r147:=X}
r946:=r423-r189
r190:=(r147==0) ? r946:r945      // but r147 was clobbered!
r147:=(r190==0)
if (r147==0) goto L501


This is noce_try_cmove_arith:

  /* if (test) x = a + b; else x = c - d;
     => y = a + b;
        x = c - d;
        if (test)
          x = y;
  */

with "(test)" being clobbered by the assignment to "y" or "x" on the
code after the transformation has been applied.  noce_try_cmove_arith
does not expect that the arithmetic insns emitted to load vtrue or
vfalse into general operands may clobber the condition.  There should
be tests like this:

Index: ifcvt.c
===================================================================
--- ifcvt.c     (revision 203224)
+++ ifcvt.c     (working copy)
@@ -1573,6 +1573,8 @@ noce_try_cmove_arith (struct noce_if_info *if_info
                         optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_a)));
       if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost))
        return FALSE;
+      if (modified_in_p (if_info->cond, insn_a))
+       return FALSE;
     }
   else
     insn_cost = 0;
@@ -1584,6 +1586,8 @@ noce_try_cmove_arith (struct noce_if_info *if_info
                          optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_b)));
       if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost))
         return FALSE;
+      if (modified_in_p (if_info->cond, insn_b))
+       return FALSE;
     }

   /* Possibly rearrange operands to make things come out more natural.  */



That's option 1 of comment #3.  Option 2 is only viable if the insn
computing "cond" is nearby (i.e. immediately above insn_a / insn_b),
otherwise it'll be necessary to solve a code motion dataflow problem.
Within one basic block that still would be doable (modified_between_p),
but I doubt it's worth the trouble.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]