]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
basic-block.h (find_sub_basic_blocks): Use sbitmap parameter.
authorJan Hubicka <jh@suse.cz>
Sat, 20 Oct 2001 10:04:00 +0000 (12:04 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 20 Oct 2001 10:04:00 +0000 (10:04 +0000)
* basic-block.h (find_sub_basic_blocks): Use sbitmap parameter.
* cfgbuild.c (find_bb_boundaries, compute_outgoing_frequencies):
Break out from ...
(find_sub_basic_blocks): ... here;
(find_many_sub_basic_blocks): New.
* recog.c (split_all_insns): Update find_sub_basic_blocks call.

* i386.h (ASM_PREFERRED_EH_DATA_FORMAT): Define sdata4.

* i386.c (ix86_va_arg): Kill indirect_p handling; fix aliasing issues.:

* i386.c (split_di, split_ti): Revamp to use simplify_subreg.

* timevar.def (TV_LIFE, TV_LIFE_UPDATE, TV_MODE_SWITCH): new.
* flow.c (update_life_info): Measure time.
* c-decl.c: Include timevar.h
(c_expand_body): Measure time.
* toplev.c (rest_of_compilation): Measure time of mode switching
separately.
* Makefile.in (c-decl.o, cfgcleanup.o): Add dependancy.

* toplev.c (flag_asynchronous_unwind_tables): New global variable.
(lang_independent_options): Add asynchronous-unwind-tables
(toplev_main): flag_asynchronous_unwind_tables implies
flag_unwind_tables.
* flags.h (flag_asynchronous_unwind_tables): Declare.
* dwarf2out.c (dwarf2out_stack_adjust): Take into account
flag_asynchronous_unwind_tables.
(output_call_frame_info): Likewise.
* invoke.texi (-fasynchronous-unwind-tables): Document.
* i386.c (optimization_options): Enable
flag_asynchronous_unwind_tables.

* i386.c (ix86_expand_setcc):  Always expect target to be QImode.
* i386.md (s* expanders): Destination is QImode.

* toplev.c (rest_of_compilation): Do not call clear_log_links.
* rtl.h (clear_log_links): Kill.
* flow.c (clear_log_links): Make static; accept blocks parameter;
do no clear life info.
(update_life_info): Call clear_log_links.

* cfganal.c (forwarder_block_p): Avoid active_insn_p calls.

From-SVN: r46374

17 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/basic-block.h
gcc/c-decl.c
gcc/cfganal.c
gcc/cfgbuild.c
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/doc/invoke.texi
gcc/dwarf2out.c
gcc/flags.h
gcc/flow.c
gcc/recog.c
gcc/rtl.h
gcc/timevar.def
gcc/toplev.c

index 834268dd8fc6987ce367809ad74dff46cb76c259..8b6793b214687e26cf6df341e49869d8b9632159 100644 (file)
@@ -1,3 +1,49 @@
+Sat Oct 20 12:01:07 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * basic-block.h (find_sub_basic_blocks): Use sbitmap parameter.
+       * cfgbuild.c (find_bb_boundaries, compute_outgoing_frequencies):
+       Break out from ...
+       (find_sub_basic_blocks): ... here;
+       (find_many_sub_basic_blocks): New.
+       * recog.c (split_all_insns): Update find_sub_basic_blocks call.
+
+       * i386.h (ASM_PREFERRED_EH_DATA_FORMAT): Define sdata4.
+
+       * i386.c (ix86_va_arg): Kill indirect_p handling; fix aliasing issues.:
+
+       * i386.c (split_di, split_ti): Revamp to use simplify_subreg.
+
+       * timevar.def (TV_LIFE, TV_LIFE_UPDATE, TV_MODE_SWITCH): new.
+       * flow.c (update_life_info): Measure time.
+       * c-decl.c: Include timevar.h
+       (c_expand_body): Measure time.
+       * toplev.c (rest_of_compilation): Measure time of mode switching
+       separately.
+       * Makefile.in (c-decl.o, cfgcleanup.o): Add dependancy.
+
+       * toplev.c (flag_asynchronous_unwind_tables): New global variable.
+       (lang_independent_options): Add asynchronous-unwind-tables
+       (toplev_main): flag_asynchronous_unwind_tables implies
+       flag_unwind_tables.
+       * flags.h (flag_asynchronous_unwind_tables): Declare.
+       * dwarf2out.c (dwarf2out_stack_adjust): Take into account
+       flag_asynchronous_unwind_tables.
+       (output_call_frame_info): Likewise.
+       * invoke.texi (-fasynchronous-unwind-tables): Document.
+       * i386.c (optimization_options): Enable
+       flag_asynchronous_unwind_tables.
+
+       * i386.c (ix86_expand_setcc):  Always expect target to be QImode.
+       * i386.md (s* expanders): Destination is QImode.
+
+       * toplev.c (rest_of_compilation): Do not call clear_log_links.
+       * rtl.h (clear_log_links): Kill.
+       * flow.c (clear_log_links): Make static; accept blocks parameter;
+       do no clear life info.
+       (update_life_info): Call clear_log_links.
+
+       * cfganal.c (forwarder_block_p): Avoid active_insn_p calls.
+
 2001-10-20  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * cpplex.c (handle_newline, skip_escaped_newlines,
index c9309727512f610df83ff6f3554e55776bf26a80..00577e1b7f75f7bf755eed0133b9c1b079c22de7 100644 (file)
@@ -1168,7 +1168,7 @@ $(srcdir)/c-parse.y: c-parse.in
 
 c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \
     $(GGC_H) $(TARGET_H) c-lex.h flags.h function.h output.h $(EXPR_H) \
-    debug.h toplev.h intl.h $(TM_P_H) tree-inline.h
+    debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H)
 c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
     $(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
 c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
@@ -1512,7 +1512,7 @@ cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
 cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
    $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
    function.h except.h $(GGC_H) 
-cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
+cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TIMEVAR_H)\
    $(BASIC_BLOCK_H) hard-reg-set.h output.h flags.h $(RECOG_H) toplev.h $(GGC_H)
 cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
    $(BASIC_BLOCK_H) hard-reg-set.h
index c56ea772c6e95b00bec829a188dddccad6cebb5f..1a0cab66f705e33a61a18486cf7bc2995c83e6a1 100644 (file)
@@ -640,6 +640,7 @@ extern bool forwarder_block_p               PARAMS ((basic_block));
 extern bool purge_all_dead_edges       PARAMS ((void));
 extern bool purge_dead_edges           PARAMS ((basic_block));
 extern void find_sub_basic_blocks      PARAMS ((basic_block));
+extern void find_many_sub_basic_blocks PARAMS ((sbitmap));
 extern bool can_fallthru               PARAMS ((basic_block, basic_block));
 extern void flow_nodes_print           PARAMS ((const char *, const sbitmap,
                                                 FILE *));
index de553b185440a1f2a49a77fdb412500235aff840..45b923aae637ba9286f94668a0dfee62e22108c4 100644 (file)
@@ -44,6 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cpplib.h"
 #include "target.h"
 #include "debug.h"
+#include "timevar.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -6802,6 +6803,8 @@ c_expand_body (fndecl, nested_p)
   if (flag_syntax_only)
     return;
 
+  timevar_push (TV_EXPAND);
+
   if (flag_inline_trees)
     {
       /* First, cache whether the current function is inlinable.  Some
@@ -6952,6 +6955,7 @@ c_expand_body (fndecl, nested_p)
   if (nested_p)
     /* Return to the enclosing function.  */
     pop_function_context ();
+  timevar_pop (TV_EXPAND);
 }
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
index 5ad1a10a9bb67701a894faecec849ae99e36b0d9..8615a14755ee0cc9abbbadde87eac0033e9dfeb0 100644 (file)
@@ -67,12 +67,13 @@ forwarder_block_p (bb)
 
   while (insn != bb->end)
     {
-      if (active_insn_p (insn))
+      if (INSN_P (insn) && active_insn_p (insn))
        return false;
       insn = NEXT_INSN (insn);
     }
-  return (!active_insn_p (insn)
-         || (GET_CODE (insn) == JUMP_INSN && onlyjump_p (insn)));
+  return (!INSN_P (insn)
+         || (GET_CODE (insn) == JUMP_INSN && simplejump_p (insn))
+         || !active_insn_p (insn));
 }
 
 /* Return nonzero if we can reach target from src by falling trought.  */
index b27c23966edb79de6b394d78945a84560acfcda9..ef86939d4ad5f399620fbfe99d4c39194489c2b7 100644 (file)
@@ -55,6 +55,8 @@ static void make_edges                        PARAMS ((rtx, int, int, int));
 static void make_label_edge            PARAMS ((sbitmap *, basic_block,
                                                 rtx, int));
 static void make_eh_edge               PARAMS ((sbitmap *, basic_block, rtx));
+static void find_bb_boundaries         PARAMS ((basic_block));
+static void compute_outgoing_frequencies PARAMS ((basic_block));
 
 /* Count the basic blocks of the function.  */
 
@@ -246,7 +248,8 @@ make_edges (label_value_list, min, max, update_p)
     }
 
   /* By nature of the way these get numbered, block 0 is always the entry.  */
-  cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
+  if (min == 0)
+    cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
 
   for (i = min; i <= max; ++i)
     {
@@ -663,18 +666,27 @@ find_basic_blocks (f, nregs, file)
   timevar_pop (TV_CFG);
 }
 \f
-/* Assume that someone emitted code with control flow instructions to the
-   basic block.  Update the data structure.  */
-void
-find_sub_basic_blocks (bb)
+/* State of basic block as seen by find_sub_basic_blocks.  */
+enum state
+  {
+    BLOCK_NEW = 0,
+    BLOCK_ORIGINAL,
+    BLOCK_TO_SPLIT
+  };
+#define STATE(bb) (enum state)(size_t)(bb)->aux
+#define SET_STATE(bb, state) (bb)->aux = (void *)(state)
+
+/* Scan basic block BB for possible BB boundaries inside the block
+   and create new basic blocks in the progress.  */
+
+static void
+find_bb_boundaries (bb)
      basic_block bb;
 {
   rtx insn = bb->head;
   rtx end = bb->end;
   rtx flow_transfer_insn = NULL_RTX;
   edge fallthru = NULL;
-  basic_block first_bb = bb;
-  int i;
 
   if (insn == bb->end)
     return;
@@ -694,7 +706,7 @@ find_sub_basic_blocks (bb)
            abort ();
          break;
 
-       /* On code label, split current basic block.  */
+         /* On code label, split current basic block.  */
        case CODE_LABEL:
          fallthru = split_block (bb, PREV_INSN (insn));
          if (flow_transfer_insn)
@@ -725,7 +737,7 @@ find_sub_basic_blocks (bb)
            {
              if (GET_CODE (PATTERN (insn)) == ADDR_VEC
                  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
-               abort();
+               abort ();
              flow_transfer_insn = insn;
            }
          else if (code == CALL_INSN)
@@ -764,18 +776,87 @@ find_sub_basic_blocks (bb)
      followed by cleanup at fallthru edge, so the outgoing edges may
      be dead.  */
   purge_dead_edges (bb);
+}
+
+/*  Assume that frequency of basic block B is known.  Compute frequencies
+    and probabilities of outgoing edges.  */
+
+static void
+compute_outgoing_frequencies (b)
+     basic_block b;
+{
+  edge e, f;
+  if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
+    {
+      rtx note = find_reg_note (b->end, REG_BR_PROB, NULL);
+      int probability;
+
+      if (!note)
+       return;
+      probability = INTVAL (XEXP (find_reg_note (b->end,
+                                                REG_BR_PROB, NULL), 0));
+      e = BRANCH_EDGE (b);
+      e->probability = probability;
+      e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
+                 / REG_BR_PROB_BASE);
+      f = FALLTHRU_EDGE (b);
+      f->probability = REG_BR_PROB_BASE - probability;
+      f->count = b->count - e->count;
+    }
+  if (b->succ && !b->succ->succ_next)
+    {
+      e = b->succ;
+      e->probability = REG_BR_PROB_BASE;
+      e->count = b->count;
+    }
+}
+
+/* Assume that someone emitted code with control flow instructions to the
+   basic block.  Update the data structure.  */
+
+void
+find_many_sub_basic_blocks (blocks)
+     sbitmap blocks;
+{
+  int i;
+  int min, max;
+
+  for (i = 0; i < n_basic_blocks; i++)
+    {
+      SET_STATE (BASIC_BLOCK (i),
+                TEST_BIT (blocks, i)
+                ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
+    }
+
+  for (i = 0; i < n_basic_blocks; i++)
+    {
+      basic_block bb = BASIC_BLOCK (i);
+      if (STATE (bb) == BLOCK_TO_SPLIT)
+       find_bb_boundaries (bb);
+    }
+
+  for (i = 0; i < n_basic_blocks; i++)
+    if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
+      break;
+  min = max = i;
+  for (; i < n_basic_blocks; i++)
+    if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
+      max = i;
 
   /* Now re-scan and wire in all edges.  This expect simple (conditional)
      jumps at the end of each new basic blocks.  */
-  make_edges (NULL, first_bb->index, bb->index, 1);
+  make_edges (NULL, min, max, 1);
 
   /* Update branch probabilities.  Expect only (un)conditional jumps
      to be created with only the forward edges.  */
-  for (i = first_bb->index; i <= bb->index; i++)
+  for (i = min; i <= max; i++)
     {
-      edge e,f;
+      edge e;
       basic_block b = BASIC_BLOCK (i);
-      if (b != first_bb)
+
+      if (STATE (b) == BLOCK_ORIGINAL)
+       continue;
+      if (STATE (b) == BLOCK_NEW)
        {
          b->count = 0;
          b->frequency = 0;
@@ -785,29 +866,48 @@ find_sub_basic_blocks (bb)
              b->frequency += EDGE_FREQUENCY (e);
            }
        }
-      if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
-       {
-         rtx note = find_reg_note (b->end, REG_BR_PROB, NULL);
-         int probability;
-
-         if (!note)
-           continue;
-         probability = INTVAL (XEXP (find_reg_note (b->end,
-                                                    REG_BR_PROB,
-                                                    NULL), 0));
-         e = BRANCH_EDGE (b);
-         e->probability = probability;
-         e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
-                     / REG_BR_PROB_BASE);
-         f = FALLTHRU_EDGE (b);
-         f->probability = REG_BR_PROB_BASE - probability;
-         f->count = b->count - e->count;
-       }
-      if (b->succ && !b->succ->succ_next)
+      compute_outgoing_frequencies (b);
+    }
+  for (i = 0; i < n_basic_blocks; i++)
+    SET_STATE (BASIC_BLOCK (i), 0);
+}
+
+/* Like above but for single basic block only.  */
+
+void
+find_sub_basic_blocks (bb)
+    basic_block bb;
+{
+  int i;
+  int min, max;
+  basic_block next = (bb->index == n_basic_blocks - 1
+                     ? NULL : BASIC_BLOCK (bb->index + 1));
+
+  min = bb->index;
+  find_bb_boundaries (bb);
+  max = (next ? next->index : n_basic_blocks) - 1;
+
+  /* Now re-scan and wire in all edges.  This expect simple (conditional)
+     jumps at the end of each new basic blocks.  */
+  make_edges (NULL, min, max, 1);
+
+  /* Update branch probabilities.  Expect only (un)conditional jumps
+     to be created with only the forward edges.  */
+  for (i = min; i <= max; i++)
+    {
+      edge e;
+      basic_block b = BASIC_BLOCK (i);
+
+      if (i != min)
        {
-         e = b->succ;
-         e->probability = REG_BR_PROB_BASE;
-         e->count = b->count;
+         b->count = 0;
+         b->frequency = 0;
+         for (e = b->pred; e; e=e->pred_next)
+           {
+             b->count += e->count;
+             b->frequency += EDGE_FREQUENCY (e);
+           }
        }
+      compute_outgoing_frequencies (b);
     }
 }
index 6be389cc9203b6d48e2c18be061e50da04a8015e..b9f1470d3e1686d2c751a078a3333f5368dbb3a9 100644 (file)
@@ -1061,7 +1061,10 @@ optimization_options (level, size)
   if (TARGET_64BIT && optimize >= 1)
     flag_omit_frame_pointer = 1;
   if (TARGET_64BIT)
-    flag_pcc_struct_return = 0;
+    {
+      flag_pcc_struct_return = 0;
+      flag_asynchronous_unwind_tables = 1;
+    }
 }
 \f
 /* Table of valid machine attributes.  */
@@ -2331,7 +2334,7 @@ ix86_va_arg (valist, type)
   static int intreg[6] = { 0, 1, 2, 3, 4, 5 };
   tree f_gpr, f_fpr, f_ovf, f_sav;
   tree gpr, fpr, ovf, sav, t;
-  int indirect_p = 0, size, rsize;
+  int size, rsize;
   rtx lab_false, lab_over = NULL_RTX;
   rtx addr_rtx, r;
   rtx container;
@@ -2459,9 +2462,11 @@ ix86_va_arg (valist, type)
          int i;
          rtx mem;
 
-         mem = assign_temp (type, 0, 1, 0);
+         /* Never use the memory itself, as it has the alias set.  */
+         addr_rtx = XEXP (assign_temp (type, 0, 1, 0), 0);
+         mem = gen_rtx_MEM (BLKmode, addr_rtx);
          set_mem_alias_set (mem, get_varargs_alias_set ());
-         addr_rtx = XEXP (mem, 0);
+
          for (i = 0; i < XVECLEN (container, 0); i++)
            {
              rtx slot = XVECEXP (container, 0, i);
@@ -2487,7 +2492,6 @@ ix86_va_arg (valist, type)
              src_mem = adjust_address (src_mem, mode, src_offset);
              dest_mem = adjust_address (mem, mode, INTVAL (XEXP (slot, 1)));
              PUT_MODE (dest_mem, mode);
-             /* ??? Break out TImode moves from integer registers?  */
              emit_move_insn (dest_mem, src_mem);
            }
        }
@@ -2543,14 +2547,6 @@ ix86_va_arg (valist, type)
   if (container)
     emit_label (lab_over);
 
-  if (indirect_p)
-    {
-      abort ();
-      r = gen_rtx_MEM (Pmode, addr_rtx);
-      set_mem_alias_set (r, get_varargs_alias_set ());
-      emit_move_insn (addr_rtx, r);
-    }
-
   return addr_rtx;
 }
 \f
@@ -5931,27 +5927,19 @@ split_di (operands, num, lo_half, hi_half)
   while (num--)
     {
       rtx op = operands[num];
-      if (CONSTANT_P (op))
-       split_double (op, &lo_half[num], &hi_half[num]);
-      else if (! reload_completed)
-       {
-         lo_half[num] = gen_lowpart (SImode, op);
-         hi_half[num] = gen_highpart (SImode, op);
-       }
-      else if (GET_CODE (op) == REG)
-       {
-         if (TARGET_64BIT)
-           abort();
-         lo_half[num] = gen_rtx_REG (SImode, REGNO (op));
-         hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1);
-       }
-      else if (offsettable_memref_p (op))
+
+      /* simplify_subreg refuse to split volatile memory addresses,
+         but we still have to handle it.  */
+      if (GET_CODE (op) == MEM)
        {
          lo_half[num] = adjust_address (op, SImode, 0);
          hi_half[num] = adjust_address (op, SImode, 4);
        }
       else
-       abort ();
+       {
+         lo_half[num] = simplify_gen_subreg (SImode, op, DImode, 0);
+         hi_half[num] = simplify_gen_subreg (SImode, op, DImode, 4);
+       }
     }
 }
 /* Split one or more TImode RTL references into pairs of SImode
@@ -5969,40 +5957,19 @@ split_ti (operands, num, lo_half, hi_half)
   while (num--)
     {
       rtx op = operands[num];
-      if (CONSTANT_P (op))
-       {
-         if (GET_CODE (op) == CONST_INT)
-           {
-             lo_half[num] = GEN_INT (trunc_int_for_mode (INTVAL (op), SImode));
-             hi_half[num] = (1 << (HOST_BITS_PER_WIDE_INT -1)) != 0 ? constm1_rtx : const0_rtx;
-           }
-         else if (GET_CODE (op) == CONST_DOUBLE && HOST_BITS_PER_WIDE_INT == 64)
-           {
-             lo_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (op), SImode));
-             hi_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_HIGH (op), SImode));
-           }
-         else
-           abort ();
-       }
-      else if (! reload_completed)
-       {
-         lo_half[num] = gen_lowpart (DImode, op);
-         hi_half[num] = gen_highpart (DImode, op);
-       }
-      else if (GET_CODE (op) == REG)
-       {
-         if (TARGET_64BIT)
-           abort();
-         lo_half[num] = gen_rtx_REG (DImode, REGNO (op));
-         hi_half[num] = gen_rtx_REG (DImode, REGNO (op) + 1);
-       }
-      else if (offsettable_memref_p (op))
+
+      /* simplify_subreg refuse to split volatile memory addresses, but we
+         still have to handle it.  */
+      if (GET_CODE (op) == MEM)
        {
          lo_half[num] = adjust_address (op, DImode, 0);
          hi_half[num] = adjust_address (op, DImode, 8);
        }
       else
-       abort ();
+       {
+         lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0);
+         hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8);
+       }
     }
 }
 \f
@@ -7860,54 +7827,19 @@ ix86_expand_setcc (code, dest)
 {
   rtx ret, tmp, tmpreg;
   rtx second_test, bypass_test;
-  int type;
 
   if (GET_MODE (ix86_compare_op0) == DImode
       && !TARGET_64BIT)
     return 0; /* FAIL */
 
-  /* Three modes of generation:
-     0 -- destination does not overlap compare sources:
-          clear dest first, emit strict_low_part setcc.
-     1 -- destination does overlap compare sources:
-          emit subreg setcc, zero extend.
-     2 -- destination is in QImode:
-          emit setcc only.
-
-     We don't use mode 0 early in compilation because it confuses CSE.
-     There are peepholes to turn mode 1 into mode 0 if things work out
-     nicely after reload.  */
-
-  type = cse_not_expected ? 0 : 1;
-
-  if (GET_MODE (dest) == QImode)
-    type = 2;
-  else if (reg_overlap_mentioned_p (dest, ix86_compare_op0)
-          || reg_overlap_mentioned_p (dest, ix86_compare_op1))
-    type = 1;
-
-  if (type == 0)
-    emit_move_insn (dest, const0_rtx);
+  if (GET_MODE (dest) != QImode)
+    abort ();
 
   ret = ix86_expand_compare (code, &second_test, &bypass_test);
   PUT_MODE (ret, QImode);
 
   tmp = dest;
   tmpreg = dest;
-  if (type == 0)
-    {
-      tmp = gen_lowpart (QImode, dest);
-      tmpreg = tmp;
-      tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp);
-    }
-  else if (type == 1)
-    {
-      if (!cse_not_expected)
-       tmp = gen_reg_rtx (QImode);
-      else
-        tmp = gen_lowpart (QImode, dest);
-      tmpreg = tmp;
-    }
 
   emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
   if (bypass_test || second_test)
@@ -7932,17 +7864,6 @@ ix86_expand_setcc (code, dest)
        emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
     }
 
-  if (type == 1)
-    {
-      rtx clob;
-
-      tmp = gen_rtx_ZERO_EXTEND (GET_MODE (dest), tmp);
-      tmp = gen_rtx_SET (VOIDmode, dest, tmp);
-      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
-      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
-      emit_insn (tmp);
-    }
-
   return 1; /* DONE */
 }
 
index 49c1b27132d273f0e97203d0892887b3a2e10021..da093be4e4906724710f59fe4250c2859dbd1763 100644 (file)
@@ -2885,7 +2885,8 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
    Whether or not a particular assembler allows us to enter such, I
    guess we'll have to see.  */
 #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL)                      \
-  (flag_pic ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel                \
+  (flag_pic                                                            \
+    ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4\
    : DW_EH_PE_absptr)
 
 /* This is how to output the definition of a user-level label named NAME,
index e12c4bd2bc913de3cc8a8e3403fdaf299009339f..efede44cda1af5d5f05ea7537202b7f66e8c89d3 100644 (file)
 ;; way, which can later delete the movzx if only QImode is needed.
 
 (define_expand "seq"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (eq:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (eq:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
 
 (define_expand "sne"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (ne:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (ne:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sgt"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (gt:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (gt:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
 
 (define_expand "sgtu"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (gtu:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (gtu:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
 
 (define_expand "slt"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (lt:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (lt:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
 
 (define_expand "sltu"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (ltu:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (ltu:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
 
 (define_expand "sge"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (ge:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (ge:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sgeu"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (geu:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (geu:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
 
 (define_expand "sle"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (le:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (le:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sleu"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (leu:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (leu:QI (reg:CC 17) (const_int 0)))]
   ""
   "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
 
 (define_expand "sunordered"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (unordered:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (unordered:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
 
 (define_expand "sordered"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (ordered:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (ordered:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387"
   "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
 
 (define_expand "suneq"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (uneq:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (uneq:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
 
 (define_expand "sunge"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (unge:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (unge:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sungt"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (ungt:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (ungt:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
 
 (define_expand "sunle"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (unle:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (unle:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sunlt"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (unlt:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (unlt:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
 
 (define_expand "sltgt"
-  [(set (match_operand:SI 0 "register_operand" "")
-        (ltgt:SI (reg:CC 17) (const_int 0)))]
+  [(set (match_operand:QI 0 "register_operand" "")
+        (ltgt:QI (reg:CC 17) (const_int 0)))]
   "TARGET_80387 || TARGET_SSE"
   "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
 
index 89ee913006bd0c3383e0c1d90f40d98d0a8fb714..d8887d84eca05f74c0b8f3321a3f5b15c267c3c4 100644 (file)
@@ -602,7 +602,7 @@ in the following sections.
 @gccoptlist{
 -fcall-saved-@var{reg}  -fcall-used-@var{reg} @gol
 -ffixed-@var{reg} -fexceptions @gol
--fnon-call-exceptions  -funwind-tables @gol
+-fnon-call-exceptions  -funwind-tables -fasynchronous-unwind-tables @gol
 -finhibit-size-directive  -finstrument-functions @gol
 -fcheck-memory-usage  -fprefix-function-name @gol
 -fno-common  -fno-ident  -fno-gnu-linker @gol
@@ -9658,6 +9658,12 @@ static data, but will not affect the generated code in any other way.
 You will normally not enable this option; instead, a language processor
 that needs this handling would enable it on your behalf.
 
+@item -fasynchronous-unwind-tables
+@opindex funwind-tables
+Generate unwind table in dwarf2 format, if supported by target machine.  The
+table is exact at each instruction boundary, so it can be used for stack
+unwinding from asynchronous events (such as debugger or garbage collector).
+
 @item -fpcc-struct-return
 @opindex fpcc-struct-return
 Return ``short'' @code{struct} and @code{union} values in memory like
index 1d245b7ad905b945609bac13f10d58b07fb83d43..486c7a20b27c1fe992939f05047c5b8ff108a82f 100644 (file)
@@ -943,7 +943,8 @@ dwarf2out_stack_adjust (insn)
   long offset;
   const char *label;
 
-  if (! flag_non_call_exceptions && GET_CODE (insn) == CALL_INSN)
+  if (!flag_asynchronous_unwind_tables
+      && GET_CODE (insn) == CALL_INSN)
     {
       /* Extract the size of the args from the CALL rtx itself.  */
 
@@ -960,7 +961,7 @@ dwarf2out_stack_adjust (insn)
 
   /* If only calls can throw, and we have a frame pointer,
      save up adjustments until we see the CALL_INSN.  */
-  else if (! flag_non_call_exceptions
+  else if (!flag_asynchronous_unwind_tables
           && cfa.reg != STACK_POINTER_REGNUM)
     return;
 
@@ -1721,7 +1722,7 @@ output_call_frame_info (for_eh)
      emit any EH unwind information.  */
   if (for_eh)
     {
-      int any_eh_needed = 0;
+      int any_eh_needed = flag_asynchronous_unwind_tables;
       for (i = 0; i < fde_table_in_use; ++i)
        if (fde_table[i].uses_eh_lsda)
          any_eh_needed = any_lsda_needed = 1;
index bf9e2af95ec553d4c5abc12cb8160b6e32609faa..04c3ed93eaa9c5d9648d3b4e73b2533d74bf8125 100644 (file)
@@ -451,6 +451,10 @@ extern int flag_exceptions;
 
 extern int flag_unwind_tables;
 
+/* Nonzero means generate frame unwind info table exact at each insn boundary */
+
+extern int flag_asynchronous_unwind_tables;
+
 /* Nonzero means don't place uninitialized global data in common storage
    by default.  */
 
index 030a23370521a6a1b8ac860906a884a49029dfb6..58bf25724c0dd6dd883327277532811eeb89d97a 100644 (file)
@@ -344,6 +344,7 @@ static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
 static void invalidate_mems_from_set   PARAMS ((struct propagate_block_info *,
                                                 rtx));
 static void delete_dead_jumptables     PARAMS ((void));
+static void clear_log_links            PARAMS ((sbitmap));
 \f
 
 void
@@ -628,12 +629,19 @@ update_life_info (blocks, extent, prop_flags)
 
   tmp = INITIALIZE_REG_SET (tmp_head);
 
+  timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
+               ? TV_LIFE_UPDATE : TV_LIFE);
+
   /* Changes to the CFG are only allowed when
      doing a global update for the entire CFG.  */
   if ((prop_flags & PROP_ALLOW_CFG_CHANGES)
       && (extent == UPDATE_LIFE_LOCAL || blocks))
     abort ();
 
+  /* Clear log links in case we are asked to (re)compute them.  */
+  if (prop_flags & PROP_LOG_LINKS)
+    clear_log_links (blocks);
+
   /* For a global update, we go through the relaxation process again.  */
   if (extent != UPDATE_LIFE_LOCAL)
     {
@@ -727,6 +735,8 @@ update_life_info (blocks, extent, prop_flags)
                                     }
                                 });
     }
+  timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
+              ? TV_LIFE_UPDATE : TV_LIFE);
 }
 
 /* Free the variables allocated by find_basic_blocks.
@@ -4088,31 +4098,33 @@ count_or_remove_death_notes (blocks, kill)
 
   return count;
 }
-/* Clear LOG_LINKS fields of insns in a chain.
-   Also clear the global_live_at_{start,end} fields of the basic block
-   structures.  */
+/* Clear LOG_LINKS fields of insns in a selected blocks or whole chain
+   if blocks is NULL.  */
 
-void
-clear_log_links (insns)
-     rtx insns;
+static void
+clear_log_links (blocks)
+     sbitmap blocks;
 {
-  rtx i;
-  int b;
-
-  for (i = insns; i; i = NEXT_INSN (i))
-    if (INSN_P (i))
-      LOG_LINKS (i) = 0;
+  rtx insn;
+  int i;
 
-  for (b = 0; b < n_basic_blocks; b++)
+  if (!blocks)
     {
-      basic_block bb = BASIC_BLOCK (b);
-
-      bb->global_live_at_start = NULL;
-      bb->global_live_at_end = NULL;
+      rtx insn;
+      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+       if (INSN_P (insn))
+         free_EXPR_LIST_list (&LOG_LINKS (insn));
     }
-
-  ENTRY_BLOCK_PTR->global_live_at_end = NULL;
-  EXIT_BLOCK_PTR->global_live_at_start = NULL;
+  else
+    EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+      {
+       basic_block bb = BASIC_BLOCK (i);
+       rtx insn;
+       for (insn = bb->head; insn != NEXT_INSN (bb->end);
+            insn = NEXT_INSN (insn))
+         if (INSN_P (insn))
+           free_EXPR_LIST_list (&LOG_LINKS (insn));
+      });
 }
 
 /* Given a register bitmap, turn on the bits in a HARD_REG_SET that
index 6c3ecd446db7e91ab1f3079665905b0e6f28ea81..874d56755d2a7418426bc18e64075ccf5c0a82d8 100644 (file)
@@ -2778,8 +2778,7 @@ split_all_insns (upd_life)
 
   if (changed)
     {
-      for (i = 0; i < n_basic_blocks; i++)
-       find_sub_basic_blocks (BASIC_BLOCK (i));
+      find_many_sub_basic_blocks (blocks);
     }
 
   if (changed && upd_life)
index 4c0eb2c4e83995647635436ab1f54fe7d602e372..d6908e99a27caf3db3858c1a4d770cf27884d797 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1481,7 +1481,6 @@ void free_EXPR_LIST_node          PARAMS ((rtx));
 void free_INSN_LIST_node               PARAMS ((rtx));
 rtx alloc_INSN_LIST                    PARAMS ((rtx, rtx));
 rtx alloc_EXPR_LIST                    PARAMS ((int, rtx, rtx));
-void clear_log_links                    PARAMS ((rtx));
 
 /* regclass.c */
 
index 7f62497d7f9ca173eed337e0026ebe63f4b57c0f..353a942bf71dfe9ed2f4843dd1b461614dd575f8 100644 (file)
@@ -43,6 +43,9 @@ DEFTIMEVAR (TV_DUMP                  , "dump files")
 DEFTIMEVAR (TV_CFG                   , "cfg construction")
 /* Time spent by cleaning up CFG.  */
 DEFTIMEVAR (TV_CLEANUP_CFG           , "cfg cleanup")
+/* Time spent by life analysis.  */
+DEFTIMEVAR (TV_LIFE                 , "life analysis")
+DEFTIMEVAR (TV_LIFE_UPDATE          , "life info update")
 /* Timing in various stages of the compiler.  */
 DEFTIMEVAR (TV_CPP                  , "preprocessing")
 DEFTIMEVAR (TV_LEX                  , "lexical analysis")
@@ -60,6 +63,7 @@ DEFTIMEVAR (TV_FLOW                  , "flow analysis")
 DEFTIMEVAR (TV_COMBINE               , "combiner")
 DEFTIMEVAR (TV_IFCVT                , "if-conversion")
 DEFTIMEVAR (TV_REGMOVE               , "regmove")
+DEFTIMEVAR (TV_MODE_SWITCH           , "mode switching")
 DEFTIMEVAR (TV_SCHED                 , "scheduling")
 DEFTIMEVAR (TV_LOCAL_ALLOC           , "local alloc")
 DEFTIMEVAR (TV_GLOBAL_ALLOC          , "global alloc")
index 2df15e7f18c3ca39e263940b9dbbdf2a19ef7ee5..3bc9dac156ba3f628c42ce6243d706bb3d9f4efe 100644 (file)
@@ -737,6 +737,10 @@ int flag_exceptions;
 
 int flag_unwind_tables = 0;
 
+/* Nonzero means generate frame unwind info table exact at each insn boundary */
+
+int flag_asynchronous_unwind_tables = 0;
+
 /* Nonzero means don't place uninitialized global data in common storage
    by default.  */
 
@@ -1096,6 +1100,8 @@ lang_independent_options f_options[] =
    N_("Enable exception handling") },
   {"unwind-tables", &flag_unwind_tables, 1,
    N_("Just generate unwind tables for exception handling") },
+  {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1,
+   N_("Generate unwind tables exact at each instruction boundary") },
   {"non-call-exceptions", &flag_non_call_exceptions, 1,
    N_("Support synchronous non-call exceptions") },
   {"profile-arcs", &profile_arc_flag, 1,
@@ -2933,10 +2939,6 @@ rest_of_compilation (decl)
       convert_from_ssa ();
       /* New registers have been created.  Rescan their usage.  */
       reg_scan (insns, max_reg_num (), 1);
-      /* Life analysis used in SSA adds log_links but these
-        shouldn't be there until the flow stage, so clear
-        them away.  */
-      clear_log_links (insns);
 
       close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
       timevar_pop (TV_FROM_SSA);
@@ -3370,7 +3372,7 @@ rest_of_compilation (decl)
   register_life_up_to_date = 0;
 
 #ifdef OPTIMIZE_MODE_SWITCHING
-  timevar_push (TV_GCSE);
+  timevar_push (TV_MODE_SWITCH);
 
   no_new_pseudos = 0;
   if (optimize_mode_switching (NULL))
@@ -3382,7 +3384,7 @@ rest_of_compilation (decl)
     }
   no_new_pseudos = 1;
 
-  timevar_pop (TV_GCSE);
+  timevar_pop (TV_MODE_SWITCH);
 #endif
 
   timevar_push (TV_SCHED);
@@ -4911,6 +4913,11 @@ toplev_main (argc, argv)
       flag_rerun_cse_after_loop = 1;
     }
 
+  if (flag_non_call_exceptions)
+    flag_asynchronous_unwind_tables = 1;
+  if (flag_asynchronous_unwind_tables)
+    flag_unwind_tables = 1;
+
   /* Warn about options that are not supported on this machine.  */
 #ifndef INSN_SCHEDULING
   if (flag_schedule_insns || flag_schedule_insns_after_reload)