diff mbox

Fix PR rtl-optimization/51924

Message ID 201201221529.43028.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Jan. 22, 2012, 2:29 p.m. UTC
This is another problem uncovered by the generalization of the ZEE pass: when 
the definition insn of an extension is itself an extension, modifying the insn 
for the first extension breaks the handling of the second extension.  This was 
silent in ZEE because you never have 2 identical successive extensions, but is 
now exposed in REE.

The attached patch implements a minimal fix with the associated FIXME.  Tested 
on x86_64-suse-linux, applied on the mainline.


2012-01-22  Eric Botcazou  <ebotcazou@adacore.com>

	PR rtl-optimization/51924
	* ree.c (combine_set_extension): Improve debugging message.
	(combine_reaching_defs): Likewise.
	(get_defs): Rename confusingly named variable.
	(find_and_remove_re): Skip a candidate if the extension expression has
	been modified.


2012-01-22  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.dg/ext-elim-1.c: New test.
diff mbox

Patch

Index: ree.c
===================================================================
--- ree.c	(revision 183348)
+++ ree.c	(working copy)
@@ -346,7 +346,8 @@  combine_set_extension (ext_cand *cand, r
     {
       if (dump_file)
         {
-          fprintf (dump_file, "Merged instruction with extension:\n");
+          fprintf (dump_file,
+		   "Tentatively merged extension with definition:\n");
           print_rtl_single (dump_file, curr_insn);
         }
       return true;
@@ -407,21 +408,21 @@  transform_ifelse (ext_cand *cand, rtx de
 static struct df_link *
 get_defs (rtx insn, rtx reg, VEC (rtx,heap) **dest)
 {
-  df_ref reg_info, *defs;
+  df_ref reg_info, *uses;
   struct df_link *ref_chain, *ref_link;
 
   reg_info = NULL;
 
-  for (defs = DF_INSN_USES (insn); *defs; defs++)
+  for (uses = DF_INSN_USES (insn); *uses; uses++)
     {
-      reg_info = *defs;
+      reg_info = *uses;
       if (GET_CODE (DF_REF_REG (reg_info)) == SUBREG)
         return NULL;
       if (REGNO (DF_REF_REG (reg_info)) == REGNO (reg))
         break;
     }
 
-  gcc_assert (reg_info != NULL && defs != NULL);
+  gcc_assert (reg_info != NULL && uses != NULL);
 
   ref_chain = DF_REF_CHAIN (reg_info);
 
@@ -686,11 +687,10 @@  combine_reaching_defs (ext_cand *cand, r
              purposes.  This extension cannot be deleted.  */
           if (dump_file)
             {
-              FOR_EACH_VEC_ELT (rtx, vec, i, def_insn)
-                {
-                  fprintf (dump_file, "Non-mergeable definitions:\n");
-                  print_rtl_single (dump_file, def_insn);
-                }
+	      fprintf (dump_file,
+		       "Merge cancelled, non-mergeable definitions:\n");
+	      FOR_EACH_VEC_ELT (rtx, vec, i, def_insn)
+	        print_rtl_single (dump_file, def_insn);
             }
         }
     }
@@ -843,6 +843,12 @@  find_and_remove_re (void)
     {
       num_re_opportunities++;
 
+      /* If the candidate insn is itself a definition insn for another
+         candidate, it may have been modified and the UD chain broken.
+         FIXME: the handling of successive extensions can be improved.  */
+      if (!reg_mentioned_p (curr_cand->expr, PATTERN (curr_cand->insn)))
+	continue;
+
       /* Try to combine the extension with the definition.  */
       if (dump_file)
         {