re PR tree-optimization/50693 (Loop optimization restricted by GOTOs)
authorJakub Jelinek <jakub@redhat.com>
Sat, 5 Nov 2011 19:58:37 +0000 (20:58 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 5 Nov 2011 19:58:37 +0000 (20:58 +0100)
PR tree-optimization/50693
* tree-cfg.c (gimple_can_merge_blocks_p): Allow merging with
non-forced user labels.
(gimple_merge_blocks): Turn non-forced user labels into
debug bind stmt with the label as first operand and reset value.
(gimple_duplicate_bb): Don't duplicate label debug stmts.
* dwarf2out.c (gen_label_die): Handle NOTE_INSN_DELETED_DEBUG_LABEL.
* final.c (final_scan_insn): Likewise.
(rest_of_clean_state): Don't dump NOTE_INSN_DELETED_DEBUG_LABEL.
* var-tracking.c (debug_label_num): New variable.
(delete_debug_insns): Don't delete DEBUG_INSNs for LABEL_DECLs,
instead turn them into NOTE_INSN_DELETED_DEBUG_LABEL notes.
* cfglayout.c (skip_insns_after_block, duplicate_insn_chain): Handle
NOTE_INSN_DELETED_DEBUG_LABEL.
(duplicate_insn_chain): Don't duplicate LABEL_DECL DEBUG_INSNs.
* insn-notes.def (DELETED_DEBUG_LABEL): New note kind.
* print-rtl.c (print_rtx): Handle NOTE_INSN_DELETED_DEBUG_LABEL.
* gengtype.c (adjust_field_rtx_def): Likewise.
* config/i386/i386.c (ix86_output_function_epilogue): For MachO
clear CODE_LABEL_NUMBER of NOTE_INSN_DELETED_DEBUG_LABEL
if their are at the end of function and nop hasn't been emitted.
* config/rs6000/rs6000.c (rs6000_output_function_epilogue): Likewise.

From-SVN: r181014

gcc/ChangeLog
gcc/cfglayout.c
gcc/config/i386/i386.c
gcc/config/rs6000/rs6000.c
gcc/dwarf2out.c
gcc/final.c
gcc/gengtype.c
gcc/insn-notes.def
gcc/print-rtl.c
gcc/tree-cfg.c
gcc/var-tracking.c

index 9765e3ce154396848241abfc440b20338b846b3e..25eb1ce4bb12a5e27f81e99728b0ddd64a817d9e 100644 (file)
@@ -1,3 +1,28 @@
+2011-11-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/50693
+       * tree-cfg.c (gimple_can_merge_blocks_p): Allow merging with
+       non-forced user labels.
+       (gimple_merge_blocks): Turn non-forced user labels into
+       debug bind stmt with the label as first operand and reset value.
+       (gimple_duplicate_bb): Don't duplicate label debug stmts.
+       * dwarf2out.c (gen_label_die): Handle NOTE_INSN_DELETED_DEBUG_LABEL.
+       * final.c (final_scan_insn): Likewise.
+       (rest_of_clean_state): Don't dump NOTE_INSN_DELETED_DEBUG_LABEL.
+       * var-tracking.c (debug_label_num): New variable.
+       (delete_debug_insns): Don't delete DEBUG_INSNs for LABEL_DECLs,
+       instead turn them into NOTE_INSN_DELETED_DEBUG_LABEL notes.
+       * cfglayout.c (skip_insns_after_block, duplicate_insn_chain): Handle
+       NOTE_INSN_DELETED_DEBUG_LABEL.
+       (duplicate_insn_chain): Don't duplicate LABEL_DECL DEBUG_INSNs.
+       * insn-notes.def (DELETED_DEBUG_LABEL): New note kind.
+       * print-rtl.c (print_rtx): Handle NOTE_INSN_DELETED_DEBUG_LABEL.
+       * gengtype.c (adjust_field_rtx_def): Likewise.
+       * config/i386/i386.c (ix86_output_function_epilogue): For MachO
+       clear CODE_LABEL_NUMBER of NOTE_INSN_DELETED_DEBUG_LABEL
+       if their are at the end of function and nop hasn't been emitted.
+       * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Likewise.
+
 2011-11-05  Georg-Johann Lay  <avr@gjlay.de>
 
        PR rtl-optimization/50448
index 62ac6bfe151e71e6d4bda8129579d8167927b625..22d3d87e68b7d264bdf134f7f438dfd63d766469 100644 (file)
@@ -149,6 +149,7 @@ skip_insns_after_block (basic_block bb)
            break;
          case NOTE_INSN_DELETED:
          case NOTE_INSN_DELETED_LABEL:
+         case NOTE_INSN_DELETED_DEBUG_LABEL:
            continue;
          default:
            reorder_insns (insn, insn, last_insn);
@@ -1174,6 +1175,10 @@ duplicate_insn_chain (rtx from, rtx to)
       switch (GET_CODE (insn))
        {
        case DEBUG_INSN:
+         /* Don't duplicate label debug insns.  */
+         if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
+           break;
+         /* FALLTHRU */
        case INSN:
        case CALL_INSN:
        case JUMP_INSN:
@@ -1219,6 +1224,7 @@ duplicate_insn_chain (rtx from, rtx to)
 
            case NOTE_INSN_DELETED:
            case NOTE_INSN_DELETED_LABEL:
+           case NOTE_INSN_DELETED_DEBUG_LABEL:
              /* No problem to strip these.  */
            case NOTE_INSN_FUNCTION_BEG:
              /* There is always just single entry to function.  */
index fb0ac8de0b092e99124c0852bedf2618a98b9487..ca62b229089a70ef61b41f195a495dd6717394e1 100644 (file)
@@ -10879,15 +10879,28 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
      it looks like we might want one, insert a NOP.  */
   {
     rtx insn = get_last_insn ();
+    rtx deleted_debug_label = NULL_RTX;
     while (insn
           && NOTE_P (insn)
           && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
-      insn = PREV_INSN (insn);
+      {
+       /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
+          notes only, instead set their CODE_LABEL_NUMBER to -1,
+          otherwise there would be code generation differences
+          in between -g and -g0.  */
+       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+         deleted_debug_label = insn;
+       insn = PREV_INSN (insn);
+      }
     if (insn
        && (LABEL_P (insn)
            || (NOTE_P (insn)
                && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)))
       fputs ("\tnop\n", file);
+    else if (deleted_debug_label)
+      for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
+       if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+         CODE_LABEL_NUMBER (insn) = -1;
   }
 #endif
 
index 86fe85906e6d075277db41c2398bc66a3cd60079..779086a30b18695a02bd9d5b2779f56a2aea8ffd 100644 (file)
@@ -21461,15 +21461,28 @@ rs6000_output_function_epilogue (FILE *file,
      it looks like we might want one, insert a NOP.  */
   {
     rtx insn = get_last_insn ();
+    rtx deleted_debug_label = NULL_RTX;
     while (insn
           && NOTE_P (insn)
           && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
-      insn = PREV_INSN (insn);
+      {
+       /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
+          notes only, instead set their CODE_LABEL_NUMBER to -1,
+          otherwise there would be code generation differences
+          in between -g and -g0.  */
+       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+         deleted_debug_label = insn;
+       insn = PREV_INSN (insn);
+      }
     if (insn
        && (LABEL_P (insn)
            || (NOTE_P (insn)
                && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)))
       fputs ("\tnop\n", file);
+    else if (deleted_debug_label)
+      for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
+       if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+         CODE_LABEL_NUMBER (insn) = -1;
   }
 #endif
 
index e6f86a49854a1c3825aa5f47e754186ba94a8408..39be9a16e9c36ad359d86a338ae414a3afeed0cb 100644 (file)
@@ -18020,6 +18020,14 @@ gen_label_die (tree decl, dw_die_ref context_die)
          ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
          add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
        }
+      else if (insn
+              && NOTE_P (insn)
+              && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL
+              && CODE_LABEL_NUMBER (insn) != -1)
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label, "LDL", CODE_LABEL_NUMBER (insn));
+         add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
+       }
     }
 }
 
index e6d288639b76910883bf7b829b03f1fe76d81f04..bd4e7a762a73c6e4fe9f7381ed47f28119d9dcec 100644 (file)
@@ -2080,6 +2080,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
          break;
 
+       case NOTE_INSN_DELETED_DEBUG_LABEL:
+         /* Similarly, but need to use different namespace for it.  */
+         if (CODE_LABEL_NUMBER (insn) != -1)
+           ASM_OUTPUT_DEBUG_LABEL (file, "LDL", CODE_LABEL_NUMBER (insn));
+         break;
+
        case NOTE_INSN_VAR_LOCATION:
        case NOTE_INSN_CALL_ARG_LOCATION:
          if (!DECL_IGNORED_P (current_function_decl))
@@ -4369,7 +4375,8 @@ rest_of_clean_state (void)
              (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
               && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION
               && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG
-              && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END)))
+              && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END
+              && NOTE_KIND (insn) != NOTE_INSN_DELETED_DEBUG_LABEL)))
        print_rtl_single (final_output, insn);
     }
 
index 6063d81daa56e70e1b0f1919efd129dd8067de56..c9c08a4db315f383d640540cf44672f00a557105 100644 (file)
@@ -1015,6 +1015,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
          {
          case NOTE_INSN_MAX:
          case NOTE_INSN_DELETED_LABEL:
+         case NOTE_INSN_DELETED_DEBUG_LABEL:
            note_flds = create_field (note_flds, &string_type, "rt_str");
            break;
 
index 2ea673f05e643e4a06ec9ec01193142d8bdc5f75..c1d621a1d166de8867a576b11ce57494336256f5 100644 (file)
@@ -36,6 +36,10 @@ INSN_NOTE (DELETED)
 
 /* Generated in place of user-declared labels when they are deleted.  */
 INSN_NOTE (DELETED_LABEL)
+/* Similarly, but for labels that have been present in debug stmts
+   earlier and thus will only appear with -g.  These must use different
+   label namespace.  */
+INSN_NOTE (DELETED_DEBUG_LABEL)
 
 /* These are used to mark the beginning and end of a lexical block.
    See NOTE_BLOCK and reorder_blocks.  */
index edeeefa6071c6f9ecd61c1c87deb40e37353120a..9bd8621c4edd6f0bfda0c4559e45c8214ef4689c 100644 (file)
@@ -283,6 +283,7 @@ print_rtx (const_rtx in_rtx)
                }
 
              case NOTE_INSN_DELETED_LABEL:
+             case NOTE_INSN_DELETED_DEBUG_LABEL:
                {
                  const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
                  if (label)
@@ -442,7 +443,8 @@ print_rtx (const_rtx in_rtx)
          {
            /* This field is only used for NOTE_INSN_DELETED_LABEL, and
               other times often contains garbage from INSN->NOTE death.  */
-           if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL)
+           if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL
+               || NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL)
              fprintf (outfile, " %d",  XINT (in_rtx, i));
          }
 #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
index 2819e7b2fc6ecbb45040d2a8d079cf43ec63dd81..28aea2f69332b99840c0e28b490a650b91eff23c 100644 (file)
@@ -1454,8 +1454,8 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
        break;
       lab = gimple_label_label (stmt);
 
-      /* Do not remove user labels.  */
-      if (!DECL_ARTIFICIAL (lab))
+      /* Do not remove user forced labels.  */
+      if (!DECL_ARTIFICIAL (lab) && FORCED_LABEL (lab))
        return false;
     }
 
@@ -1701,6 +1701,15 @@ gimple_merge_blocks (basic_block a, basic_block b)
              gimple_stmt_iterator dest_gsi = gsi_start_bb (a);
              gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
            }
+         /* Other user labels keep around in a form of a debug stmt.  */
+         else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_STMTS)
+           {
+             gimple dbg = gimple_build_debug_bind (label,
+                                                   integer_zero_node,
+                                                   stmt);
+             gimple_debug_bind_reset_value (dbg);
+             gsi_insert_before (&gsi, dbg, GSI_SAME_STMT);
+           }
 
          lp_nr = EH_LANDING_PAD_NR (label);
          if (lp_nr)
@@ -5207,6 +5216,12 @@ gimple_duplicate_bb (basic_block bb)
       if (gimple_code (stmt) == GIMPLE_LABEL)
        continue;
 
+      /* Don't duplicate label debug stmts.  */
+      if (gimple_debug_bind_p (stmt)
+         && TREE_CODE (gimple_debug_bind_get_var (stmt))
+            == LABEL_DECL)
+       continue;
+
       /* Create a new copy of STMT and duplicate STMT's virtual
         operands.  */
       copy = gimple_copy (stmt);
index 11d4efdcdc25db027f9c92eebb1b9d872afab780..95bc02b183c6bd819f92f664190326ede1f353a4 100644 (file)
@@ -9517,6 +9517,12 @@ vt_initialize (void)
   return true;
 }
 
+/* This is *not* reset after each function.  It gives each
+   NOTE_INSN_DELETED_DEBUG_LABEL in the entire compilation
+   a unique label number.  */
+
+static int debug_label_num = 1;
+
 /* Get rid of all debug insns from the insn stream.  */
 
 static void
@@ -9532,7 +9538,22 @@ delete_debug_insns (void)
     {
       FOR_BB_INSNS_SAFE (bb, insn, next)
        if (DEBUG_INSN_P (insn))
-         delete_insn (insn);
+         {
+           tree decl = INSN_VAR_LOCATION_DECL (insn);
+           if (TREE_CODE (decl) == LABEL_DECL
+               && DECL_NAME (decl)
+               && !DECL_RTL_SET_P (decl))
+             {
+               PUT_CODE (insn, NOTE);
+               NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL;
+               NOTE_DELETED_LABEL_NAME (insn)
+                 = IDENTIFIER_POINTER (DECL_NAME (decl));
+               SET_DECL_RTL (decl, insn);
+               CODE_LABEL_NUMBER (insn) = debug_label_num++;
+             }
+           else
+             delete_insn (insn);
+         }
     }
 }