[PATCH 3/4] Define MAX_CODE_ALIGN globally.

2018-07-16 Thread marxin

gcc/ChangeLog:

2018-07-11  Martin Liska  

* align.h (MAX_CODE_ALIGN): New.
(MAX_CODE_ALIGN_VALUE): New.
* common/config/i386/i386-common.c (ix86_handle_option):
(MAX_CODE_ALIGN): Moved to align.h.
* final.c (MAX_CODE_ALIGN): Likewise.
* opts.c (parse_and_check_align_values):
(MAX_CODE_ALIGN): Likewise.
(MAX_CODE_ALIGN_VALUE): Likewise.
---
 gcc/align.h  | 4 
 gcc/common/config/i386/i386-common.c | 3 ---
 gcc/final.c  | 1 -
 gcc/opts.c   | 4 
 4 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/gcc/align.h b/gcc/align.h
index 5a5d6c752a3..9acce47cf9b 100644
--- a/gcc/align.h
+++ b/gcc/align.h
@@ -74,3 +74,7 @@ struct align_flags
 
   align_flags_tuple levels[2];
 };
+
+/* Define maximum supported code alignment.  */
+#define MAX_CODE_ALIGN 16
+#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 277ee55a093..70b3c3f2fc3 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -1318,9 +1318,6 @@ ix86_handle_option (struct gcc_options *opts,
   return true;
 
 
-  /* Comes from final.c -- no real reason to change it.  */
-#define MAX_CODE_ALIGN 16
-
 case OPT_malign_loops_:
   warning_at (loc, 0, "-malign-loops is obsolete, use -falign-loops");
   if (value > MAX_CODE_ALIGN)
diff --git a/gcc/final.c b/gcc/final.c
index 59eb75c3d63..445a3fe938a 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -842,7 +842,6 @@ shorten_branches (rtx_insn *first)
   rtx_insn *insn;
   int max_uid;
   int i;
-#define MAX_CODE_ALIGN 16
   rtx_insn *seq;
   int something_changed = 1;
   char *varying_length;
diff --git a/gcc/opts.c b/gcc/opts.c
index e536607fe79..0625b15b27b 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1805,10 +1805,6 @@ parse_and_check_align_values (const char *flag,
   return false;
 }
 
-  /* Comes from final.c -- no real reason to change it.  */
-#define MAX_CODE_ALIGN 16
-#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
-
   for (unsigned i = 0; i < result_values.length (); i++)
 if (result_values[i] > MAX_CODE_ALIGN_VALUE)
   {


[PATCH 2/4] Fix coding style of ASM_OUTPUT_ALIGN.

2018-07-16 Thread marxin

gcc/ChangeLog:

2018-07-11  Martin Liska  

* config/i386/att.h (ASM_OUTPUT_ALIGN): Fix spacing
in order to fulfil coding style.
* config/i386/cygming.h (ASM_OUTPUT_ALIGN): Likewise.
* config/i386/gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
* config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_PAD): Likewise.
* config/iq2000/iq2000.h (ASM_OUTPUT_ALIGN): Likewise.
* config/pa/pa.h (ASM_OUTPUT_ALIGN): Likewise.
* config/sparc/sol2.h (ASM_OUTPUT_ALIGN_WITH_NOP): Likewise.
* config/sparc/sparc.h (ASM_OUTPUT_ALIGN): Likewise.
* config/visium/visium.h (ASM_OUTPUT_ALIGN): Likewise.
(ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
---
 gcc/config/i386/att.h  | 2 +-
 gcc/config/i386/cygming.h  | 2 +-
 gcc/config/i386/gas.h  | 2 +-
 gcc/config/i386/x86-64.h   | 2 +-
 gcc/config/iq2000/iq2000.h | 2 +-
 gcc/config/pa/pa.h | 2 +-
 gcc/config/sparc/sol2.h| 2 +-
 gcc/config/sparc/sparc.h   | 2 +-
 gcc/config/visium/visium.h | 4 ++--
 9 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/gcc/config/i386/att.h b/gcc/config/i386/att.h
index 8e4bc2e8d94..7dd359b9001 100644
--- a/gcc/config/i386/att.h
+++ b/gcc/config/i386/att.h
@@ -57,7 +57,7 @@ do\
to a multiple of 2**LOG bytes.  */
 
 #define ASM_OUTPUT_ALIGN(FILE,LOG)	\
-if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+if ((LOG) != 0) fprintf ((FILE), "\t.align %d\n", 1 << (LOG))
 
 /* This is how to output an assembler line
that says to advance the location counter by SIZE bytes.  */
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 80a0a37e308..cfe563f47af 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -290,7 +290,7 @@ do {		\
 
 #undef ASM_OUTPUT_ALIGN
 #define ASM_OUTPUT_ALIGN(FILE,LOG)	\
-if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+if ((LOG) != 0) fprintf ((FILE), "\t.align %d\n", 1 << (LOG))
 
 /* Windows uses explicit import from shared libraries.  */
 #define MULTIPLE_SYMBOL_SPACES 1
diff --git a/gcc/config/i386/gas.h b/gcc/config/i386/gas.h
index e149ab1360c..eb30db5d326 100644
--- a/gcc/config/i386/gas.h
+++ b/gcc/config/i386/gas.h
@@ -69,7 +69,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
 #  define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
 if ((LOG) != 0) { \
-  if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1<<(LOG))-1)		\
+  if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1 << (LOG)) - 1)		\
 	fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
   else\
 	fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
diff --git a/gcc/config/i386/x86-64.h b/gcc/config/i386/x86-64.h
index 66bbd5edc59..bc97454d2f6 100644
--- a/gcc/config/i386/x86-64.h
+++ b/gcc/config/i386/x86-64.h
@@ -77,7 +77,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define ASM_OUTPUT_MAX_SKIP_PAD(FILE, LOG, MAX_SKIP)			\
   if ((LOG) != 0)			\
 {	\
-  if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1<<(LOG))-1)		\
+  if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1 << (LOG)) - 1)		\
 fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
   else\
 fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index 87c4114b409..1dff91f6c0f 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -489,7 +489,7 @@ while (0)
 
 #define ASM_OUTPUT_ALIGN(STREAM,LOG)	\
   if ((LOG) != 0)   \
-fprintf (STREAM, "\t.balign %d\n", 1<<(LOG))
+fprintf (STREAM, "\t.balign %d\n", 1 << (LOG))
 
 
 /* Macros Affecting all Debug Formats.  */
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 67b3c714ea8..024e7b831ec 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -1187,7 +1187,7 @@ do {	 \
location counter to a multiple of 2**LOG bytes.  */
 
 #define ASM_OUTPUT_ALIGN(FILE,LOG)	\
-fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
+fprintf (FILE, "\t.align %d\n", (1 << (LOG)))
 
 #define ASM_OUTPUT_SKIP(FILE,SIZE)  \
   fprintf (FILE, "\t.blockz " HOST_WIDE_INT_PRINT_UNSIGNED"\n",		\
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index b84f218c811..1bd4d61b2f3 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -413,7 +413,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
with GNU as. */
 #define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG)   \
   if ((LOG) != 0) \
-fprintf (FILE, "\t.align %d,0x100\n", (1<<(LOG)))
+fprintf (FILE, "\t.align %d,0x100\n", (1 << (LOG)))
 
 /* Use Solaris ELF section syntax with Sun as.  */
 #undef TARGET_ASM_NAMED_SECTION
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 419995431e2..032a91d467a 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1659,7 +1659,7 @@

[PATCH 1/4] Clean up of new format of -falign-FOO.

2018-07-16 Thread marxin

gcc/ChangeLog:

2018-07-11  Martin Liska  

* align.h: New file.
* config/alpha/alpha.c (alpha_align_insns_1): Use align_functions 
directly.
* config/i386/i386.c (ix86_avoid_jump_mispredicts): Use new return type
align_flags of label_to_alignment.
* config/m32r/m32r.h (LOOP_ALIGN): Wrap returned values into align_flags
class.
* config/m68k/m68k.c: Do not use removed align_labels_value and
align_loops_value.
* config/nds32/nds32.h (JUMP_ALIGN): Wrap result into align_flags class.
(LOOP_ALIGN): Likewise.
(LABEL_ALIGN): Likewise.
* config/powerpcspe/powerpcspe.c (TARGET_ASM_LOOP_ALIGN_MAX_SKIP):
Remove not used macro.
(rs6000_loop_align): Change return type to align_flags.
(rs6000_loop_align_max_skip): Remove.
* config/rs6000/rs6000-protos.h (rs6000_loop_align):
Change return type to align_flags.
* config/rs6000/rs6000.c (TARGET_ASM_LOOP_ALIGN_MAX_SKIP):
Remove not used macro.
(rs6000_loop_align):  Change return type to align_flags.
(rs6000_loop_align_max_skip): Remove.
* config/rx/rx.h (JUMP_ALIGN): Wrap integer values
* config/rx/rx-protos.h (rx_align_for_label): Make it
static function.
* config/rx/rx.c (rx_align_for_label): Change return type
to align_flags.
(rx_max_skip_for_label): Remove TARGET_ASM_*_ALIGN_MAX_SKIP
macro definitions.
into align_flags class.
(LABEL_ALIGN): Likewise.
(LOOP_ALIGN): Likewise.
* config/s390/s390.c (s390_label_align): Use align_flags
class member.
(s390_asm_output_function_label): Likewise.
* config/sh/sh.c (sh_override_options_after_change):
Use align_flags class directly without macros.
(find_barrier): Likewise.
(barrier_align): Likewise.
(sh_loop_align): Likewise.
* config/spu/spu.c (spu_option_override):
Use align_flags_tuple::get_value instead of removed macros.
(spu_sched_init): Likewise.
* config/spu/spu.h (GTY): Likewise.
* config/visium/visium.c (visium_option_override):
Set "8" as default secondary alignment.
* config/visium/visium.h (SUBALIGN_LOG): Define to 3
in order to guarantee secondary alignment of 8.
* coretypes.h: Include align.h header file.
* doc/tm.texi: Remove TARGET_ASM_JUMP_ALIGN_MAX_SKIP,
TARGET_ASM_LOOP_ALIGN_MAX_SKIP, TARGET_ASM_LABEL_ALIGN_MAX_SKIP
and TARGET_ASM_LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP macros.
* doc/tm.texi.in: Likewise.
* final.c (struct label_alignment): Remove not used structure.
(LABEL_ALIGN): Change type to align_flags.
(LOOP_ALIGN): Likewise.
(JUMP_ALIGN): Likewise.
(default_loop_align_max_skip): Remove.
(default_label_align_max_skip): Likewise.
(default_jump_align_max_skip): Likewise.
(default_label_align_after_barrier_max_skip):
(LABEL_TO_ALIGNMENT): Change to access label_align vector.
(LABEL_TO_MAX_SKIP): Remove.
(label_to_alignment): Return align_flags type instead of integer.
(label_to_max_skip): Remove.
(align_fuzz): Use align_flags type.
(compute_alignments): Use align_flags type and use align_flags::max
to combine multiple alignments.
(grow_label_align): Grow vec instead of C array.
(update_alignments): Assign just LABEL_TO_ALIGNMENT.
(shorten_branches):  Use align_flags type and use align_flags::max
to combine multiple alignments.
(final_scan_insn_1): Remove usage of secondary alignment that comes
from label alignment, but instead use proper secondary alignment
which is computed in grow_label_align.
* flags.h (struct align_flags_tuple): Move to align.h.
(struct align_flags): Likewise.
(state_align_loops): Rename to align_loops.
(state_align_jumps): Rename to align_jumps.
(state_align_labels): Rename to align_labels.
(state_align_functions): Rename to align_functions.
(align_loops_log): Remove.
(align_jumps_log): Remove.
(align_labels_log): Remove.
(align_functions_log): Remove.
(align_loops_max_skip): Remove.
(align_jumps_max_skip): Remove.
(align_labels_max_skip): Remove.
(align_functions_max_skip): Remove.
(align_loops_value): Remove.
(align_jumps_value): Remove.
(align_labels_value): Remove.
(align_functions_value): Remove.
* output.h (label_to_alignment): Change return type to align_flags.
(label_to_max_skip): Remove.
* target.def: Remove loop_align_max_skip, label_align_max_skip,
jump_align_max_skip macros.
* targhooks.h (default_loop_align_max_skip): Remove.
(default_label_align_max_skip): Likewise.
(default_jump_align_max_skip): Likew

[PATCH 4/4] Do not enable OPT_falign_* for -Os.

2018-07-16 Thread marxin

gcc/ChangeLog:

2018-07-12  Martin Liska  

* opts.c: Do not enable OPT_falign_* for -Os.
---
 gcc/opts.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/opts.c b/gcc/opts.c
index 0625b15b27b..b8ae8756b4f 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -510,10 +510,10 @@ static const struct default_options default_options_table[] =
 { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
 { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
 { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
-{ OPT_LEVELS_2_PLUS, OPT_falign_loops, NULL, 1 },
-{ OPT_LEVELS_2_PLUS, OPT_falign_jumps, NULL, 1 },
-{ OPT_LEVELS_2_PLUS, OPT_falign_labels, NULL, 1 },
-{ OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },
+{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_loops, NULL, 1 },
+{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_jumps, NULL, 1 },
+{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_labels, NULL, 1 },
+{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_functions, NULL, 1 },
 { OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
 { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },
 { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },


[PATCH 0/4] Alignment option enhancements

2018-07-16 Thread marxin
Hi.

As you probably noticed, current trunk accepts extended format
of -falign-FOO options.
However there are some limitations that are addressed in the patchset:

1) E.g. align_labels_max_skip and align_labels_log are separate
   values and targets can override them via LABEL_ALIGN and
   LABEL_ALIGN_MAX_SKIP.  If you take a look at code in final.c:

 if (max_log < log)
{
  max_log = log;
  max_skip = targetm.asm_out.label_align_max_skip (label);
}

   It improves alignment, but max_skip can be zero and then we end up
   with no alignment.  Thus I see it saner to provide just a single hook
   and return align_flags class instance.

2) In final.c we mix label, jump and loop alignments. I believe when
   combining them together, one should do maximum and not rely on:

 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
  ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
  /* Above, we don't know whether a label, jump or loop
 alignment was used.  Conservatively apply
 label subalignment, not jump or loop
 subalignment (they are almost always larger).  */

   That's implemented in align_flags::max function. When combining
   for instance -falign-labels=1000 and -falign-jumps=2000, I hope
   using alignment of 2000 is the right choice.

3) I removed various align_* defines and use directly
   align_{*}.

4) I ported visium target to provide always secondary alignment of 8B.
   That's the same what x86_64 does and was factored out in previous commits
   I did.
  
5) Globally MAX_CODE_ALIGN is introduced.

6) Various coding styles are fixes in target code.

7) OPT_falign_* is not set with -Os. Then --help=common -Q reports proper 
values.

I tested that on x86_64-linux-gnu and ppc64le-linux. And also I tested all 
targets
that I touched, these should provide equal results.

Martin

marxin (4):
  Clean up of new format of -falign-FOO.
  Fix coding style of ASM_OUTPUT_ALIGN.
  Define MAX_CODE_ALIGN globally.
  Do not enable OPT_falign_* for -Os.

 gcc/align.h  |  80 
 gcc/common/config/i386/i386-common.c |   3 -
 gcc/config/alpha/alpha.c |   5 +-
 gcc/config/i386/att.h|   2 +-
 gcc/config/i386/cygming.h|   2 +-
 gcc/config/i386/gas.h|   2 +-
 gcc/config/i386/i386.c   |   5 +-
 gcc/config/i386/x86-64.h |   2 +-
 gcc/config/iq2000/iq2000.h   |   2 +-
 gcc/config/m32r/m32r.h   |   3 +-
 gcc/config/m68k/m68k.c   |  10 +-
 gcc/config/nds32/nds32.h |   9 +-
 gcc/config/pa/pa.h   |   2 +-
 gcc/config/powerpcspe/powerpcspe.c   |  18 +--
 gcc/config/rs6000/rs6000-protos.h|   2 +-
 gcc/config/rs6000/rs6000.c   |  18 +--
 gcc/config/rx/rx-protos.h|   2 +-
 gcc/config/rx/rx.c   |  59 +
 gcc/config/rx/rx.h   |   6 +-
 gcc/config/s390/s390.c   |   9 +-
 gcc/config/sh/sh.c   |  19 +--
 gcc/config/sparc/sol2.h  |   2 +-
 gcc/config/sparc/sparc.h |   2 +-
 gcc/config/spu/spu.c |   6 +-
 gcc/config/spu/spu.h |   2 +-
 gcc/config/visium/visium.c   |   2 +-
 gcc/config/visium/visium.h   |  17 +--
 gcc/coretypes.h  |   1 +
 gcc/doc/tm.texi  |  24 
 gcc/doc/tm.texi.in   |   8 --
 gcc/final.c  | 189 ---
 gcc/flags.h  |  38 +-
 gcc/opts.c   |  12 +-
 gcc/output.h |   6 +-
 gcc/system.h |   2 -
 gcc/target.def   |  40 --
 gcc/targhooks.h  |   4 -
 gcc/toplev.c |  44 ++-
 gcc/varasm.c |  14 +-
 39 files changed, 262 insertions(+), 411 deletions(-)
 create mode 100644 gcc/align.h

-- 
2.18.0



[PATCH 2/4] Replace ENABLE_CHECKING macro with flag_checking in GNAT

2016-02-25 Thread marxin
gcc/ada/ChangeLog:

2016-02-24  Martin Liska  

* gcc-interface/utils.c (set_reverse_storage_order_on_pad_type):
Replace ENABLE_CHECKING macro with flag_checking.
---
 gcc/ada/gcc-interface/utils.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index ff21e7b..4f81f1d 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -1486,11 +1486,13 @@ set_reverse_storage_order_on_pad_type (tree type)
 {
   tree field, canonical_pad_type;
 
-#ifdef ENABLE_CHECKING
-  /* If the inner type is not scalar then the function does nothing.  */
-  tree inner_type = TREE_TYPE (TYPE_FIELDS (type));
-  gcc_assert (!AGGREGATE_TYPE_P (inner_type) && !VECTOR_TYPE_P (inner_type));
-#endif
+  if (flag_checking)
+{
+  /* If the inner type is not scalar then the function does nothing.  */
+  tree inner_type = TREE_TYPE (TYPE_FIELDS (type));
+  gcc_assert (!AGGREGATE_TYPE_P (inner_type)
+ && !VECTOR_TYPE_P (inner_type));
+}
 
   /* This is required for the canonicalization.  */
   gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
-- 
2.7.0




[PATCH 4/4] Poison ENABLE_CHECKING macro

2016-02-25 Thread marxin
gcc/ChangeLog:

2016-02-25  Martin Liska  

* system.h: Poison ENABLE_CHECKING macro.
---
 gcc/system.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/system.h b/gcc/system.h
index 445073c..cb54541 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1014,6 +1014,10 @@ extern void fancy_abort (const char *, int, const char 
*) ATTRIBUTE_NORETURN;
 #undef rindex
  #pragma GCC poison bcopy bzero bcmp rindex
 
+/* Poison ENABLE_CHECKING macro that should be replaced with
+   'if (flag_checking)', or with CHECKING_P macro.  */
+#pragma GCC poison ENABLE_CHECKING
+
 #endif /* GCC >= 3.0 */
 
 /* This macro allows casting away const-ness to pass -Wcast-qual
-- 
2.7.0



[PATCH 3/4] Replace ENABLE_CHECKING with CHECKING_P in dwarf2out

2016-02-25 Thread marxin
gcc/ChangeLog:

2016-02-25  Martin Liska  

* dwarf2out.c (new_loc_descr): Replace ENABLE_CHECKING with
CHECKING_P.
(resolve_args_picking_1): Likewise.
* dwarf2out.h (struct GTY): Likewise.
---
 gcc/dwarf2out.c | 6 +++---
 gcc/dwarf2out.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 97e192b..a8c21d8 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1325,7 +1325,7 @@ new_loc_descr (enum dwarf_location_atom op, unsigned 
HOST_WIDE_INT oprnd1,
   dw_loc_descr_ref descr = ggc_cleared_alloc ();
 
   descr->dw_loc_opc = op;
-#if ENABLE_CHECKING
+#if CHECKING_P
   descr->dw_loc_frame_offset = -1;
 #endif
   descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -15369,14 +15369,14 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, 
unsigned initial_frame_offset,
   /* If we already met this node, there is nothing to compute anymore.  */
   if (visited.add (l))
{
-#if ENABLE_CHECKING
+#if CHECKING_P
  /* Make sure that the stack size is consistent wherever the execution
 flow comes from.  */
  gcc_assert ((unsigned) l->dw_loc_frame_offset == frame_offset_);
 #endif
  break;
}
-#if ENABLE_CHECKING
+#if CHECKING_P
   l->dw_loc_frame_offset = frame_offset_;
 #endif
 
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index a96ac38..91b3d6b 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -239,7 +239,7 @@ struct GTY((chain_next ("%h.dw_loc_next"))) 
dw_loc_descr_node {
  frame offset.  */
   unsigned int frame_offset_rel : 1;
   int dw_loc_addr;
-#if ENABLE_CHECKING
+#if CHECKING_P
   /* When translating a function into a DWARF procedure, contains the frame
  offset *before* evaluating this operation.  It is -1 when not yet
  initialized.  */
-- 
2.7.0




[PATCH 0/4] Replace remaining ENABLE_CHECKING macros

2016-02-25 Thread marxin
Hello

Following series removes remaining usage of ENABLE_CHECKING macro, where
the last patch eventually poisons the macro.

The series has been tested in common and survives regbootstrap on
x86_64-linux-gnu with default options (and Ada enabled)
and --enable-checking=none.

Ready for trunk?
Martin

marxin (4):
  Replace ENABLE_CHECKING macro with flag_checking in HSA
  Replace ENABLE_CHECKING macro with flag_checking in GNAT
  Replace ENABLE_CHECKING with CHECKING_P in dwarf2out
  Poison ENABLE_CHECKING macro

 gcc/ada/gcc-interface/utils.c | 12 +++-
 gcc/dwarf2out.c   |  6 +++---
 gcc/dwarf2out.h   |  2 +-
 gcc/hsa-gen.c | 25 +
 gcc/hsa-regalloc.c|  7 +++
 gcc/system.h  |  4 
 6 files changed, 31 insertions(+), 25 deletions(-)

-- 
2.7.0



[PATCH 1/4] Replace ENABLE_CHECKING macro with flag_checking in HSA

2016-02-25 Thread marxin
gcc/ChangeLog:

2016-02-24  Martin Liska  

* hsa-gen.c (generate_hsa): Replace ENABLE_CHECKING macro
with flag_checking.
* hsa-regalloc.c (linear_scan_regalloc): Likewise.
---
 gcc/hsa-gen.c  | 25 +
 gcc/hsa-regalloc.c |  7 +++
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 28e8b6f..8e2144c 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -6091,21 +6091,22 @@ generate_hsa (bool kernel)
 s->m_gridified_kernel_p);
 }
 
-#ifdef ENABLE_CHECKING
-  for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
-if (hsa_cfun->m_ssa_map[i])
-  hsa_cfun->m_ssa_map[i]->verify_ssa ();
-
-  basic_block bb;
-  FOR_EACH_BB_FN (bb, cfun)
+  if (flag_checking)
 {
-  hsa_bb *hbb = hsa_bb_for_bb (bb);
+  for (unsigned i = 0; i < hsa_cfun->m_ssa_map.length (); i++)
+   if (hsa_cfun->m_ssa_map[i])
+ hsa_cfun->m_ssa_map[i]->verify_ssa ();
 
-  for (hsa_insn_basic *insn = hbb->m_first_insn; insn; insn = insn->m_next)
-   insn->verify ();
-}
+  basic_block bb;
+  FOR_EACH_BB_FN (bb, cfun)
+   {
+ hsa_bb *hbb = hsa_bb_for_bb (bb);
 
-#endif
+ for (hsa_insn_basic *insn = hbb->m_first_insn; insn;
+  insn = insn->m_next)
+   insn->verify ();
+   }
+}
 
   hsa_regalloc ();
   hsa_brig_emit_function ();
diff --git a/gcc/hsa-regalloc.c b/gcc/hsa-regalloc.c
index f8e83ecf..9437132 100644
--- a/gcc/hsa-regalloc.c
+++ b/gcc/hsa-regalloc.c
@@ -580,10 +580,9 @@ linear_scan_regalloc (struct m_reg_class_desc *classes)
   /* Sort all intervals by increasing start point.  */
   gcc_assert (ind2reg.length () == (size_t) hsa_cfun->m_reg_count);
 
-#ifdef ENABLE_CHECKING
-  for (unsigned i = 0; i < ind2reg.length (); i++)
-gcc_assert (ind2reg[i]);
-#endif
+  if (flag_checking)
+for (unsigned i = 0; i < ind2reg.length (); i++)
+  gcc_assert (ind2reg[i]);
 
   ind2reg.qsort (cmp_begin);
   for (i = 0; i < 4; i++)
-- 
2.7.0




[PATCH 2/6] Fix memory leak in tree-ssa

2015-11-23 Thread marxin
gcc/ChangeLog:

2015-11-20  Martin Liska  

* tree-ssa.c (redirect_edge_var_map_destroy): Release
vectors that are used as a second argument of a hash_map.
---
 gcc/tree-ssa.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 02fca4c..db7d065 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -121,6 +121,11 @@ redirect_edge_var_map_vector (edge e)
 void
 redirect_edge_var_map_destroy (void)
 {
+  if (edge_var_maps)
+for (hash_map >::iterator it =
+edge_var_maps->begin (); it != edge_var_maps->end (); ++it)
+  (*it).second.release ();
+
   delete edge_var_maps;
   edge_var_maps = NULL;
 }
-- 
2.6.3




[PATCH 0/6] Another fixes of various memory leaks

2015-11-23 Thread marxin
Hi.

Following series has been just bootregtested on x86_64-linux-gnu
(all patches together).

Ready for trunk?
Thanks,
Martin

marxin (6):
  Fix memory leak in cilk
  Fix memory leak in tree-ssa
  Fix memory leaks in IPA devirt
  Fix memory leak in loop_vec_info
  Fix parser memory leak in cilk_simd_fn_info
  Fix memory leak in tree-chkp.c

 gcc/c-family/array-notation-common.c |  2 ++
 gcc/c-family/cilk.c  |  1 +
 gcc/c/c-array-notation.c | 38 ++
 gcc/cp/cp-array-notation.c   | 52 ++--
 gcc/cp/parser.c  |  2 ++
 gcc/ipa-devirt.c |  5 ++--
 gcc/tree-chkp.c  |  2 ++
 gcc/tree-ssa.c   |  5 
 gcc/tree-vect-loop-manip.c   |  2 --
 gcc/tree-vect-loop.c |  1 +
 gcc/vec.h| 12 +
 11 files changed, 68 insertions(+), 54 deletions(-)

-- 
2.6.3



[PATCH 4/6] Fix memory leak in loop_vec_info

2015-11-23 Thread marxin
gcc/ChangeLog:

2015-11-23  Martin Liska  

* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
Do not release memory for comp_alias_ddrs.
* tree-vect-loop.c (destroy_loop_vec_info): Release
the memory for all loop_vec_info.
---
 gcc/tree-vect-loop-manip.c | 2 --
 gcc/tree-vect-loop.c   | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index c96e196..226b88f 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -2284,8 +2284,6 @@ vect_create_cond_for_alias_checks (loop_vec_info 
loop_vinfo, tree * cond_expr)
 dump_printf_loc (MSG_NOTE, vect_location,
 "created %u versioning for alias checks.\n",
 comp_alias_ddrs.length ());
-
-  comp_alias_ddrs.release ();
 }
 
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 41e5031..8f39578 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1179,6 +1179,7 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo, bool 
clean_stmts)
   free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo));
   LOOP_VINFO_LOOP_NEST (loop_vinfo).release ();
   LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).release ();
+  LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo).release ();
   LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo).release ();
   slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
   FOR_EACH_VEC_ELT (slp_instances, j, instance)
-- 
2.6.3




[PATCH 5/6] Fix parser memory leak in cilk_simd_fn_info

2015-11-23 Thread marxin
gcc/cp/ChangeLog:

2015-11-23  Martin Liska  

* parser.c (cp_parser_late_parsing_cilk_simd_fn_info):
Release tokens.
---
 gcc/cp/parser.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 24ed404..fd5c7ec 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -35014,6 +35014,7 @@ cp_parser_late_parsing_cilk_simd_fn_info (cp_parser 
*parser, tree attrs)
   error ("%<#pragma omp declare simd%> of % attribute cannot be "
 "used in the same function marked as a Cilk Plus SIMD-enabled "
 " function");
+  parser->cilk_simd_fn_info->tokens.release ();
   XDELETE (parser->cilk_simd_fn_info);
   parser->cilk_simd_fn_info = NULL;
   return attrs;
@@ -35051,6 +35052,7 @@ cp_parser_late_parsing_cilk_simd_fn_info (cp_parser 
*parser, tree attrs)
   attrs = c;
 }
   info->fndecl_seen = true;
+  parser->cilk_simd_fn_info->tokens.release ();
   XDELETE (parser->cilk_simd_fn_info);
   parser->cilk_simd_fn_info = NULL;
   return attrs;
-- 
2.6.3




[PATCH 6/6] Fix memory leak in tree-chkp.c

2015-11-23 Thread marxin
gcc/ChangeLog:

2015-11-23  Martin Liska  

* tree-chkp.c (chkp_make_static_bounds): Release buffer
used for string.
---
 gcc/tree-chkp.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c
index 34d9dfc..8b6381f 100644
--- a/gcc/tree-chkp.c
+++ b/gcc/tree-chkp.c
@@ -2910,6 +2910,8 @@ chkp_make_static_bounds (tree obj)
pointer_bounds_type_node);
 }
 
+  free (bnd_var_name);
+
   TREE_PUBLIC (bnd_var) = 0;
   TREE_USED (bnd_var) = 1;
   TREE_READONLY (bnd_var) = 0;
-- 
2.6.3



[PATCH 1/6] Fix memory leak in cilk

2015-11-23 Thread marxin
gcc/c/ChangeLog:

2015-11-20  Martin Liska  

PR c++/68312
* c-array-notation.c (fix_builtin_array_notation_fn):
Use release_vec_vec instead of vec::release.
(build_array_notation_expr): Likewise.
(fix_conditional_array_notations_1): Likewise.
(fix_array_notation_expr): Likewise.
(fix_array_notation_call_expr): Likewise.

gcc/cp/ChangeLog:

2015-11-20  Martin Liska  

PR c++/68312
* cp-array-notation.c (expand_sec_reduce_builtin):
Likewise.
(create_array_refs): Replace argument with const reference.
(expand_an_in_modify_expr): Likewise.
(cp_expand_cond_array_notations): Likewise.
(expand_unary_array_notation_exprs): Likewise.

gcc/c-family/ChangeLog:

2015-11-20  Martin Liska  

PR c++/68312
* array-notation-common.c (cilkplus_extract_an_triplets):
Release vector of vectors.
* cilk.c (gimplify_cilk_spawn): Free allocated memory.

gcc/ChangeLog:

2015-11-20  Martin Liska  

PR c++/68312
* vec.h (release_vec_vec): New function.
---
 gcc/c-family/array-notation-common.c |  2 ++
 gcc/c-family/cilk.c  |  1 +
 gcc/c/c-array-notation.c | 38 ++
 gcc/cp/cp-array-notation.c   | 52 ++--
 gcc/vec.h| 12 +
 5 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/gcc/c-family/array-notation-common.c 
b/gcc/c-family/array-notation-common.c
index 4f7072b..5f2209d 100644
--- a/gcc/c-family/array-notation-common.c
+++ b/gcc/c-family/array-notation-common.c
@@ -636,6 +636,8 @@ cilkplus_extract_an_triplets (vec *list, 
size_t size, size_t rank,
  fold_build1 (CONVERT_EXPR, integer_type_node,
   ARRAY_NOTATION_STRIDE (ii_tree));
  }
+
+  release_vec_vec (array_exprs);
 }
 
 /* Replaces all the __sec_implicit_arg functions in LIST with the induction
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
index e75e20c..1167b2b 100644
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -844,6 +844,7 @@ gimplify_cilk_spawn (tree *spawn_p)
call2, build_empty_stmt (EXPR_LOCATION (call1)));
   append_to_statement_list (spawn_expr, spawn_p);
 
+  free (arg_array);
   return GS_OK;
 }
 
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
index 21f8684..49f5f7b 100644
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -98,7 +98,7 @@ make_triplet_val_inv (location_t loc, tree *value)
 
 static void
 create_cmp_incr (location_t loc, vec *node, size_t rank,
-vec > an_info)
+const vec > &an_info)
 {
   for (size_t ii = 0; ii < rank; ii++)
 {
@@ -122,7 +122,7 @@ create_cmp_incr (location_t loc, vec *node, 
size_t rank,
 */
 
 static vec *
-create_array_refs (location_t loc, vec > an_info,
+create_array_refs (location_t loc, const vec > &an_info,
   vec an_loop_info, size_t size, size_t rank)
 {
   tree ind_mult, ind_incr;
@@ -205,7 +205,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree 
*new_var)
   location_t location = UNKNOWN_LOCATION;
   tree loop_with_init = alloc_stmt_list ();
   vec > an_info = vNULL;
-  vec an_loop_info = vNULL;
+  auto_vec an_loop_info;
   enum built_in_function an_type =
 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
   if (an_type == BUILT_IN_NONE)
@@ -593,8 +593,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree 
*new_var)
 }
   append_to_statement_list_force (body, &loop_with_init);
 
-  an_info.release ();
-  an_loop_info.release ();
+  release_vec_vec (an_info);
   
   return loop_with_init;
 }
@@ -614,7 +613,7 @@ build_array_notation_expr (location_t location, tree lhs, 
tree lhs_origtype,
   tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
   tree array_expr = NULL_TREE;
   tree an_init = NULL_TREE;
-  vec cond_expr = vNULL;
+  auto_vec cond_expr;
   tree body, loop_with_init = alloc_stmt_list();
   tree scalar_mods = NULL_TREE;
   vec *rhs_array_operand = NULL, *lhs_array_operand = NULL;
@@ -624,7 +623,7 @@ build_array_notation_expr (location_t location, tree lhs, 
tree lhs_origtype,
   tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE;
   size_t rhs_list_size = 0, lhs_list_size = 0; 
   vec > lhs_an_info = vNULL, rhs_an_info = vNULL;
-  vec lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
+  auto_vec lhs_an_loop_info, rhs_an_loop_info;
   
   /* If either of this is true, an error message must have been send out
  already.  Not necessary to send out multiple error messages.  */
@@ -881,14 +880,9 @@ build_array_notation_expr (location_t location, tree lhs, 
tree lhs_origtype,
 }
   append_to_statement_list_force (body, &loop_with_init);
 
-  lhs_an_info.release ();
-  lhs_an_loop_info.release ();
+  release_vec_vec (lhs_an_info);
   if (rhs_rank)
-{
-  rhs_an_info.release ();

[PATCH 3/6] Fix memory leaks in IPA devirt

2015-11-23 Thread marxin
gcc/ChangeLog:

2015-11-20  Martin Liska  

* ipa-devirt.c (ipa_devirt): Use auto_vec instead
of a local-scope vec. Release final_warning_records.
---
 gcc/ipa-devirt.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index e74f853..6003c92 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -3837,7 +3837,7 @@ ipa_devirt (void)
 
   if (warn_suggest_final_methods)
{
- vec decl_warnings_vec = vNULL;
+ auto_vec decl_warnings_vec;
 
  final_warning_records->decl_warnings.traverse
 *, add_decl_warning> 
(&decl_warnings_vec);
@@ -3887,7 +3887,8 @@ ipa_devirt (void)
  decl, count, dyn_count);
}
}
-   
+
+  final_warning_records->type_warnings.release ();
   delete (final_warning_records);
   final_warning_records = 0;
 }
-- 
2.6.3




[PATCH 3/3] Improve switch code emission for a balanced tree (PR tree-optimization/86847).

2018-08-14 Thread marxin
This is the most complex patch. It follows original implementation and
does following improvements that were part of original code:

a) for a node with both children (that don't have children) and only single case
values handled: emit series of 3 compares and jump to default
b) for a node with only one child (that doesn't have a child) and only single
case values handled: emit 2 compares and jump to default
c) for a node of a range without a child, emit if (index - low) <= (high - low))
d) profile emission is precise, taken also from previous implementation

These changes + VRP should move us back to code quality we had in GCC 8.

gcc/ChangeLog:

2018-08-13  Martin Liska  

PR tree-optimization/86847
* tree-switch-conversion.c (switch_decision_tree::dump_case_nodes):
Dump also subtree probability.
(switch_decision_tree::do_jump_if_equal): New function.
(switch_decision_tree::emit_case_nodes): Handle special
situations in balanced tree that can be emitted much simpler.
Fix calculation of probabilities that happen in tree expansion.
* tree-switch-conversion.h (struct cluster): Add
is_single_value_p.
(struct simple_cluster): Likewise.
(struct case_tree_node): Add new function has_child.
(do_jump_if_equal): New.

gcc/testsuite/ChangeLog:

2018-08-13  Martin Liska  

* gcc.dg/tree-ssa/switch-3.c: New test.
* gcc.dg/tree-ssa/vrp105.c: Remove.
---
 gcc/testsuite/gcc.dg/tree-ssa/switch-3.c |  20 ++
 gcc/testsuite/gcc.dg/tree-ssa/vrp105.c   |  37 
 gcc/tree-switch-conversion.c | 243 ---
 gcc/tree-switch-conversion.h |  24 +++
 4 files changed, 256 insertions(+), 68 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/switch-3.c
 delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp105.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-3.c
new file mode 100644
index 000..44981e1d186
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-3.c
@@ -0,0 +1,20 @@
+/* { dg-options "-O2 -fdump-tree-switchlower1" } */
+
+int cipher_to_alg(int cipher)
+{
+  switch (cipher)  
+{
+  case 8:   return 2;  
+  case 16:  return 3;  
+  case 32:  return 4;  
+  case 64:  return 6;  
+  case 256: return 9;  
+  case 512: return 10; 
+  case 2048: return 11;
+  case 4096: return 12;
+  case 8192: return 13;
+}
+  return 0;
+} 
+
+/* { dg-final { scan-tree-dump-times "if \\(cipher\[^\n ]*" 12 "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp105.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp105.c
deleted file mode 100644
index 7cdd4dd8f3a..000
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp105.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* PR tree-optimization/18046  */
-/* { dg-options "-O2 -fdump-tree-vrp2-details" }  */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp2" } }  */
-/* In the 2nd VRP pass (after PRE) we expect to thread the default label of the
-   1st switch straight to that of the 2nd switch.  */
-
-extern void foo (void);
-extern void bar (void);
-
-extern int i;
-void
-test (void)
-{
-  switch (i)
-{
-case 0:
-  foo ();
-  break;
-case 1:
-  bar ();
-  break;
-default:
-  break;
-}
-
-  switch (i)
-{
-case 0:
-  foo ();
-  break;
-case 1:
-  bar ();
-  break;
-default:
-  break;
-}
-}
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index cd771438214..78914bbe81a 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -2008,7 +2008,9 @@ switch_decision_tree::dump_case_nodes (FILE *f, case_tree_node *root,
   fprintf (f, "%*s", indent_step * indent_level, "");
   root->m_c->dump (f);
   root->m_c->m_prob.dump (f);
-  fputs ("\n", f);
+  fputs (" subtree: ", f);
+  root->m_c->m_subtree_prob.dump (f);
+  fputs (")\n", f);
 
   dump_case_nodes (f, root->m_right, indent_step, indent_level);
 }
@@ -2054,6 +2056,33 @@ switch_decision_tree::emit_cmp_and_jump_insns (basic_block bb, tree op0,
   return false_edge->dest;
 }
 
+/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE.
+   PROB is the probability of jumping to LABEL_BB.  */
+
+basic_block
+switch_decision_tree::do_jump_if_equal (basic_block bb, tree op0, tree op1,
+	basic_block label_bb,
+	profile_probability prob)
+{
+  op1 = fold_convert (TREE_TYPE (op0), op1);
+
+  gcond *cond = gimple_build_cond (EQ_EXPR, op0, op1, NULL_TREE, NULL_TREE);
+  gimple_stmt_iterator gsi = gsi_last_bb (bb);
+  gsi_insert_before (&gsi, cond, GSI_SAME_STMT);
+
+  gcc_assert (single_succ_p (bb));
+
+  /* Make a new basic block where false branch will take place.  */
+  edge false_edge = split_block (bb, cond);
+  false_edge->fla

[PATCH 0/3] Improvements to switch expansion code

2018-08-14 Thread marxin
Hi.

With my rapid simplification of balanced tree emission we regressed
on number of tests needed (PR 86847). Apart from that profile info
was missing (INV) for jump tables and bit tests. That's fixed in another
2 patches. I'm explaining details of the patches in corresponding emails.

Patch can bootstrap on ppc64le-redhat-linux and survives regression tests.

marxin (3):
  Fix probabilities for jump table (PR tree-optimization/86702).
  Fix probability for bit-tests.
  Improve switch code emission for a balanced tree (PR
tree-optimization/86847).

 gcc/testsuite/gcc.dg/tree-ssa/switch-2.c |  25 ++
 gcc/testsuite/gcc.dg/tree-ssa/switch-3.c |  20 ++
 gcc/testsuite/gcc.dg/tree-ssa/vrp105.c   |  37 ---
 gcc/tree-switch-conversion.c | 329 +++
 gcc/tree-switch-conversion.h |  47 +++-
 5 files changed, 366 insertions(+), 92 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/switch-2.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/switch-3.c
 delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp105.c

-- 
2.18.0



[PATCH 1/3] Fix probabilities for jump table (PR tree-optimization/86702).

2018-08-14 Thread marxin
The patch set even probability to jump tables based on number of
cases which are handled on each edge.

gcc/ChangeLog:

2018-08-06  Martin Liska  

PR tree-optimization/86702
* tree-switch-conversion.c (jump_table_cluster::emit):
Make probabilities even for values in jump table
according to number of cases handled.
(switch_decision_tree::compute_cases_per_edge): Pass
argument to reset_out_edges_aux function.
(switch_decision_tree::analyze_switch_statement): Likewise.
* tree-switch-conversion.h (switch_decision_tree::reset_out_edges_aux):
Make it static.
---
 gcc/tree-switch-conversion.c | 40 ++--
 gcc/tree-switch-conversion.h | 11 +-
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 492cd365a30..0b5c93118f6 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1064,6 +1064,9 @@ void
 jump_table_cluster::emit (tree index_expr, tree,
 			  tree default_label_expr, basic_block default_bb)
 {
+  unsigned HOST_WIDE_INT range = get_range (get_low (), get_high ());
+  unsigned HOST_WIDE_INT nondefault_range = 0;
+
   /* For jump table we just emit a new gswitch statement that will
  be latter lowered to jump table.  */
   auto_vec  labels;
@@ -1080,6 +1083,39 @@ jump_table_cluster::emit (tree index_expr, tree,
 unshare_expr (default_label_expr), labels);
   gimple_stmt_iterator gsi = gsi_start_bb (m_case_bb);
   gsi_insert_after (&gsi, s, GSI_NEW_STMT);
+
+  /* Set up even probabilities for all cases.  */
+  for (unsigned i = 0; i < m_cases.length (); i++)
+{
+  simple_cluster *sc = static_cast (m_cases[i]);
+  edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
+  unsigned HOST_WIDE_INT case_range
+	= sc->get_range (sc->get_low (), sc->get_high ());
+  nondefault_range += case_range;
+
+  /* case_edge->aux is number of values in a jump-table that are covered
+	 by the case_edge.  */
+  case_edge->aux = (void *) ((intptr_t) (case_edge->aux) + case_range);
+}
+
+  edge default_edge = gimple_switch_default_edge (s);
+  default_edge->probability = profile_probability::never ();
+
+  for (unsigned i = 0; i < m_cases.length (); i++)
+{
+  simple_cluster *sc = static_cast (m_cases[i]);
+  edge case_edge = find_edge (m_case_bb, sc->m_case_bb);
+  case_edge->probability
+	= profile_probability::always ().apply_scale ((intptr_t)case_edge->aux,
+		  range);
+}
+
+  /* Number of non-default values is probability of default edge.  */
+  default_edge->probability
++= profile_probability::always ().apply_scale (nondefault_range,
+		   range).invert ();
+
+  switch_decision_tree::reset_out_edges_aux (s);
 }
 
 /* Find jump tables of given CLUSTERS, where all members of the vector
@@ -1571,7 +1607,7 @@ bit_test_cluster::hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
 void
 switch_decision_tree::compute_cases_per_edge ()
 {
-  reset_out_edges_aux ();
+  reset_out_edges_aux (m_switch);
   int ncases = gimple_switch_num_labels (m_switch);
   for (int i = ncases - 1; i >= 1; --i)
 {
@@ -1614,7 +1650,7 @@ switch_decision_tree::analyze_switch_statement ()
   m_case_bbs.quick_push (case_edge->dest);
 }
 
-  reset_out_edges_aux ();
+  reset_out_edges_aux (m_switch);
 
   /* Find jump table clusters.  */
   vec output = jump_table_cluster::find_jump_tables (clusters);
diff --git a/gcc/tree-switch-conversion.h b/gcc/tree-switch-conversion.h
index 4beac785f05..af2f47a07e6 100644
--- a/gcc/tree-switch-conversion.h
+++ b/gcc/tree-switch-conversion.h
@@ -513,10 +513,6 @@ struct switch_decision_tree
   /* Attempt to expand CLUSTERS as a decision tree.  Return true when
  expanded.  */
   bool try_switch_expansion (vec &clusters);
-
-  /* Reset the aux field of all outgoing edges of switch basic block.  */
-  inline void reset_out_edges_aux ();
-
   /* Compute the number of case labels that correspond to each outgoing edge of
  switch statement.  Record this information in the aux field of the edge.
  */
@@ -576,6 +572,9 @@ struct switch_decision_tree
 	  basic_block label_bb,
 	  profile_probability prob);
 
+  /* Reset the aux field of all outgoing edges of switch basic block.  */
+  static inline void reset_out_edges_aux (gswitch *swtch);
+
   /* Switch statement.  */
   gswitch *m_switch;
 
@@ -838,9 +837,9 @@ struct switch_conversion
 };
 
 void
-switch_decision_tree::reset_out_edges_aux ()
+switch_decision_tree::reset_out_edges_aux (gswitch *swtch)
 {
-  basic_block bb = gimple_bb (m_switch);
+  basic_block bb = gimple_bb (swtch);
   edge e;
   edge_iterator ei;
   FOR_EACH_EDGE (e, ei, bb->succs)


[PATCH 2/3] Fix probability for bit-tests.

2018-08-14 Thread marxin
The patch set even probability to bit test based on number of
cases which are handled on each edge.

gcc/ChangeLog:

2018-08-06  Martin Liska  

* tree-switch-conversion.c (bit_test_cluster::find_bit_tests):
Add new argument to bit_test_cluster constructor.
(bit_test_cluster::emit): Set bits really number of values
handlel by a test.
(bit_test_cluster::hoist_edge_and_branch_if_true): Add
probability argument.
* tree-switch-conversion.h (struct bit_test_cluster):
Add m_handles_entire_switch.

gcc/testsuite/ChangeLog:

2018-08-06  Martin Liska  

* gcc.dg/tree-ssa/switch-2.c: New test.
---
 gcc/testsuite/gcc.dg/tree-ssa/switch-2.c | 25 +
 gcc/tree-switch-conversion.c | 46 +---
 gcc/tree-switch-conversion.h | 12 +--
 3 files changed, 67 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/switch-2.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/switch-2.c b/gcc/testsuite/gcc.dg/tree-ssa/switch-2.c
new file mode 100644
index 000..710825dc257
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/switch-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { { x86_64-*-* aarch64-*-* ia64-*-* powerpc64-*-* } && lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-switchlower1" } */
+
+int global;
+
+int foo (int x)
+{
+  switch (x) {
+case 0:
+case 10:
+  return 1;
+case 20:
+case 30:
+case 62:
+  return 2;
+case 1000:
+case 1010:
+case 1025 ... 1030:
+  return 1;
+default:
+  return 0;
+  }
+}
+
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: BT:0-62 BT:1000-1030" "switchlower1" } } */
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 0b5c93118f6..cd771438214 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1282,12 +1282,16 @@ bit_test_cluster::find_bit_tests (vec &clusters)
 return clusters.copy ();
 
   /* Find and build the clusters.  */
-  for (int end = l;;)
+  for (unsigned end = l;;)
 {
   int start = min[end].m_start;
 
   if (is_beneficial (clusters, start, end - 1))
-	output.safe_push (new bit_test_cluster (clusters, start, end - 1));
+	{
+	  bool entire = start == 0 && end == clusters.length ();
+	  output.safe_push (new bit_test_cluster (clusters, start, end - 1,
+		  entire));
+	}
   else
 	for (int i = end - 1; i >=  start; i--)
 	  output.safe_push (clusters[i]);
@@ -1437,6 +1441,7 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
   tree minval = get_low ();
   tree maxval = get_high ();
   tree range = int_const_binop (MINUS_EXPR, maxval, minval);
+  unsigned HOST_WIDE_INT bt_range = get_range (minval, maxval);
 
   /* Go through all case labels, and collect the case labels, profile
  counts, and other information we need to build the branch tests.  */
@@ -1455,11 +1460,11 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
 	  test[k].mask = wi::zero (prec);
 	  test[k].target_bb = n->m_case_bb;
 	  test[k].label = n->m_case_label_expr;
-	  test[k].bits = 1;
+	  test[k].bits = 0;
 	  count++;
 	}
-  else
-	test[k].bits++;
+
+  test[k].bits += n->get_range (n->get_low (), n->get_high ());
 
   lo = tree_to_uhwi (int_const_binop (MINUS_EXPR, n->get_low (), minval));
   if (n->get_high () == NULL_TREE)
@@ -1516,14 +1521,20 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
   /*simple=*/true, NULL_TREE,
   /*before=*/true, GSI_SAME_STMT);
 
-  /* if (idx > range) goto default */
-  range = force_gimple_operand_gsi (&gsi,
+  if (m_handles_entire_switch)
+{
+  /* if (idx > range) goto default */
+  range
+	= force_gimple_operand_gsi (&gsi,
 fold_convert (unsigned_index_type, range),
 /*simple=*/true, NULL_TREE,
 /*before=*/true, GSI_SAME_STMT);
-  tmp = fold_build2 (GT_EXPR, boolean_type_node, idx, range);
-  basic_block new_bb = hoist_edge_and_branch_if_true (&gsi, tmp, default_bb);
-  gsi = gsi_last_bb (new_bb);
+  tmp = fold_build2 (GT_EXPR, boolean_type_node, idx, range);
+  basic_block new_bb
+	= hoist_edge_and_branch_if_true (&gsi, tmp, default_bb,
+	 profile_probability::unlikely ());
+  gsi = gsi_last_bb (new_bb);
+}
 
   /* csui = (1 << (word_mode) idx) */
   csui = make_ssa_name (word_type_node);
@@ -1536,17 +1547,23 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
   gsi_insert_before (&gsi, shift_stmt, GSI_SAME_STMT);
   update_stmt (shift_stmt);
 
+  profile_probability prob = profile_probability::always ();
+
   /* for each unique set of cases:
if (const & csui) goto target  */
   for (k = 0; k < count; k++)
 {
+  prob = profile_probability::always ().apply_scale (test[k].bits,
+			 bt_range);
+  bt_range -= test[k].bits;
   tmp = wide_int_to_tree (word_type_node, test[k].mask);
   tmp = fold_build2 (BIT_AND_EXPR, word_type_node,

[PATCH 0/3] Rework early return and hot/cold label predictors

2017-06-06 Thread marxin
Hello.

As mentioned in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79489#c1
early-return predictors is currenty not much precise. I decided to
come up with GIMPLE_PREDICT statement that I put early and thus
more precise numbers can be seen.

For SPEC 2017 we can improve the predictor from:
HEURISTICS   BRANCHES  (REL)  BR. HITRATE   
 HITRATE   COVERAGE COVERAGE  (REL)  predict.def  (REL)
early return (on trees) 17804  11.7%   63.54%   55.14% 
/  85.46%38154989508   38.15G   5.4%  54%   1.1%

to:

early return (on trees)  3692   4.1%   79.55%   66.22% 
/  76.14%15778842701   15.78G   2.4%  66%   0.2%

For tests I had to change couple of tailrecursion tests, where recursion
happens in tailr2 pass. It's not done in tailr1 due to GIMPLE_PREDICT
statement.

Apart from that I would like to add a sanity unit tests for values
of predictors. And finally, I was asked by Honza to transform cold/hot
label predictors to GIMPLE_PREDICT as well.

Patch can bootstrap on ppc64le-redhat-linux and survives regression tests.

Ready to be installed?
Martin

marxin (3):
  Come up with selftests for predict.c.
  Make early return predictor more precise.
  Rework cold and hot label attributes in predict.c.

 gcc/gimple-low.c|   3 +
 gcc/gimple-predict.h|   8 ++
 gcc/gimplify.c  |  26 +-
 gcc/predict.c   | 103 +---
 gcc/predict.def |  15 +---
 gcc/selftest-run-tests.c|   1 +
 gcc/selftest.h  |   1 +
 gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c  |   4 +-
 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-1.c |   4 +-
 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-2.c |   4 +-
 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c |   4 +-
 gcc/tree-inline.c   |   7 ++
 12 files changed, 95 insertions(+), 85 deletions(-)

-- 
2.13.0



[PATCH 1/3] Come up with selftests for predict.c.

2017-06-06 Thread marxin
gcc/ChangeLog:

2017-05-26  Martin Liska  

* predict.c (struct branch_predictor): New struct.
(test_prediction_value_range): New test.
(predict_tests_c_tests): New function.
* selftest-run-tests.c (selftest::run_tests): Run the function.
* selftest.h: Declare new tests.
---
 gcc/predict.c| 39 +++
 gcc/selftest-run-tests.c |  1 +
 gcc/selftest.h   |  1 +
 3 files changed, 41 insertions(+)

diff --git a/gcc/predict.c b/gcc/predict.c
index ac35fa41129..ea445e94e46 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -57,6 +57,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "ipa-utils.h"
 #include "gimple-pretty-print.h"
+#include "selftest.h"
 
 /* Enum with reasons why a predictor is ignored.  */
 
@@ -3803,3 +3804,41 @@ force_edge_cold (edge e, bool impossible)
 impossible ? "impossible" : "cold");
 }
 }
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Test that value range of predictor values defined in predict.def is
+   within range [51, 100].  */
+
+struct branch_predictor
+{
+  const char *name;
+  unsigned probability;
+};
+
+#define DEF_PREDICTOR(ENUM, NAME, HITRATE, FLAGS) { NAME, HITRATE },
+
+static void
+test_prediction_value_range ()
+{
+  branch_predictor predictors[] = {
+#include "predict.def"
+{NULL, -1}
+  };
+
+  for (unsigned i = 0; predictors[i].name != NULL; i++)
+ASSERT_TRUE (100 * predictors[i].probability / REG_BR_PROB_BASE > 50);
+}
+
+/* Run all of the selfests within this file.  */
+
+void
+predict_tests_c_tests ()
+{
+  test_prediction_value_range ();
+}
+
+} // namespace selftest
+#endif /* CHECKING_P.  */
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index f62bc72b072..af511a47681 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -92,6 +92,7 @@ selftest::run_tests ()
 targetm.run_target_selftests ();
 
   store_merging_c_tests ();
+  predict_tests_c_tests ();
 
   /* Run any lang-specific selftests.  */
   lang_hooks.run_lang_selftests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index dad53e9fe09..e84b309359d 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -196,6 +196,7 @@ extern void tree_c_tests ();
 extern void tree_cfg_c_tests ();
 extern void vec_c_tests ();
 extern void wide_int_cc_tests ();
+extern void predict_tests_c_tests ();
 
 extern int num_passes;
 
-- 
2.13.0




[PATCH 3/3] Rework cold and hot label attributes in predict.c.

2017-06-06 Thread marxin
gcc/ChangeLog:

2017-05-26  Martin Liska  

* gimplify.c (gimplify_label_expr): Insert GIMPLE_PREDICT
statements on cold and hot labels.
* predict.c (tree_estimate_probability_bb): Remove the
prediction from this place.

gcc/testsuite/ChangeLog:

2017-05-31  Martin Liska  

* gcc.dg/tree-ssa/attr-hotcold-2.c: Update scanned patterns.
---
 gcc/gimplify.c | 10 +-
 gcc/predict.c  | 23 ---
 gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c |  4 ++--
 3 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f192a891a8c..b2818e2465f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2356,10 +2356,18 @@ gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
   gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
  == current_function_decl);
 
-  glabel *label_stmt = gimple_build_label (LABEL_EXPR_LABEL (*expr_p));
+  tree label = LABEL_EXPR_LABEL (*expr_p);
+  glabel *label_stmt = gimple_build_label (label);
   gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
   gimplify_seq_add_stmt (pre_p, label_stmt);
 
+  if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
+gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
+ NOT_TAKEN));
+  else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
+gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
+ TAKEN));
+
   return GS_ALL_DONE;
 }
 
diff --git a/gcc/predict.c b/gcc/predict.c
index d561f27342d..419a4842f03 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -2698,29 +2698,6 @@ tree_estimate_probability_bb (basic_block bb)
 
   FOR_EACH_EDGE (e, ei, bb->succs)
 {
-  /* Predict edges to user labels with attributes.  */
-  if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
-   {
- gimple_stmt_iterator gi;
- for (gi = gsi_start_bb (e->dest); !gsi_end_p (gi); gsi_next (&gi))
-   {
- glabel *label_stmt = dyn_cast  (gsi_stmt (gi));
- tree decl;
-
- if (!label_stmt)
-   break;
- decl = gimple_label_label (label_stmt);
- if (DECL_ARTIFICIAL (decl))
-   continue;
-
- /* Finally, we have a user-defined label.  */
- if (lookup_attribute ("cold", DECL_ATTRIBUTES (decl)))
-   predict_edge_def (e, PRED_COLD_LABEL, NOT_TAKEN);
- else if (lookup_attribute ("hot", DECL_ATTRIBUTES (decl)))
-   predict_edge_def (e, PRED_HOT_LABEL, TAKEN);
-   }
-   }
-
   /* Look for block we are guarding (ie we dominate it,
 but it doesn't postdominate us).  */
   if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun) && e->dest != bb
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c
index 13d2916c47b..184dd10ddae 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c
@@ -20,9 +20,9 @@ void f(int x, int y)
 
 /* { dg-final { scan-tree-dump-times "hot label heuristics" 1 
"profile_estimate" } } */
 /* { dg-final { scan-tree-dump-times "cold label heuristics" 1 
"profile_estimate" } } */
-/* { dg-final { scan-tree-dump-times "block 4, loop depth 0, count 0, freq 
\[1-4\]\[^0-9\]" 3 "profile_estimate" } } */
+/* { dg-final { scan-tree-dump "A \\\[0\\\..*\\\]" "profile_estimate" } } */
 
 /* Note: we're attempting to match some number > 6000, i.e. > 60%.
The exact number ought to be tweekable without having to juggle
the testcase around too much.  */
-/* { dg-final { scan-tree-dump-times "block 5, loop depth 0, count 0, freq 
\[6-9\]\[0-9\]\[0-9\]\[0-9\]" 3 "profile_estimate" } } */
+/* { dg-final { scan-tree-dump "B \\\[\[6-9\]\[0-9\]\\\..*\\\]" 
"profile_estimate" } } */
-- 
2.13.0



[PATCH 2/3] Make early return predictor more precise.

2017-06-06 Thread marxin
gcc/ChangeLog:

2017-05-26  Martin Liska  

PR tree-optimization/79489
* gimplify.c (maybe_add_early_return_predict_stmt): New
function.
(gimplify_return_expr): Call the function.
* predict.c (tree_estimate_probability_bb): Remove handling
of early return.
* predict.def: Update comment about early return predictor.
* gimple-predict.h (is_gimple_predict): New function.
* tree-inline.c (remap_gimple_stmt): Do not copy early return
predictors during inlining.
* predict.def: Change default value of early return to 66.

gcc/testsuite/ChangeLog:

2017-05-31  Martin Liska  

PR tree-optimization/79489
* gcc.dg/tree-ssa/tailrecursion-1.c: Change tail1 to tailr2.
* gcc.dg/tree-ssa/tailrecursion-2.c: Likewise.
* gcc.dg/tree-ssa/tailrecursion-6.c: Likewise.
---
 gcc/gimple-low.c|  3 ++
 gcc/gimple-predict.h|  8 +
 gcc/gimplify.c  | 16 ++
 gcc/predict.c   | 41 -
 gcc/predict.def | 15 ++---
 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-1.c |  4 +--
 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-2.c |  4 +--
 gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c |  4 +--
 gcc/tree-inline.c   |  7 +
 9 files changed, 43 insertions(+), 59 deletions(-)

diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 619b9d7bfb1..a56a7b87b88 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "calls.h"
 #include "gimple-iterator.h"
 #include "gimple-low.h"
+#include "predict.h"
+#include "gimple-predict.h"
 
 /* The differences between High GIMPLE and Low GIMPLE are the
following:
@@ -684,6 +686,7 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct 
lower_data *data)
   /* When not optimizing, make sure user returns are preserved.  */
   if (!optimize && gimple_has_location (stmt))
 DECL_ARTIFICIAL (tmp_rs.label) = 0;
+
   t = gimple_build_goto (tmp_rs.label);
   gimple_set_location (t, gimple_location (stmt));
   gimple_set_block (t, gimple_block (stmt));
diff --git a/gcc/gimple-predict.h b/gcc/gimple-predict.h
index ba58e12e9e9..0e6c2e1ea01 100644
--- a/gcc/gimple-predict.h
+++ b/gcc/gimple-predict.h
@@ -80,4 +80,12 @@ gimple_build_predict (enum br_predictor predictor, enum 
prediction outcome)
   return p;
 }
 
+/* Return true if GS is a GIMPLE_PREDICT statement.  */
+
+static inline bool
+is_gimple_predict (const gimple *gs)
+{
+  return gimple_code (gs) == GIMPLE_PREDICT;
+}
+
 #endif  /* GCC_GIMPLE_PREDICT_H */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2c7fc9fabd1..f192a891a8c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1428,6 +1428,20 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   return GS_ALL_DONE;
 }
 
+/* Maybe add early return predict statement to PRE_P sequence.  */
+
+static void
+maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
+{
+  /* If we are not in a conditional context, add PREDICT statement.  */
+  if (gimple_conditional_context ())
+{
+  gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
+ NOT_TAKEN);
+  gimplify_seq_add_stmt (pre_p, predict);
+}
+}
+
 /* Gimplify a RETURN_EXPR.  If the expression to be returned is not a
GIMPLE value, it is assigned to a new temporary and the statement is
re-written to return the temporary.
@@ -1458,6 +1472,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
   || TREE_CODE (ret_expr) == RESULT_DECL
   || ret_expr == error_mark_node)
 {
+  maybe_add_early_return_predict_stmt (pre_p);
   greturn *ret = gimple_build_return (ret_expr);
   gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
   gimplify_seq_add_stmt (pre_p, ret);
@@ -1525,6 +1540,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
 
   gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
 
+  maybe_add_early_return_predict_stmt (pre_p);
   ret = gimple_build_return (result);
   gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
   gimplify_seq_add_stmt (pre_p, ret);
diff --git a/gcc/predict.c b/gcc/predict.c
index ea445e94e46..d561f27342d 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -2695,7 +2695,6 @@ tree_estimate_probability_bb (basic_block bb)
 {
   edge e;
   edge_iterator ei;
-  gimple *last;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
 {
@@ -2722,46 +2721,6 @@ tree_estimate_probability_bb (basic_block bb)
}
}
 
-  /* Predict early returns to be probable, as we've already taken
-care for error returns and other cases are often used for
-fast paths through function.
-
-Since we've already removed the return statements, we are
-looking for CFG like:
-
-if (conditional)

[PATCH 0/7] GCOV: infrastructure clean-up

2017-11-09 Thread marxin
Hello.

Following patch series is quite mechanical, it adds usage of STL
containers and it removes many typedefs that are with C++ not needed
in my oppinion.

Patch survives gcov.exp test-suite.

Thanks,
Martin

marxin (7):
  GCOV: introduce global vector of functions
  GCOV: simplify usage of function_info::artificial.
  GCOV: introduce vector for function_info::counts.
  GCOV: remove typedef for function_t
  GCOV: remove typedef for arc_t
  GCOV: remove typedef for block_t
  GCOV: remove typedef of coverage_t.

 gcc/gcov.c | 365 ++---
 1 file changed, 177 insertions(+), 188 deletions(-)

-- 
2.14.3



[PATCH 2/7] GCOV: simplify usage of function_info::artificial.

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (is_artificial): New function.
(process_file): Erase all artificial early.
(generate_results): Skip as all artificial are already
removed.
---
 gcc/gcov.c | 66 +-
 1 file changed, 40 insertions(+), 26 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 83239639247..3dc159726c7 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -1088,6 +1088,14 @@ struct function_start_pair_hash : typed_noop_remove 

   }
 };
 
+/* Function filter based on function_info::artificial variable.  */
+
+static bool
+is_artificial (function_info *fn)
+{
+  return fn->artificial;
+}
+
 /* Process a single input file.  */
 
 static void
@@ -1122,33 +1130,40 @@ process_file (const char *file_name)
  fn_map.put (needle, *it);
   }
 
+  /* Remove all artificial function.  */
+  functions.erase (remove_if (functions.begin (), functions.end (),
+ is_artificial), functions.end ());
+
   for (vector::iterator it = functions.begin ();
it != functions.end (); it++)
 {
   function_t *fn = *it;
+  unsigned src = fn->src;
 
   if (fn->counts || no_data_file)
{
- unsigned src = fn->src;
- unsigned block_no;
+ source_info *s = &sources[src];
+ s->functions.push_back (fn);
 
- /* Process only non-artificial functions.  */
- if (!fn->artificial)
+ /* Mark last line in files touched by function.  */
+ for (unsigned block_no = 0; block_no != fn->blocks.size ();
+  block_no++)
{
- source_info *s = &sources[src];
- s->functions.push_back (fn);
-
- /* Mark last line in files touched by function.  */
- for (block_no = 0; block_no != fn->blocks.size (); block_no++)
+ block_t *block = &fn->blocks[block_no];
+ for (unsigned i = 0; i < block->locations.size (); i++)
{
- block_t *block = &fn->blocks[block_no];
- for (unsigned i = 0; i < block->locations.size (); i++)
+ /* Sort lines of locations.  */
+ sort (block->locations[i].lines.begin (),
+   block->locations[i].lines.end ());
+
+ if (!block->locations[i].lines.empty ())
{
- /* Sort lines of locations.  */
- sort (block->locations[i].lines.begin (),
-   block->locations[i].lines.end ());
+ s = &sources[block->locations[i].source_file_idx];
+ unsigned last_line
+   = block->locations[i].lines.back ();
 
- if (!block->locations[i].lines.empty ())
+ /* Record new lines for the function.  */
+ if (last_line >= s->lines.size ())
{
  s = &sources[block->locations[i].source_file_idx];
  unsigned last_line
@@ -1162,17 +1177,18 @@ process_file (const char *file_name)
}
}
}
-
- /* Allocate lines for group function, following start_line
-and end_line information of the function.  */
- if (fn->is_group)
-   fn->lines.resize (fn->end_line - fn->start_line + 1);
}
-
- solve_flow_graph (fn);
- if (fn->has_catch)
-   find_exception_blocks (fn);
}
+
+ /* Allocate lines for group function, following start_line
+and end_line information of the function.  */
+ if (fn->is_group)
+   fn->lines.resize (fn->end_line - fn->start_line + 1);
+
+
+ solve_flow_graph (fn);
+ if (fn->has_catch)
+   find_exception_blocks (fn);
}
   else
{
@@ -1221,8 +1237,6 @@ generate_results (const char *file_name)
 {
   function_t *fn = *it;
   coverage_t coverage;
-  if (fn->artificial)
-   continue;
 
   memset (&coverage, 0, sizeof (coverage));
   coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
-- 
2.14.3




[PATCH 1/7] GCOV: introduce global vector of functions

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (read_graph_file): Store to global vector of functions.
(read_count_file): Iterate the vector.
(process_file): Likewise.
(generate_results): Likewise.
(release_structures): Likewise.
---
 gcc/gcov.c | 108 +
 1 file changed, 44 insertions(+), 64 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 846a2326196..83239639247 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -392,10 +392,8 @@ public:
   unsigned src;  /* Source file */
 };
 
-/* Holds a list of function basic block graphs.  */
-

-static function_t *functions;
-static function_t **fn_end = &functions;
+/* Vector of all functions.  */
+static vector functions;
 
 /* Vector of source files.  */
 static vector sources;
@@ -532,8 +530,8 @@ static void generate_results (const char *);
 static void create_file_names (const char *);
 static char *canonicalize_name (const char *);
 static unsigned find_source (const char *);
-static function_t *read_graph_file (void);
-static int read_count_file (function_t *);
+static void read_graph_file (void);
+static int read_count_file (void);
 static void solve_flow_graph (function_t *);
 static void find_exception_blocks (function_t *);
 static void add_branch_counts (coverage_t *, const arc_t *);
@@ -1095,42 +1093,40 @@ struct function_start_pair_hash : typed_noop_remove 

 static void
 process_file (const char *file_name)
 {
-  function_t *fns;
-
   create_file_names (file_name);
-  fns = read_graph_file ();
-  if (!fns)
+  read_graph_file ();
+  if (functions.empty ())
 return;
 
-  read_count_file (fns);
+  read_count_file ();
 
   hash_map fn_map;
 
   /* Identify group functions.  */
-  for (function_t *f = fns; f; f = f->next)
-if (!f->artificial)
+  for (vector::iterator it = functions.begin ();
+   it != functions.end (); it++)
+if (!(*it)->artificial)
   {
function_start needle;
-   needle.source_file_idx = f->src;
-   needle.start_line = f->start_line;
+   needle.source_file_idx = (*it)->src;
+   needle.start_line = (*it)->start_line;
 
function_t **slot = fn_map.get (needle);
if (slot)
  {
-   gcc_assert ((*slot)->end_line == f->end_line);
+   gcc_assert ((*slot)->end_line == (*it)->end_line);
(*slot)->is_group = 1;
-   f->is_group = 1;
+   (*it)->is_group = 1;
  }
else
- fn_map.put (needle, f);
+ fn_map.put (needle, *it);
   }
 
-  while (fns)
+  for (vector::iterator it = functions.begin ();
+   it != functions.end (); it++)
 {
-  function_t *fn = fns;
+  function_t *fn = *it;
 
-  fns = fn->next;
-  fn->next = NULL;
   if (fn->counts || no_data_file)
{
  unsigned src = fn->src;
@@ -1177,14 +1173,12 @@ process_file (const char *file_name)
  if (fn->has_catch)
find_exception_blocks (fn);
}
-
- *fn_end = fn;
- fn_end = &fn->next;
}
   else
-   /* The function was not in the executable -- some other
-  instance must have been selected.  */
-   delete fn;
+   {
+ /* The function was not in the executable -- some other
+instance must have been selected.  */
+   }
 }
 }
 
@@ -1222,10 +1216,10 @@ output_gcov_file (const char *file_name, source_info 
*src)
 static void
 generate_results (const char *file_name)
 {
-  function_t *fn;
-
-  for (fn = functions; fn; fn = fn->next)
+  for (vector::iterator it = functions.begin ();
+   it != functions.end (); it++)
 {
+  function_t *fn = *it;
   coverage_t coverage;
   if (fn->artificial)
continue;
@@ -1291,13 +1285,11 @@ generate_results (const char *file_name)
 static void
 release_structures (void)
 {
-  function_t *fn;
+  for (vector::iterator it = functions.begin ();
+   it != functions.end (); it++)
+delete (*it);
 
-  while ((fn = functions))
-{
-  functions = fn->next;
-  delete fn;
-}
+  functions.resize (0);
 }
 
 /* Generate the names of the graph and data files.  If OBJECT_DIRECTORY
@@ -1455,29 +1447,26 @@ find_source (const char *file_name)
   return idx;
 }
 
-/* Read the notes file.  Return list of functions read -- in reverse order.  */
+/* Read the notes file.  Save functions to FUNCTIONS global vector.  */
 
-static function_t *
+static void
 read_graph_file (void)
 {
   unsigned version;
   unsigned current_tag = 0;
-  function_t *fn = NULL;
-  function_t *fns = NULL;
-  function_t **fns_end = &fns;
   unsigned tag;
 
   if (!gcov_open (bbg_file_name, 1))
 {
   fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
-  return fns;
+  return;
 }
   bbg_file_time = gcov_time ();
   if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
 {
   fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
  

[PATCH 5/7] GCOV: remove typedef for arc_t

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (struct arc_info): Remove typedef for arc_t.
(struct line_info): Likewise.
(add_branch_counts): Likewise.
(output_branch_count): Likewise.
(function_info::~function_info): Likewise.
(circuit): Likewise.
(output_intermediate_line): Likewise.
(read_graph_file): Likewise.
(solve_flow_graph): Likewise.
(find_exception_blocks): Likewise.
(add_line_counts): Likewise.
(accumulate_line_info): Likewise.
(output_line_details): Likewise.
(output_function_details): Likewise.
---
 gcc/gcov.c | 58 +-
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index a1c489bccdc..e33c7b6f8cd 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -79,7 +79,7 @@ struct source_info;
 
 /* Describes an arc between two basic blocks.  */
 
-typedef struct arc_info
+struct arc_info
 {
   /* source and destination blocks.  */
   struct block_info *src;
@@ -113,7 +113,7 @@ typedef struct arc_info
   /* Links to next arc on src and dst lists.  */
   struct arc_info *succ_next;
   struct arc_info *pred_next;
-} arc_t;
+};
 
 /* Describes which locations (lines and files) are associated with
a basic block.  */
@@ -137,8 +137,8 @@ typedef struct block_info
   block_info ();
 
   /* Chain of exit and entry arcs.  */
-  arc_t *succ;
-  arc_t *pred;
+  arc_info *succ;
+  arc_info *pred;
 
   /* Number of unprocessed exit and entry arcs.  */
   gcov_type num_succ;
@@ -166,7 +166,7 @@ typedef struct block_info
   {
 /* Single line graph cycle workspace.  Used for all-blocks
mode.  */
-arc_t *arc;
+arc_info *arc;
 unsigned ident;
   } cycle; /* Used in all-blocks mode, after blocks are linked onto
 lines.  */
@@ -200,7 +200,7 @@ struct line_info
   gcov_type count;
 
   /* Branches from blocks that end on this line.  */
-  vector branches;
+  vector branches;
 
   /* blocks which start on this line.  Used in all-blocks mode.  */
   vector blocks;
@@ -533,14 +533,14 @@ static void read_graph_file (void);
 static int read_count_file (void);
 static void solve_flow_graph (function_info *);
 static void find_exception_blocks (function_info *);
-static void add_branch_counts (coverage_t *, const arc_t *);
+static void add_branch_counts (coverage_t *, const arc_info *);
 static void add_line_counts (coverage_t *, function_info *);
 static void executed_summary (unsigned, unsigned);
 static void function_summary (const coverage_t *, const char *);
 static const char *format_gcov (gcov_type, gcov_type, int);
 static void accumulate_line_counts (source_info *);
 static void output_gcov_file (const char *, source_info *);
-static int output_branch_count (FILE *, int, const arc_t *);
+static int output_branch_count (FILE *, int, const arc_info *);
 static void output_lines (FILE *, const source_info *);
 static char *make_gcov_file_name (const char *, const char *);
 static char *mangle_name (const char *, char *);
@@ -559,7 +559,7 @@ function_info::~function_info ()
 {
   for (int i = blocks.size () - 1; i >= 0; i--)
 {
-  arc_t *arc, *arc_n;
+  arc_info *arc, *arc_n;
 
   for (arc = blocks[i].succ; arc; arc = arc_n)
{
@@ -589,7 +589,7 @@ bool function_info::group_line_p (unsigned n, unsigned 
src_idx)
simple paths)--the node is unblocked only when it participates in a cycle.
*/
 
-typedef vector arc_vector_t;
+typedef vector arc_vector_t;
 typedef vector block_vector_t;
 
 /* Enum with types of loop in CFG.  */
@@ -671,7 +671,7 @@ circuit (block_t *v, arc_vector_t &path, block_t *start,
   blocked.push_back (v);
   block_lists.push_back (block_vector_t ());
 
-  for (arc_t *arc = v->succ; arc; arc = arc->succ_next)
+  for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
 {
   block_t *w = arc->dst;
   if (w < start || !linfo.has_block (w))
@@ -690,7 +690,7 @@ circuit (block_t *v, arc_vector_t &path, block_t *start,
   if (result != NO_LOOP)
 unblock (v, blocked, block_lists);
   else
-for (arc_t *arc = v->succ; arc; arc = arc->succ_next)
+for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
   {
block_t *w = arc->dst;
if (w < start || !linfo.has_block (w))
@@ -960,7 +960,7 @@ output_intermediate_line (FILE *f, line_info *line, 
unsigned line_num)
   format_gcov (line->count, 0, -1),
   line->has_unexecuted_block);
 
-  vector::const_iterator it;
+  vector::const_iterator it;
   if (flag_branches)
 for (it = line->branches.begin (); it != line->branches.end ();
 it++)
@@ -1563,7 +1563,7 @@ read_graph_file (void)
 
  if (dest >= fn->blocks.size ())
goto corrupt;
- arc = XCNEW (arc_t);
+ arc = XCNEW (arc_info);
 
  arc->dst = &fn->blocks[dest];
  arc->src = src_blk;
@@ -1782,7 +1782,7 @@ static

[PATCH 3/7] GCOV: introduce vector for function_info::counts.

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (function_info::function_info): Remove num_counts
and add vector.
(function_info::~function_info): Use the vector.
(process_file): Likewise.
(read_graph_file): Likewise.
(read_count_file): Likewise.
(solve_flow_graph): Likewise.
---
 gcc/gcov.c | 21 -
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 3dc159726c7..02a01b51763 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -257,8 +257,7 @@ typedef struct function_info
   unsigned blocks_executed;
 
   /* Raw arc coverage counts.  */
-  gcov_type *counts;
-  unsigned num_counts;
+  vector counts;
 
   /* First line number.  */
   unsigned start_line;
@@ -551,8 +550,8 @@ extern int main (int, char **);
 function_info::function_info (): name (NULL), demangled_name (NULL),
   ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
   artificial (0), is_group (0),
-  blocks (), blocks_executed (0), counts (NULL), num_counts (0),
-  start_line (0), start_column (0), end_line (0), src (0), lines (), next 
(NULL)
+  blocks (), blocks_executed (0), counts (),
+  start_line (0), start_column (), end_line (0), src (0), lines (), next (NULL)
 {
 }
 
@@ -568,7 +567,6 @@ function_info::~function_info ()
  free (arc);
}
 }
-  free (counts);
   if (flag_demangled_names && demangled_name != name)
 free (demangled_name);
   free (name);
@@ -1140,7 +1138,7 @@ process_file (const char *file_name)
   function_t *fn = *it;
   unsigned src = fn->src;
 
-  if (fn->counts || no_data_file)
+  if (!fn->counts.empty () || no_data_file)
{
  source_info *s = &sources[src];
  s->functions.push_back (fn);
@@ -1604,7 +1602,7 @@ read_graph_file (void)
}
 
  if (!arc->on_tree)
-   fn->num_counts++;
+   fn->counts.push_back (0);
}
 
  if (mark_catches)
@@ -1755,13 +1753,10 @@ read_count_file (void)
}
   else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
{
- if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
+ if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
goto mismatch;
 
- if (!fn->counts)
-   fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
-
- for (ix = 0; ix != fn->num_counts; ix++)
+ for (ix = 0; ix != fn->counts.size (); ix++)
fn->counts[ix] += gcov_read_counter ();
}
   gcov_sync (base, length);
@@ -1788,7 +1783,7 @@ solve_flow_graph (function_t *fn)
 {
   unsigned ix;
   arc_t *arc;
-  gcov_type *count_ptr = fn->counts;
+  gcov_type *count_ptr = &fn->counts.front ();
   block_t *blk;
   block_t *valid_blocks = NULL;/* valid, but unpropagated blocks.  */
   block_t *invalid_blocks = NULL;  /* invalid, but inferable blocks.  */
-- 
2.14.3




[PATCH 7/7] GCOV: remove typedef of coverage_t.

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (struct coverage_info): Remove typedef of coverage_t.
(struct source_info): Likewise.
(add_branch_counts): Likewise.
(add_line_counts): Likewise.
(function_summary): Likewise.
(output_intermediate_line): Likewise.
(generate_results): Likewise.
---
 gcc/gcov.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 0e5ae8110ad..0669fd9deab 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -294,7 +294,7 @@ struct function_line_start_cmp
 
 /* Describes coverage of a file or function.  */
 
-typedef struct coverage_info
+struct coverage_info
 {
   int lines;
   int lines_executed;
@@ -307,7 +307,7 @@ typedef struct coverage_info
   int calls_executed;
 
   char *name;
-} coverage_t;
+};
 
 /* Describes a file mentioned in the block graph.  Contains an array
of line info.  */
@@ -329,7 +329,7 @@ struct source_info
   /* Vector of line information.  */
   vector lines;
 
-  coverage_t coverage;
+  coverage_info coverage;
 
   /* Functions in this source file.  These are in ascending line
  number order.  */
@@ -533,10 +533,10 @@ static void read_graph_file (void);
 static int read_count_file (void);
 static void solve_flow_graph (function_info *);
 static void find_exception_blocks (function_info *);
-static void add_branch_counts (coverage_t *, const arc_info *);
-static void add_line_counts (coverage_t *, function_info *);
+static void add_branch_counts (coverage_info *, const arc_info *);
+static void add_line_counts (coverage_info *, function_info *);
 static void executed_summary (unsigned, unsigned);
-static void function_summary (const coverage_t *, const char *);
+static void function_summary (const coverage_info *, const char *);
 static const char *format_gcov (gcov_type, gcov_type, int);
 static void accumulate_line_counts (source_info *);
 static void output_gcov_file (const char *, source_info *);
@@ -968,8 +968,8 @@ output_intermediate_line (FILE *f, line_info *line, 
unsigned line_num)
if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
  {
const char *branch_type;
-   /* branch:,
-  branch_coverage_type
+   /* branch:,
+  branch_coverage_infoype
   : notexec (Branch not executed)
   : taken (Branch executed and taken)
   : nottaken (Branch executed, but not taken)
@@ -1234,7 +1234,7 @@ generate_results (const char *file_name)
it != functions.end (); it++)
 {
   function_info *fn = *it;
-  coverage_t coverage;
+  coverage_info coverage;
 
   memset (&coverage, 0, sizeof (coverage));
   coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
@@ -2072,7 +2072,7 @@ find_exception_blocks (function_info *fn)
 /* Increment totals in COVERAGE according to arc ARC.  */
 
 static void
-add_branch_counts (coverage_t *coverage, const arc_info *arc)
+add_branch_counts (coverage_info *coverage, const arc_info *arc)
 {
   if (arc->is_call_non_return)
 {
@@ -2184,7 +2184,7 @@ executed_summary (unsigned lines, unsigned executed)
 /* Output summary info for a function or file.  */
 
 static void
-function_summary (const coverage_t *coverage, const char *title)
+function_summary (const coverage_info *coverage, const char *title)
 {
   fnotice (stdout, "%s '%s'\n", title, coverage->name);
   executed_summary (coverage->lines, coverage->lines_executed);
@@ -2421,7 +2421,7 @@ mangle_name (char const *base, char *ptr)
the appropriate basic block.  */
 
 static void
-add_line_counts (coverage_t *coverage, function_info *fn)
+add_line_counts (coverage_info *coverage, function_info *fn)
 {
   bool has_any_line = false;
   /* Scan each basic block.  */
-- 
2.14.3



[PATCH 6/7] GCOV: remove typedef for block_t

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (struct block_info): Remove typedef for block_t.
(struct line_info): Likewise.
(line_info::has_block): Likewise.
(EXIT_BLOCK): Likewise.
(unblock): Likewise.
(circuit): Likewise.
(get_cycles_count): Likewise.
(process_file): Likewise.
(read_graph_file): Likewise.
(solve_flow_graph): Likewise.
(find_exception_blocks): Likewise.
(add_line_counts): Likewise.
(accumulate_line_info): Likewise.
(output_line_details): Likewise.
---
 gcc/gcov.c | 52 ++--
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index e33c7b6f8cd..0e5ae8110ad 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -131,7 +131,7 @@ struct block_location_info
 /* Describes a basic block. Contains lists of arcs to successor and
predecessor blocks.  */
 
-typedef struct block_info
+struct block_info
 {
   /* Constructor.  */
   block_info ();
@@ -175,7 +175,7 @@ typedef struct block_info
  line.  */
   struct block_info *chain;
 
-} block_t;
+};
 
 block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred 
(0),
   id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
@@ -194,7 +194,7 @@ struct line_info
   line_info ();
 
   /* Return true when NEEDLE is one of basic blocks the line belongs to.  */
-  bool has_block (block_t *needle);
+  bool has_block (block_info *needle);
 
   /* Execution count.  */
   gcov_type count;
@@ -203,7 +203,7 @@ struct line_info
   vector branches;
 
   /* blocks which start on this line.  Used in all-blocks mode.  */
-  vector blocks;
+  vector blocks;
 
   unsigned exists : 1;
   unsigned unexceptional : 1;
@@ -216,7 +216,7 @@ line_info::line_info (): count (0), branches (), blocks (), 
exists (false),
 }
 
 bool
-line_info::has_block (block_t *needle)
+line_info::has_block (block_info *needle)
 {
   return std::find (blocks.begin (), blocks.end (), needle) != blocks.end ();
 }
@@ -253,7 +253,7 @@ struct function_info
  at blocks[0] and the exit block is at blocks[1].  */
 #define ENTRY_BLOCK (0)
 #define EXIT_BLOCK (1)
-  vector blocks;
+  vector blocks;
   unsigned blocks_executed;
 
   /* Raw arc coverage counts.  */
@@ -590,7 +590,7 @@ bool function_info::group_line_p (unsigned n, unsigned 
src_idx)
*/
 
 typedef vector arc_vector_t;
-typedef vector block_vector_t;
+typedef vector block_vector_t;
 
 /* Enum with types of loop in CFG.  */
 
@@ -635,7 +635,7 @@ handle_cycle (const arc_vector_t &edges, int64_t &count)
blocked by U in BLOCK_LISTS.  */
 
 static void
-unblock (const block_t *u, block_vector_t &blocked,
+unblock (const block_info *u, block_vector_t &blocked,
 vector &block_lists)
 {
   block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
@@ -660,7 +660,7 @@ unblock (const block_t *u, block_vector_t &blocked,
Returns what type of loop it contains.  */
 
 static loop_type
-circuit (block_t *v, arc_vector_t &path, block_t *start,
+circuit (block_info *v, arc_vector_t &path, block_info *start,
 block_vector_t &blocked, vector &block_lists,
 line_info &linfo, int64_t &count)
 {
@@ -673,7 +673,7 @@ circuit (block_t *v, arc_vector_t &path, block_t *start,
 
   for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
 {
-  block_t *w = arc->dst;
+  block_info *w = arc->dst;
   if (w < start || !linfo.has_block (w))
continue;
 
@@ -692,7 +692,7 @@ circuit (block_t *v, arc_vector_t &path, block_t *start,
   else
 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
   {
-   block_t *w = arc->dst;
+   block_info *w = arc->dst;
if (w < start || !linfo.has_block (w))
  continue;
 
@@ -721,7 +721,7 @@ get_cycles_count (line_info &linfo, bool 
handle_negative_cycles = true)
 
   loop_type result = NO_LOOP;
   gcov_type count = 0;
-  for (vector::iterator it = linfo.blocks.begin ();
+  for (vector::iterator it = linfo.blocks.begin ();
it != linfo.blocks.end (); it++)
 {
   arc_vector_t path;
@@ -1147,7 +1147,7 @@ process_file (const char *file_name)
  for (unsigned block_no = 0; block_no != fn->blocks.size ();
   block_no++)
{
- block_t *block = &fn->blocks[block_no];
+ block_info *block = &fn->blocks[block_no];
  for (unsigned i = 0; i < block->locations.size (); i++)
{
  /* Sort lines of locations.  */
@@ -1549,7 +1549,7 @@ read_graph_file (void)
  unsigned src = gcov_read_unsigned ();
  fn->blocks[src].id = src;
  unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
- block_t *src_blk = &fn->blocks[src];
+ block_info *src_blk = &fn->blocks[src];
  unsigned mark_catches = 0;
  struct arc_info *arc;
 
@@ -1622,7 +1622,7 @@ read_graph_file (void)

[PATCH 4/7] GCOV: remove typedef for function_t

2017-11-09 Thread marxin
gcc/ChangeLog:

2017-11-09  Martin Liska  

* gcov.c (struct function_info): Remove typedef for function_t.
(struct source_info): Likewise.
(source_info::get_functions_at_location): Likewise.
(solve_flow_graph): Likewise.
(find_exception_blocks): Likewise.
(add_line_counts): Likewise.
(output_intermediate_file): Likewise.
(process_file): Likewise.
(generate_results): Likewise.
(release_structures): Likewise.
(read_graph_file): Likewise.
(read_count_file): Likewise.
(accumulate_line_counts): Likewise.
(output_lines): Likewise.
---
 gcc/gcov.c | 70 +++---
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 02a01b51763..a1c489bccdc 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -223,7 +223,7 @@ line_info::has_block (block_t *needle)
 
 /* Describes a single function. Contains an array of basic blocks.  */
 
-typedef struct function_info
+struct function_info
 {
   function_info ();
   ~function_info ();
@@ -276,7 +276,7 @@ typedef struct function_info
 
   /* Next function.  */
   struct function_info *next;
-} function_t;
+};
 
 /* Function info comparer that will sort functions according to starting
line.  */
@@ -317,7 +317,7 @@ struct source_info
   /* Default constructor.  */
   source_info ();
 
-  vector get_functions_at_location (unsigned line_num) const;
+  vector get_functions_at_location (unsigned line_num) const;
 
   /* Index of the source_info in sources vector.  */
   unsigned index;
@@ -333,7 +333,7 @@ struct source_info
 
   /* Functions in this source file.  These are in ascending line
  number order.  */
-  vector  functions;
+  vector  functions;
 };
 
 source_info::source_info (): index (0), name (NULL), file_time (),
@@ -341,12 +341,12 @@ source_info::source_info (): index (0), name (NULL), 
file_time (),
 {
 }
 
-vector
+vector
 source_info::get_functions_at_location (unsigned line_num) const
 {
-  vector r;
+  vector r;
 
-  for (vector::const_iterator it = functions.begin ();
+  for (vector::const_iterator it = functions.begin ();
it != functions.end (); it++)
 {
   if ((*it)->start_line == line_num && (*it)->src == index)
@@ -392,7 +392,7 @@ public:
 };
 
 /* Vector of all functions.  */
-static vector functions;
+static vector functions;
 
 /* Vector of source files.  */
 static vector sources;
@@ -531,10 +531,10 @@ static char *canonicalize_name (const char *);
 static unsigned find_source (const char *);
 static void read_graph_file (void);
 static int read_count_file (void);
-static void solve_flow_graph (function_t *);
-static void find_exception_blocks (function_t *);
+static void solve_flow_graph (function_info *);
+static void find_exception_blocks (function_info *);
 static void add_branch_counts (coverage_t *, const arc_t *);
-static void add_line_counts (coverage_t *, function_t *);
+static void add_line_counts (coverage_t *, function_info *);
 static void executed_summary (unsigned, unsigned);
 static void function_summary (const coverage_t *, const char *);
 static const char *format_gcov (gcov_type, gcov_type, int);
@@ -1001,7 +1001,7 @@ output_intermediate_file (FILE *gcov_file, source_info 
*src)
 
   std::sort (src->functions.begin (), src->functions.end (),
 function_line_start_cmp ());
-  for (vector::iterator it = src->functions.begin ();
+  for (vector::iterator it = src->functions.begin ();
it != src->functions.end (); it++)
 {
   /* function:,, */
@@ -1012,10 +1012,10 @@ output_intermediate_file (FILE *gcov_file, source_info 
*src)
 
   for (unsigned line_num = 0; line_num <= src->lines.size (); line_num++)
 {
-  vector fns = src->get_functions_at_location (line_num);
+  vector fns = src->get_functions_at_location (line_num);
 
   /* Print first group functions that begin on the line.  */
-  for (vector::iterator it2 = fns.begin ();
+  for (vector::iterator it2 = fns.begin ();
   it2 != fns.end (); it2++)
{
  vector &lines = (*it2)->lines;
@@ -1106,10 +1106,10 @@ process_file (const char *file_name)
 
   read_count_file ();
 
-  hash_map fn_map;
+  hash_map fn_map;
 
   /* Identify group functions.  */
-  for (vector::iterator it = functions.begin ();
+  for (vector::iterator it = functions.begin ();
it != functions.end (); it++)
 if (!(*it)->artificial)
   {
@@ -1117,7 +1117,7 @@ process_file (const char *file_name)
needle.source_file_idx = (*it)->src;
needle.start_line = (*it)->start_line;
 
-   function_t **slot = fn_map.get (needle);
+   function_info **slot = fn_map.get (needle);
if (slot)
  {
gcc_assert ((*slot)->end_line == (*it)->end_line);
@@ -1132,10 +1132,10 @@ process_file (const char *file_name)
   functions.erase (remove_if (functions.begin (), functions.end (),
 

[PATCH 4/4] Change default for jump_table expansion ratio to 8.

2018-06-08 Thread marxin

gcc/ChangeLog:

2018-06-07  Martin Liska  

* tree-switch-conversion.c (jump_table_cluster::can_be_handled):
Change default ratio from 10 to 8.
---
 gcc/tree-switch-conversion.c | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 60181542bcc..5573f50d59f 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1075,17 +1075,11 @@ jump_table_cluster::can_be_handled (const vec &clusters,
  make a sequence of conditional branches instead of a dispatch.
 
  The definition of "much bigger" depends on whether we are
- optimizing for size or for speed.  If the former, the maximum
- ratio range/count = 3, because this was found to be the optimal
- ratio for size on i686-pc-linux-gnu, see PR11823.  The ratio
- 10 is much older, and was probably selected after an extensive
- benchmarking investigation on numerous platforms.  Or maybe it
- just made sense to someone at some point in the history of GCC,
- who knows...  */
+ optimizing for size or for speed.  */
   if (!flag_jump_tables)
 return false;
 
-  unsigned HOST_WIDE_INT max_ratio = optimize_insn_for_size_p () ? 3 : 10;
+  unsigned HOST_WIDE_INT max_ratio = optimize_insn_for_size_p () ? 3 : 8;
 
   unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (),
 	clusters[end]->get_high ());


[PATCH 0/4][v2] Implement smart multiple switch expansion algorithms

2018-06-08 Thread marxin
4-mine
BENCHMARK: /tmp/before/sphinx_livepretend_peak.amd64-m64-mine
  +0.0% +32 .text   +32  +0.0%
  -0.3% -64 .rodata -64  -0.3%
  -0.0% -32 TOTAL   -48  -0.0%
BENCHMARK: /tmp/before/tonto_peak.amd64-m64-mine
  +0.2%+928 .rodata  +928  +0.2%
  -0.0%-176 .text-176  -0.0%
  +0.0%+760 TOTAL+832  +0.0%
BENCHMARK: /tmp/before/wrf_peak.amd64-m64-mine
  +0.2%+608 .rodata  +608  +0.2%
  -0.0%-608 .text-608  -0.0%
  +0.0% +24 TOTAL-272  -0.0%
BENCHMARK: /tmp/before/Xalan_peak.amd64-m64-mine
  +0.3% +2.06Ki .rodata   +2.06Ki  +0.3%
  -0.0%-496 .text-496  -0.0%
  +0.0% +1.60Ki TOTAL +1.11Ki  +0.0%
BENCHMARK: /tmp/before/zeusmp_peak.amd64-m64-mine

Which gives us very similar numbers.

3) http://natsys-lab.blogspot.com/
https://github.com/natsys/blog

It's a HTTP request parser benchmark. There are some nice new jump tables
created:

http_ngx.c.167t.switchlower1:;; GIMPLE switch case clusters: 0 10 13 JT:97-105 

which is a switch that handles 'a' - 'z', plus 0, 10, 13. JT is created for
alphabet characters. I can also measure benchmark changes:

++++-+
| https://github.com/natsys/blog |  base  | Gcc 9  |  ratio  |
++++-+
| goto_big_header_line   | 244.22 | 202.62 | 82.97%  |
| goto_header_line   | 119.06 | 118.58 | 99.60%  |
| goto_opt_request_line  | 172.97 | 156.39 | 90.41%  |
| goto_request_line  | 201.47 | 159.29 | 79.06%  |
| hsm_header_line| 283.14 | 282.16 | 99.65%  |
| ngx_big_header_line| 755.11 | 683.98 | 90.58%  |
| ngx_header_line|  84.85 |  84.46 | 99.54%  |
| ngx_lw_header_line |  96.61 |  95.98 | 99.35%  |
| ngx_request_line   |  141.9 | 184.47 | 130.00% |
| tbl_big_header_line| 414.59 | 359.58 | 86.73%  |
| tbl_header_line| 206.87 | 205.71 | 99.44%  |
++++-+

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Thoughts?
Martin

marxin (4):
  Transform switch_conversion into a class.
  Switch other switch expansion methods into classes.
  Enable clustering for switch statements.
  Change default for jump_table expansion ratio to 8.

 gcc/testsuite/gcc.dg/tree-ssa/vrp104.c |2 +-
 gcc/tree-switch-conversion.c   | 2518 +++-
 gcc/tree-switch-conversion.h   |  845 
 3 files changed, 1941 insertions(+), 1424 deletions(-)
 create mode 100644 gcc/tree-switch-conversion.h

-- 
2.17.0



[PATCH 3/4] Enable clustering for switch statements.

2018-06-08 Thread marxin

gcc/ChangeLog:

2018-06-07  Martin Liska  

* tree-switch-conversion.c (jump_table_cluster::find_jump_tables):
New.
(bit_test_cluster::find_bit_tests): Likewise.
(switch_decision_tree::analyze_switch_statement): Find clusters.
* tree-switch-conversion.h (struct jump_table_cluster): Document
hierarchy.
---
 gcc/tree-switch-conversion.c | 170 +++
 gcc/tree-switch-conversion.h |  19 +++-
 2 files changed, 169 insertions(+), 20 deletions(-)

diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 8f3dc8fd8a4..60181542bcc 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1004,6 +1004,64 @@ jump_table_cluster::emit (tree index_expr, tree,
   gsi_insert_after (&gsi, s, GSI_NEW_STMT);
 }
 
+vec
+jump_table_cluster::find_jump_tables (vec &clusters)
+{
+  unsigned l = clusters.length ();
+  auto_vec min;
+  min.reserve (l + 1);
+
+  min.quick_push (min_cluster_item (0, 0, 0));
+
+  for (unsigned i = 1; i <= l; i++)
+{
+  /* Set minimal # of clusters with i-th item to infinite.  */
+  min.quick_push (min_cluster_item (INT_MAX, INT_MAX, INT_MAX));
+
+  for (unsigned j = 0; j < i; j++)
+	{
+	  unsigned HOST_WIDE_INT s = min[j].m_non_jt_cases;
+	  if (i - j < case_values_threshold ())
+	s += i - j;
+
+	  /* Prefer clusters with smaller number of numbers covered.  */
+	  if ((min[j].m_count + 1 < min[i].m_count
+	   || (min[j].m_count + 1 == min[i].m_count
+		   && s < min[i].m_non_jt_cases))
+	  && can_be_handled (clusters, j, i - 1))
+	min[i] = min_cluster_item (min[j].m_count + 1, j, s);
+	}
+}
+
+  /* No result.  */
+  if (min[l].m_count == INT_MAX)
+return clusters.copy ();
+
+  vec output;
+  output.create (4);
+
+  /* Find and build the clusters.  */
+  for (int end = l;;)
+{
+  int start = min[end].m_start;
+
+  /* Do not allow clusters with small number of cases.  */
+  if (is_beneficial (clusters, start, end - 1))
+	output.safe_push (new jump_table_cluster (clusters, start, end - 1));
+  else
+	for (int i = end - 1; i >= start; i--)
+	  output.safe_push (clusters[i]);
+
+  end = start;
+
+  if (start <= 0)
+	break;
+}
+
+  output.reverse ();
+  return output;
+}
+
 bool
 jump_table_cluster::can_be_handled (const vec &clusters,
 unsigned start, unsigned end)
@@ -1052,6 +1110,56 @@ jump_table_cluster::is_beneficial (const vec &,
   return end - start + 1 >= case_values_threshold ();
 }
 
+vec
+bit_test_cluster::find_bit_tests (vec &clusters)
+{
+  vec output;
+  output.create (4);
+
+  unsigned l = clusters.length ();
+  auto_vec min;
+  min.reserve (l + 1);
+
+  min.quick_push (min_cluster_item (0, 0, 0));
+
+  for (unsigned i = 1; i <= l; i++)
+{
+  /* Set minimal # of clusters with i-th item to infinite.  */
+  min.quick_push (min_cluster_item (INT_MAX, INT_MAX, INT_MAX));
+
+  for (unsigned j = 0; j < i; j++)
+	{
+	  if (min[j].m_count + 1 < min[i].m_count
+	  && can_be_handled (clusters, j, i - 1))
+	min[i] = min_cluster_item (min[j].m_count + 1, j, INT_MAX);
+	}
+}
+
+  /* No result.  */
+  if (min[l].m_count == INT_MAX)
+return clusters.copy ();
+
+  /* Find and build the clusters.  */
+  for (int end = l;;)
+{
+  int start = min[end].m_start;
+
+  if (is_beneficial (clusters, start, end - 1))
+	output.safe_push (new bit_test_cluster (clusters, start, end - 1));
+  else
+	for (int i = end - 1; i >=  start; i--)
+	  output.safe_push (clusters[i]);
+
+  end = start;
+
+  if (start <= 0)
+	break;
+}
+
+  output.reverse ();
+  return output;
+}
+
 bool
 bit_test_cluster::can_be_handled (unsigned HOST_WIDE_INT range,
   unsigned int uniq)
@@ -1343,33 +1451,57 @@ switch_decision_tree::analyze_switch_statement ()
 
   reset_out_edges_aux ();
 
-  vec output;
-  output.create (1);
-
-  /* Find whether the switch statement can be expanded with a method
- different from decision tree.  */
-  unsigned end = clusters.length () - 1;
-  if (jump_table_cluster::can_be_handled (clusters, 0, end)
-  && jump_table_cluster::is_beneficial (clusters, 0, end))
-output.safe_push (new jump_table_cluster (clusters, 0, end));
-  else if (bit_test_cluster::can_be_handled (clusters, 0, end)
-	   && bit_test_cluster::is_beneficial (clusters, 0, end))
-output.safe_push (new bit_test_cluster (clusters, 0, end));
-  else
-output = clusters;
+  /* Find jump table clusters.  */
+  vec output = jump_table_cluster::find_jump_tables (clusters);
+
+  /* Find jump table clusters.  */
+  vec output2;
+  auto_vec tmp;
+  output2.create (1);
+  tmp.create (1);
+
+  for (unsigned i = 0; i < output.length (); i++)
+{
+  cluster *c = output[i];
+  if (c->get_type () != SIMPLE_CASE)
+	{
+	  if (!tmp.is_empty ())
+	{
+	  vec n = bit_test_cluster::find_bit_tests (tmp);
+	  output2.safe_splice (n);
+	  n.release ();
+	  tmp.trunc

[PATCH 2/4] Switch other switch expansion methods into classes.

2018-06-08 Thread marxin

gcc/ChangeLog:

2018-06-07  Martin Liska  

* tree-switch-conversion.c (switch_conversion::collect):
Record m_uniq property.
(switch_conversion::expand): Bail out for special conditions.
(group_cluster::~group_cluster): New.
(group_cluster::group_cluster): Likewise.
(group_cluster::dump): Likewise.
(jump_table_cluster::emit): New.
(switch_decision_tree::fix_phi_operands_for_edges): New.
(struct case_node): Remove struct.
(jump_table_cluster::can_be_handled): New.
(case_values_threshold): Moved to header.
(reset_out_edges_aux): Likewise.
(jump_table_cluster::is_beneficial): New.
(bit_test_cluster::can_be_handled): Likewise.
(add_case_node): Remove.
(bit_test_cluster::is_beneficial): New.
(case_bit_test::cmp): New.
(bit_test_cluster::emit): New.
(expand_switch_as_decision_tree_p): Remove.
(bit_test_cluster::hoist_edge_and_branch_if_true): New.
(fix_phi_operands_for_edge): Likewise.
(switch_decision_tree::analyze_switch_statement): New.
(compute_cases_per_edge): Move ...
(switch_decision_tree::compute_cases_per_edge): ... here.
(try_switch_expansion): Likewise.
(switch_decision_tree::try_switch_expansion): Likewise.
(record_phi_operand_mapping): Likewise.
(switch_decision_tree::record_phi_operand_mapping): Likewise.
(emit_case_decision_tree): Likewise.
(switch_decision_tree::emit): Likewise.
(balance_case_nodes): Likewise.
(switch_decision_tree::balance_case_nodes): Likewise.
(dump_case_nodes): Likewise.
(switch_decision_tree::dump_case_nodes): Likewise.
(emit_jump): Likewise.
(switch_decision_tree::emit_jump): Likewise.
(emit_cmp_and_jump_insns): Likewise.
(switch_decision_tree::emit_cmp_and_jump_insns): Likewise.
(emit_case_nodes): Likewise.
(switch_decision_tree::emit_case_nodes): Likewise.
(conditional_probability): Remove.
* tree-switch-conversion.h (enum cluster_type): New.
(PRINT_CASE): New.
(struct cluster): Likewise.
(cluster::cluster): Likewise.
(struct simple_cluster): Likewise.
(simple_cluster::simple_cluster): Likewise.
(struct group_cluster): Likewise.
(struct jump_table_cluster): Likewise.
(struct bit_test_cluster): Likewise.
(struct min_cluster_item): Likewise.
(struct case_tree_node): Likewise.
(case_tree_node::case_tree_node): Likewise.
(jump_table_cluster::case_values_threshold): Likewise.
(struct case_bit_test): Likewise.
(struct switch_decision_tree): Likewise.
(struct switch_conversion): Likewise.
(switch_decision_tree::reset_out_edges_aux): Likewise.

gcc/testsuite/ChangeLog:

2018-06-07  Martin Liska  

* gcc.dg/tree-ssa/vrp104.c: Grep just for GIMPLE IL.
---
 gcc/testsuite/gcc.dg/tree-ssa/vrp104.c |2 +-
 gcc/tree-switch-conversion.c   | 1343 ++--
 gcc/tree-switch-conversion.h   |  545 ++
 3 files changed, 1325 insertions(+), 565 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp104.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp104.c
index 71fa3bfa2ca..1bef76f1a21 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp104.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp104.c
@@ -2,7 +2,7 @@
 /* { dg-options "-O2 -fdump-tree-switchlower" }  */
 /* We scan for 2 switches as the dump file reports a transformation,
IL really contains just a single.  */
-/* { dg-final { scan-tree-dump-times "switch" 2 "switchlower1" } }  */
+/* { dg-final { scan-tree-dump-times "switch \\(" 2 "switchlower1" } }  */
 
 void foo (void);
 void bar (void);
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 2f848fcb6aa..8f3dc8fd8a4 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -175,6 +175,11 @@ switch_conversion::collect (gswitch *swtch)
 	  && ! tree_int_cst_equal (CASE_LOW (elt), CASE_HIGH (elt)))
 	m_count++;
 }
+
+  /* Get the number of unique non-default targets out of the GIMPLE_SWITCH
+ block.  Assume a CFG cleanup would have already removed degenerate
+ switch statements, this allows us to just use EDGE_COUNT.  */
+  m_uniq = EDGE_COUNT (gimple_bb (swtch)->succs) - 1;
 }
 
 bool
@@ -861,6 +866,22 @@ switch_conversion::expand (gswitch *swtch)
   /* A switch on a constant should have been optimized in tree-cfg-cleanup.  */
   gcc_checking_assert (!TREE_CONSTANT (m_index_expr));
 
+  /* Prefer bit test if possible.  */
+  if (tree_fits_uhwi_p (m_range_size)
+  && bit_test_cluster::can_be_handled (tree_to_uhwi (m_range_size), m_uniq)
+  && bit_test_cluster::is_beneficial (m_count, m_uniq))
+{
+  m_reason = "expanding as bit test is preferable";
+  return;
+}
+
+  if (m_uniq <= 2)
+{
+  /* This will be ex

[PATCH 1/4] Transform switch_conversion into a class.

2018-06-08 Thread marxin

gcc/ChangeLog:

2018-06-07  Martin Liska  

* tree-switch-conversion.c (MAX_CASE_BIT_TESTS): Remove.
(hoist_edge_and_branch_if_true): Likewise.
(expand_switch_using_bit_tests_p): Likewise.
(struct case_bit_test): Likewise.
(case_bit_test_cmp): Likewise.
(emit_case_bit_tests): Likewise.
(switch_conversion::switch_conversion): New class.
(struct switch_conv_info): Remove old struct.
(collect_switch_conv_info): More to ...
(switch_conversion::collect): ... this.
(check_range): Likewise.
(switch_conversion::check_range): Likewise.
(check_all_empty_except_final): Likewise.
(switch_conversion::check_all_empty_except_final): Likewise.
(check_final_bb): Likewise.
(switch_conversion::check_final_bb): Likewise.
(create_temp_arrays): Likewise.
(switch_conversion::create_temp_arrays): Likewise.
(free_temp_arrays): Likewise.
(gather_default_values): Likewise.
(switch_conversion::gather_default_values): Likewise.
(build_constructors): Likewise.
(switch_conversion::build_constructors): Likewise.
(constructor_contains_same_values_p): Likewise.
(switch_conversion::contains_same_values_p): Likewise.
(array_value_type): Likewise.
(switch_conversion::array_value_type): Likewise.
(build_one_array): Likewise.
(switch_conversion::build_one_array): Likewise.
(build_arrays): Likewise.
(switch_conversion::build_arrays): Likewise.
(gen_def_assigns): Likewise.
(switch_conversion::gen_def_assigns): Likewise.
(prune_bbs): Likewise.
(switch_conversion::prune_bbs): Likewise.
(fix_phi_nodes): Likewise.
(switch_conversion::fix_phi_nodes): Likewise.
(gen_inbound_check): Likewise.
(switch_conversion::gen_inbound_check): Likewise.
(process_switch): Use the newly created class.
(switch_conversion::expand): New.
(switch_conversion::~switch_conversion): New.
* tree-switch-conversion.h: New file.
---
 gcc/tree-switch-conversion.c | 1125 +++---
 gcc/tree-switch-conversion.h |  283 +
 2 files changed, 511 insertions(+), 897 deletions(-)
 create mode 100644 gcc/tree-switch-conversion.h

diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index dc60b34f506..2f848fcb6aa 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -55,626 +55,74 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
type in the GIMPLE type system that is language-independent?  */
 #include "langhooks.h"
 
+#include "tree-switch-conversion.h"
 
-/* Maximum number of case bit tests.
-   FIXME: This should be derived from PARAM_CASE_VALUES_THRESHOLD and
-	  targetm.case_values_threshold(), or be its own param.  */
-#define MAX_CASE_BIT_TESTS  3
-
-/* Track whether or not we have altered the CFG and thus may need to
-   cleanup the CFG when complete.  */
-bool cfg_altered;
-
-/* Split the basic block at the statement pointed to by GSIP, and insert
-   a branch to the target basic block of E_TRUE conditional on tree
-   expression COND.
-
-   It is assumed that there is already an edge from the to-be-split
-   basic block to E_TRUE->dest block.  This edge is removed, and the
-   profile information on the edge is re-used for the new conditional
-   jump.
-   
-   The CFG is updated.  The dominator tree will not be valid after
-   this transformation, but the immediate dominators are updated if
-   UPDATE_DOMINATORS is true.
-   
-   Returns the newly created basic block.  */
+using namespace tree_switch_conversion;
 
-static basic_block
-hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
-			   tree cond, edge e_true,
-			   bool update_dominators)
-{
-  tree tmp;
-  gcond *cond_stmt;
-  edge e_false;
-  basic_block new_bb, split_bb = gsi_bb (*gsip);
-  bool dominated_e_true = false;
-
-  gcc_assert (e_true->src == split_bb);
-
-  if (update_dominators
-  && get_immediate_dominator (CDI_DOMINATORS, e_true->dest) == split_bb)
-dominated_e_true = true;
-
-  tmp = force_gimple_operand_gsi (gsip, cond, /*simple=*/true, NULL,
-  /*before=*/true, GSI_SAME_STMT);
-  cond_stmt = gimple_build_cond_from_tree (tmp, NULL_TREE, NULL_TREE);
-  gsi_insert_before (gsip, cond_stmt, GSI_SAME_STMT);
-
-  e_false = split_block (split_bb, cond_stmt);
-  new_bb = e_false->dest;
-  redirect_edge_pred (e_true, split_bb);
-
-  e_true->flags &= ~EDGE_FALLTHRU;
-  e_true->flags |= EDGE_TRUE_VALUE;
-
-  e_false->flags &= ~EDGE_FALLTHRU;
-  e_false->flags |= EDGE_FALSE_VALUE;
-  e_false->probability = e_true->probability.invert ();
-  new_bb->count = e_false->count ();
-
-  if (update_dominators)
-{
-  if (dominated_e_true)
-	set_immediate_dominator (CDI_DOMINATORS, e_true->dest, split_bb);
-  set_immediate_dominator (CDI_DOMINATORS

[PATCH 1/3] Fix --enable-gather-detailed-mem-stats build.

2018-01-12 Thread marxin
gcc/ChangeLog:

2018-01-11  Martin Liska  

* Makefile.in: As qsort_chk is implemented in vec.c, add
vec.o to linkage of gencfn-macros.
* tree.c (build_new_poly_int_cst): Add CXX_MEM_STAT_INFO as it's
passing the info to record_node_allocation_statistics.
(test_vector_cst_patterns): Add CXX_MEM_STAT_INFO to declaration
and pass the info.
* ggc-common.c (struct ggc_usage): Add operator== and use
it in operator< and compare function.
* mem-stats.h (struct mem_usage): Likewise.
* vec.c (struct vec_usage): Remove operator< and compare
function. Can be simply inherited.
---
 gcc/Makefile.in  |  3 ++-
 gcc/ggc-common.c | 17 -
 gcc/mem-stats.h  | 17 -
 gcc/tree.c   | 37 +++--
 gcc/vec.c| 21 -
 5 files changed, 57 insertions(+), 38 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index fb988cda9d1..f04b8a224c0 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2810,7 +2810,8 @@ genprog = $(genprogerr) check checksum condmd match
 build/genautomata$(build_exeext) : BUILD_LIBS += -lm
 
 build/genrecog$(build_exeext) : build/hash-table.o build/inchash.o
-build/gencfn-macros$(build_exeext) : build/hash-table.o build/ggc-none.o
+build/gencfn-macros$(build_exeext) : build/hash-table.o build/vec.o \
+  build/ggc-none.o
 
 # For stage1 and when cross-compiling use the build libcpp which is
 # built with NLS disabled.  For stage2+ use the host library and
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index d435a4b0175..f83fc136d04 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -836,10 +836,22 @@ struct ggc_usage: public mem_usage
 : mem_usage (allocated, times, peak),
 m_freed (freed), m_collected (collected), m_overhead (overhead) {}
 
+  /* Equality operator.  */
+  inline bool
+  operator== (const ggc_usage &second) const
+  {
+return (get_balance () == second.get_balance ()
+   && m_peak == second.m_peak
+   && m_times == second.m_times);
+  }
+
   /* Comparison operator.  */
   inline bool
   operator< (const ggc_usage &second) const
   {
+if (*this == second)
+  return false;
+
 return (get_balance () == second.get_balance () ?
(m_peak == second.m_peak ? m_times < second.m_times
 : m_peak < second.m_peak)
@@ -926,7 +938,10 @@ struct ggc_usage: public mem_usage
 const mem_pair_t f = *(const mem_pair_t *)first;
 const mem_pair_t s = *(const mem_pair_t *)second;
 
-return (*f.second) < (*s.second);
+if (*f.second == *s.second)
+  return 0;
+
+return *f.second < *s.second ? 1 : -1;
   }
 
   /* Compare rows in final GGC summary dump.  */
diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h
index 00cb2b0aa9c..741c07301d9 100644
--- a/gcc/mem-stats.h
+++ b/gcc/mem-stats.h
@@ -163,10 +163,22 @@ struct mem_usage
  m_instances + second.m_instances);
   }
 
+  /* Equality operator.  */
+  inline bool
+  operator== (const mem_usage &second) const
+  {
+return (m_allocated == second.m_allocated
+   && m_peak == second.m_peak
+   && m_allocated == second.m_allocated);
+  }
+
   /* Comparison operator.  */
   inline bool
   operator< (const mem_usage &second) const
   {
+if (*this == second)
+  return false;
+
 return (m_allocated == second.m_allocated ?
(m_peak == second.m_peak ? m_times < second.m_times
 : m_peak < second.m_peak) : m_allocated < second.m_allocated);
@@ -181,7 +193,10 @@ struct mem_usage
 const mem_pair_t f = *(const mem_pair_t *)first;
 const mem_pair_t s = *(const mem_pair_t *)second;
 
-return (*f.second) < (*s.second);
+if (*f.second == *s.second)
+  return 0;
+
+return *f.second < *s.second ? 1 : -1;
   }
 
   /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
diff --git a/gcc/tree.c b/gcc/tree.c
index bed59d33bb2..722ce021b67 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1332,7 +1332,8 @@ build_new_int_cst (tree type, const wide_int &cst)
 /* Return a new POLY_INT_CST with coefficients COEFFS and type TYPE.  */
 
 static tree
-build_new_poly_int_cst (tree type, tree (&coeffs)[NUM_POLY_INT_COEFFS])
+build_new_poly_int_cst (tree type, tree (&coeffs)[NUM_POLY_INT_COEFFS]
+   CXX_MEM_STAT_INFO)
 {
   size_t length = sizeof (struct tree_poly_int_cst);
   record_node_allocation_statistics (POLY_INT_CST, length);
@@ -14429,7 +14430,7 @@ check_vector_cst_stepped (vec expected, tree 
actual,
 /* Test the creation of VECTOR_CSTs.  */
 
 static void
-test_vector_cst_patterns ()
+test_vector_cst_patterns (ALONE_CXX_MEM_STAT_INFO)
 {
   auto_vec elements (8);
   elements.quick_grow (8);
@@ -14440,24 +14441,28 @@ test_vector_cst_patterns ()
  { 0, 1, 2, 3, 4, 5, 6, 7 }.  */
   for (unsigned int i = 0; i < 8; ++i)
 elements[i] = build_int_cst (element_type, i);
-  check_vector_cst_step

[PATCH 0/3] Fix broken --enable-gather-detailed-mem-stats build.

2018-01-12 Thread marxin
Hi.

Due to changes to qsort where Alexander added new implementation in vec.c,
we need to change Makefile.in. Apart from that qsort_chk triggers errors
for current implementation of compare function. That's also fixed.
Last change is usage of uint64_t for allocation stats counting
of GIMPLE statements and trees.

Patch survives --enable-gather-detailed-mem-stats with and without
--enable-checking=release. I'm testing normal bootstrap and testsuite.

Ready after it finishes?
Thanks,
Martin

marxin (3):
  Fix --enable-gather-detailed-mem-stats build.
  Fix integer overflow in stats of trees.
  Fix integer overflow in stats of GIMPLE statements.

 gcc/Makefile.in  |  3 ++-
 gcc/ggc-common.c | 17 -
 gcc/gimple.c | 17 ++---
 gcc/gimple.h |  4 ++--
 gcc/mem-stats.h  | 17 -
 gcc/tree-core.h  |  4 ++--
 gcc/tree.c   | 57 +---
 gcc/vec.c| 21 -
 8 files changed, 82 insertions(+), 58 deletions(-)

-- 
2.14.3



[PATCH 2/3] Fix integer overflow in stats of trees.

2018-01-12 Thread marxin
gcc/ChangeLog:

2018-01-12  Martin Liska  

* tree-core.h: Use uint64_t instead of int.
* tree.c (tree_node_counts): Likewise.
(tree_node_sizes): Likewise.
(dump_tree_statistics): Use PRIu64 in printf format.
---
 gcc/tree-core.h |  4 ++--
 gcc/tree.c  | 20 +++-
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 56acd10a653..478c631998c 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -2123,8 +2123,8 @@ extern GTY(()) tree integer_types[itk_none];
 extern GTY(()) tree sizetype_tab[(int) stk_type_kind_last];
 
 /* Arrays for keeping track of tree node statistics.  */
-extern int tree_node_counts[];
-extern int tree_node_sizes[];
+extern uint64_t tree_node_counts[];
+extern uint64_t tree_node_sizes[];
 
 /* True if we are in gimple form and the actions of the folders need to
be restricted.  False if we are not in gimple form and folding is not
diff --git a/gcc/tree.c b/gcc/tree.c
index 722ce021b67..c008a55804c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -129,9 +129,9 @@ extern int _obstack_allocated_p (struct obstack *h, void 
*obj);
 
 /* Statistics-gathering stuff.  */
 
-static int tree_code_counts[MAX_TREE_CODES];
-int tree_node_counts[(int) all_kinds];
-int tree_node_sizes[(int) all_kinds];
+static uint64_t tree_code_counts[MAX_TREE_CODES];
+uint64_t tree_node_counts[(int) all_kinds];
+uint64_t tree_node_sizes[(int) all_kinds];
 
 /* Keep in sync with tree.h:enum tree_node_kind.  */
 static const char * const tree_node_kind_names[] = {
@@ -9123,25 +9123,27 @@ dump_tree_statistics (void)
   if (GATHER_STATISTICS)
 {
   int i;
-  int total_nodes, total_bytes;
+  uint64_t total_nodes, total_bytes;
   fprintf (stderr, "\nKind   Nodes  Bytes\n");
   mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
   total_nodes = total_bytes = 0;
   for (i = 0; i < (int) all_kinds; i++)
{
- fprintf (stderr, "%-20s %7d %10d\n", tree_node_kind_names[i],
-  tree_node_counts[i], tree_node_sizes[i]);
+ fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n",
+  tree_node_kind_names[i], tree_node_counts[i],
+  tree_node_sizes[i]);
  total_nodes += tree_node_counts[i];
  total_bytes += tree_node_sizes[i];
}
   mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
-  fprintf (stderr, "%-20s %7d %10d\n", "Total", total_nodes, total_bytes);
+  fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n", "Total",
+  total_nodes, total_bytes);
   mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
   fprintf (stderr, "Code   Nodes\n");
   mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
   for (i = 0; i < (int) MAX_TREE_CODES; i++)
-   fprintf (stderr, "%-32s %7d\n", get_tree_code_name ((enum tree_code) i),
- tree_code_counts[i]);
+   fprintf (stderr, "%-32s %7" PRIu64 "\n",
+get_tree_code_name ((enum tree_code) i), tree_code_counts[i]);
   mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
   fprintf (stderr, "\n");
   ssanames_print_statistics ();
-- 
2.14.3




[PATCH 3/3] Fix integer overflow in stats of GIMPLE statements.

2018-01-12 Thread marxin
gcc/ChangeLog:

2018-01-12  Martin Liska  

* gimple.c (gimple_alloc_counts): Use uint64_t instead of int.
(gimple_alloc_sizes): Likewise.
(dump_gimple_statistics): Use PRIu64 in printf format.
* gimple.h: Change uint64_t to int.
---
 gcc/gimple.c | 17 ++---
 gcc/gimple.h |  4 ++--
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/gcc/gimple.c b/gcc/gimple.c
index e24b9fd611d..c1b7229a6b7 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -77,8 +77,8 @@ EXPORTED_CONST enum gimple_statement_structure_enum 
gss_for_code_[] = {
 
 /* Gimple stats.  */
 
-int gimple_alloc_counts[(int) gimple_alloc_kind_all];
-int gimple_alloc_sizes[(int) gimple_alloc_kind_all];
+uint64_t gimple_alloc_counts[(int) gimple_alloc_kind_all];
+uint64_t gimple_alloc_sizes[(int) gimple_alloc_kind_all];
 
 /* Keep in sync with gimple.h:enum gimple_alloc_kind.  */
 static const char * const gimple_alloc_kind_names[] = {
@@ -2057,11 +2057,12 @@ gimple_assign_rhs_could_trap_p (gimple *s)
 void
 dump_gimple_statistics (void)
 {
-  int i, total_tuples = 0, total_bytes = 0;
+  int i;
+  uint64_t total_tuples = 0, total_bytes = 0;
 
   if (! GATHER_STATISTICS)
 {
-  fprintf (stderr, "No gimple statistics\n");
+  fprintf (stderr, "No GIMPLE statistics\n");
   return;
 }
 
@@ -2070,13 +2071,15 @@ dump_gimple_statistics (void)
   fprintf (stderr, "---\n");
   for (i = 0; i < (int) gimple_alloc_kind_all; ++i)
 {
-  fprintf (stderr, "%-20s %7d %10d\n", gimple_alloc_kind_names[i],
- gimple_alloc_counts[i], gimple_alloc_sizes[i]);
+  fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n",
+  gimple_alloc_kind_names[i], gimple_alloc_counts[i],
+  gimple_alloc_sizes[i]);
   total_tuples += gimple_alloc_counts[i];
   total_bytes += gimple_alloc_sizes[i];
 }
   fprintf (stderr, "---\n");
-  fprintf (stderr, "%-20s %7d %10d\n", "Total", total_tuples, total_bytes);
+  fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n", "Total",
+  total_tuples, total_bytes);
   fprintf (stderr, "---\n");
 }
 
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 8c0e9aefe54..281015ad3e2 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -6386,8 +6386,8 @@ enum gimple_alloc_kind
   gimple_alloc_kind_all
 };
 
-extern int gimple_alloc_counts[];
-extern int gimple_alloc_sizes[];
+extern uint64_t gimple_alloc_counts[];
+extern uint64_t gimple_alloc_sizes[];
 
 /* Return the allocation kind for a given stmt CODE.  */
 static inline enum gimple_alloc_kind
-- 
2.14.3



[PATCH 0/4] Clean-up warnings spotted by Rtags

2018-09-24 Thread marxin
Hello.

For quite some time I've been using Rtags for code completion and other
related stuff. Recently I noticed they provide diagnostics for an entire 
project.
Doing so, one can get quite some extra warning reported by Clang and I consider 
some
of them useful.

So that I would like to install my Python script that filters the warnings and 
few
patches that address the relevant warnings seen.

Patch survives bootstrap and regression tests on ppc64le-linux-gnu machine.

Martin

marxin (4):
  Add filter-rtags-warnings.py script.
  Remove unused functions and fields.
  Fix small coding style issues (PR fortran/87394).
  Fix scaling of a sreal number.

 contrib/filter-rtags-warnings.py |  71 
 gcc/alias.c  |   9 --
 gcc/config/i386/i386.c   |  15 
 gcc/cp/name-lookup.c |  15 
 gcc/cp/parser.c  |   8 --
 gcc/dbgcnt.c |   2 +-
 gcc/diagnostic-show-locus.c  |   2 -
 gcc/dump-context.h   |   1 -
 gcc/dumpfile.c   |   4 +-
 gcc/dwarf2out.c  | 141 ---
 gcc/edit-context.c   |   3 +-
 gcc/fortran/decl.c   |   2 +-
 gcc/fortran/trans.c  |  20 -
 gcc/gcov-tool.c  |   2 +-
 gcc/go/gofrontend/escape.cc  |  20 ++---
 gcc/go/gofrontend/expressions.cc |   2 +-
 gcc/go/gofrontend/gogo.h |   2 +-
 gcc/go/gofrontend/types.cc   |  13 +--
 gcc/go/gofrontend/types.h|   2 +-
 gcc/go/gofrontend/wb.cc  |  10 +--
 gcc/godump.c |   2 +-
 gcc/graphite-sese-to-poly.c  |   8 --
 gcc/ipa-cp.c |  10 ---
 gcc/ipa-fnsummary.c  |   2 +-
 gcc/lra-constraints.c|  27 --
 gcc/tree-chrec.c |  47 ---
 gcc/tree-if-conv.c   |  13 ---
 gcc/tree-ssa-coalesce.c  |  16 
 gcc/tree-ssa-pre.c   |   6 --
 gcc/tree-ssa-uninit.c|  10 ---
 gcc/tree-vrp.c   |  38 -
 31 files changed, 96 insertions(+), 427 deletions(-)
 create mode 100755 contrib/filter-rtags-warnings.py

-- 
2.19.0



[PATCH 3/4] Fix small coding style issues (PR fortran/87394).

2018-09-24 Thread marxin

gcc/ChangeLog:

2018-09-24  Martin Liska  

PR fortran/87394
* dbgcnt.c (dbg_cnt_process_single_pair): Return false
instead of NULL.
* dumpfile.c (dump_enable_all): Remove extra parenthesis.
* gcov-tool.c: Declare the function with ATTRIBUTE_NORETURN.
* godump.c (go_format_type): Remove extra parenthesis.

gcc/fortran/ChangeLog:

2018-09-24  Martin Liska  

PR fortran/87394
* decl.c (add_hidden_procptr_result): Simplify condition
as we are in branch witch 'case1 || case2'.
---
 gcc/dbgcnt.c   | 2 +-
 gcc/dumpfile.c | 4 ++--
 gcc/fortran/decl.c | 2 +-
 gcc/gcov-tool.c| 2 +-
 gcc/godump.c   | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index ddb0e8e76d9..1eea65889a8 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -138,7 +138,7 @@ dbg_cnt_process_single_pair (const char *arg)
   int high, low;
 
   if (value1 == NULL)
-return NULL;
+return false;
 
   if (value2 == NULL)
 {
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index a81ab3ed3c6..54f86237561 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -1511,7 +1511,7 @@ dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
 
   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
 {
-  if ((dump_files[i].dkind == dkind))
+  if (dump_files[i].dkind == dkind)
 {
   const char *old_filename = dump_files[i].pfilename;
   dump_files[i].pstate = -1;
@@ -1532,7 +1532,7 @@ dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
 
   for (i = 0; i < m_extra_dump_files_in_use; i++)
 {
-  if ((m_extra_dump_files[i].dkind == dkind))
+  if (m_extra_dump_files[i].dkind == dkind)
 {
   const char *old_filename = m_extra_dump_files[i].pfilename;
   m_extra_dump_files[i].pstate = -1;
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 91a1f34d7f1..7f79811d152 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -6463,7 +6463,7 @@ add_hidden_procptr_result (gfc_symbol *sym)
   gfc_symtree *stree;
   if (case1)
 	gfc_get_sym_tree ("ppr@", gfc_current_ns, &stree, false);
-  else if (case2)
+  else
 	{
 	  gfc_symtree *st2;
 	  gfc_get_sym_tree ("ppr@", gfc_current_ns->parent, &stree, false);
diff --git a/gcc/gcov-tool.c b/gcc/gcov-tool.c
index 88539f9647f..173ed5e5af2 100644
--- a/gcc/gcov-tool.c
+++ b/gcc/gcov-tool.c
@@ -438,7 +438,7 @@ static const struct option overlap_options[] =
 
 /* Print overlap usage and exit.  */
 
-static void
+static void ATTRIBUTE_NORETURN
 overlap_usage (void)
 {
   fnotice (stderr, "Overlap subcomand usage:");
diff --git a/gcc/godump.c b/gcc/godump.c
index 88e1a7782f1..baf21e27eec 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -961,7 +961,7 @@ go_format_type (struct godump_container *container, tree type,
 		   unions.  */
 		if (!is_anon_substructure)
 		  {
-		if ((DECL_NAME (field) == NULL))
+		if (DECL_NAME (field) == NULL)
 		  *p_art_i = go_append_artificial_name (ob, *p_art_i);
 		else
 		  go_append_decl_name


[PATCH 4/4] Fix scaling of a sreal number.

2018-09-24 Thread marxin

The patch is addressing following LLVM warning:
gcc/ipa-fnsummary.c:2745:54:Value Conversion Issue: implicit conversion from 
'double' to 'int64_t' (aka 'long') changes value from 0.99 to 0: 
-Wliteral-conversion

Taking look at GIMPLE IR we end up with:

   :
  D.107433 ={v} {CLOBBER};
  sreal::sreal (&D.107437, -1, 0);
  sreal::sreal (&D.107434, 0, 0);
  D.107435 = sreal::operator* (&time, &D.107434);
  D.107436 = sreal::operator- (&nonspecialized_time, &D.107435);
  _65 = operator>= (&D.107436, &D.107437);
  _66 = ~_65;
  if (_66 != 0)
goto ; [INV]
  else
goto ; [INV]

   :
  fancy_abort ("/home/marxin/Programming/gcc/gcc/ipa-fnsummary.c", 2745, 
&__FUNCTION__);

which confirms the warning.

gcc/ChangeLog:

2018-09-23  Martin Liska  

* ipa-fnsummary.c (estimate_node_size_and_time): Scale by two
integers and not by a float value.
---
 gcc/ipa-fnsummary.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 62095c6cf6f..9cb7d41ccc5 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -2742,7 +2742,7 @@ estimate_node_size_and_time (struct cgraph_node *node,
   gcc_checking_assert (time >= 0);
   /* nonspecialized_time should be always bigger than specialized time.
  Roundoff issues however may get into the way.  */
-  gcc_checking_assert ((nonspecialized_time - time * 0.99) >= -1);
+  gcc_checking_assert ((nonspecialized_time - time * 99 / 100) >= -1);
 
   /* Roundoff issues may make specialized time bigger than nonspecialized
  time.  We do not really want that to happen because some heurstics


[PATCH 2/4] Remove unused functions and fields.

2018-09-24 Thread marxin

gcc/ChangeLog:

2018-09-24  Martin Liska  

* alias.c (set_dest_equal_p): Remove unused function.
* config/i386/i386.c (def_builtin_pure2): Likewise.
* diagnostic-show-locus.c (class layout): Remove
unused field.
(layout::layout): Likewise here.
* dump-context.h (class temp_dump_context): Likewise.
* dwarf2out.c (add_AT_fde_ref): Remove unused function.
(add_AT_loclistsptr): Likewise.
(add_AT_offset): Likewise.
(get_AT_hi_pc): Likewise.
(is_comdat_die): Likewise.
(type_is_enum): Likewise.
(ceiling): Likewise.
(add_AT_vms_delta): Likewise.
(is_class_die): Likewise.
* edit-context.c (class line_event): Remove unused field.
* graphite-sese-to-poly.c (tree_int_to_gmp): Remove
unused function.
* ipa-cp.c (ipa_get_vr_lat): Likewise.
* lra-constraints.c (ok_for_index_p_nonstrict): Likewise.
(ok_for_base_p_nonstrict): Likewise.
* tree-chrec.c (is_not_constant_evolution): Likewise.
(chrec_fold_poly_cst): Likewise.
* tree-if-conv.c (has_pred_critical_p): Likewise.
* tree-ssa-coalesce.c (print_exprs): Likewise.
* tree-ssa-pre.c (bitmap_set_contains_expr): Likewise.
* tree-ssa-uninit.c (is_and_or_or_p): Likewise.
* tree-vrp.c (value_ranges_intersect_p): Likewise.
(value_range_nonnegative_p): Likewise.

gcc/cp/ChangeLog:

2018-09-24  Martin Liska  

* name-lookup.c (namespace_scope_ht_size): Remove
unused function.
* parser.c (cp_lexer_next_token_is_not_keyword): Likewise.

gcc/fortran/ChangeLog:

2018-09-24  Martin Liska  

* trans.c (remove_suffix): Remove
unused function.

gcc/go/ChangeLog:

2018-09-24  Martin Liska  

* gofrontend/escape.cc (Gogo::analyze_escape): Remove
usage of a parameter.
(Gogo::assign_connectivity): Likewise.
(class Escape_analysis_tag): Likewise.
(Gogo::tag_function): Likewise.
* gofrontend/expressions.cc (Call_expression::do_type): Likewise.
* gofrontend/gogo.h (class Gogo): Likewise.
* gofrontend/types.cc (class Call_multiple_result_type): Likewise.
(Type::make_call_multiple_result_type): Likewise.
* gofrontend/types.h (class Type): Likewise.
* gofrontend/wb.cc (class Check_escape): Likewise.
(Gogo::add_write_barriers): Likewise.
---
 gcc/alias.c  |   9 --
 gcc/config/i386/i386.c   |  15 
 gcc/cp/name-lookup.c |  15 
 gcc/cp/parser.c  |   8 --
 gcc/diagnostic-show-locus.c  |   2 -
 gcc/dump-context.h   |   1 -
 gcc/dwarf2out.c  | 141 ---
 gcc/edit-context.c   |   3 +-
 gcc/fortran/trans.c  |  20 -
 gcc/go/gofrontend/escape.cc  |  20 ++---
 gcc/go/gofrontend/expressions.cc |   2 +-
 gcc/go/gofrontend/gogo.h |   2 +-
 gcc/go/gofrontend/types.cc   |  13 +--
 gcc/go/gofrontend/types.h|   2 +-
 gcc/go/gofrontend/wb.cc  |  10 +--
 gcc/graphite-sese-to-poly.c  |   8 --
 gcc/ipa-cp.c |  10 ---
 gcc/lra-constraints.c|  27 --
 gcc/tree-chrec.c |  47 ---
 gcc/tree-if-conv.c   |  13 ---
 gcc/tree-ssa-coalesce.c  |  16 
 gcc/tree-ssa-pre.c   |   6 --
 gcc/tree-ssa-uninit.c|  10 ---
 gcc/tree-vrp.c   |  38 -
 24 files changed, 18 insertions(+), 420 deletions(-)

diff --git a/gcc/alias.c b/gcc/alias.c
index 748da2b6951..7963ece291a 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -3270,15 +3270,6 @@ memory_modified_in_insn_p (const_rtx mem, const_rtx insn)
   return memory_modified;
 }
 
-/* Return TRUE if the destination of a set is rtx identical to
-   ITEM.  */
-static inline bool
-set_dest_equal_p (const_rtx set, const_rtx item)
-{
-  rtx dest = SET_DEST (set);
-  return rtx_equal_p (dest, item);
-}
-
 /* Initialize the aliasing machinery.  Initialize the REG_KNOWN_VALUE
array.  */
 
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0c86303b9fa..e50aa037c49 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -30224,21 +30224,6 @@ def_builtin_const2 (HOST_WIDE_INT mask, const char *name,
   return decl;
 }
 
-/* Like def_builtin, but also marks the function decl "pure".  */
-
-static inline tree
-def_builtin_pure2 (HOST_WIDE_INT mask, const char *name,
-		   enum ix86_builtin_func_type tcode, enum ix86_builtins code)
-{
-  tree decl = def_builtin2 (mask, name, tcode, code);
-  if (decl)
-DECL_PURE_P (decl) = 1;
-  else
-ix86_builtins_isa[(int) code].pure_p = true;
-
-  return decl;
-}
-
 /* Add any new builtin functions for a given ISA that may not have been
declared.  This saves a bit of space compared to adding all of the
declarations to the tree, even if we didn't use them. 

[PATCH 1/4] Add filter-rtags-warnings.py script.

2018-09-24 Thread marxin

contrib/ChangeLog:

2018-09-24  Martin Liska  

* filter-rtags-warnings.py: New file.
---
 contrib/filter-rtags-warnings.py | 71 
 1 file changed, 71 insertions(+)
 create mode 100755 contrib/filter-rtags-warnings.py

diff --git a/contrib/filter-rtags-warnings.py b/contrib/filter-rtags-warnings.py
new file mode 100755
index 000..ee27e7c8942
--- /dev/null
+++ b/contrib/filter-rtags-warnings.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+#
+# Script to analyze warnings produced by rtags command (using LLVM):
+# rc --diagnose-all --synchronous-diagnostics --json
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3, or (at your option) any later
+# version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .  */
+#
+#
+#
+
+import sys
+import json
+import argparse
+
+def skip_warning(filename, warning):
+ignores = {
+'': ['-Warray-bounds', '-Wmismatched-tags', 'gcc_gfc: -Wignored-attributes', '-Wchar-subscripts',
+'string literal (potentially insecure): -Wformat-security', '-Wdeprecated-register',
+'-Wvarargs', 'keyword is hidden by macro definition', "but the argument has type 'char *': -Wformat-pedantic",
+'-Wnested-anon-types', 'qualifier in explicit instantiation of', 'attribute argument not supported: asm_fprintf'],
+'insn-modes.c': ['-Wshift-count-overflow'],
+'insn-emit.c': ['-Wtautological-compare'],
+'insn-attrtab.c': ['-Wparentheses-equality'],
+'gimple-match.c': ['-Wunused-', '-Wtautological-compare'],
+'generic-match.c': ['-Wunused-', '-Wtautological-compare'],
+}
+
+message = warning['message']
+
+if warning['type'] == 'fixit':
+return True
+
+for name, ignores in ignores.items():
+for i in ignores:
+if name in filename and i in message:
+return True
+
+return False
+
+parser = argparse.ArgumentParser()
+parser.add_argument('json_file', help = 'Rtags JSON file with diagnostics')
+parser.add_argument('-n', '--no-filter', action = 'store_true', help = 'No filter')
+
+args = parser.parse_args()
+
+data = json.load(open(args.json_file))
+file_warnings = data['checkStyle']
+
+total = 0
+for filename, warnings in file_warnings.items():
+if warnings:
+for w in warnings:
+if args.no_filter or not skip_warning(filename, w):
+total += 1
+print('%s:%d:%d:%s' % (filename, w['line'], w['column'], w['message']))
+
+print('Total: %d' % total)


[PATCH 09/14] Remove cgraph_node::summary_uid and make cgraph_node::uid really unique.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-05-16  Martin Liska  

* cgraph.c (cgraph_node::remove): Do not recycle uid.
* cgraph.h (symbol_table::release_symbol): Do not pass uid.
(symbol_table::allocate_cgraph_symbol): Do not set uid.
* passes.c (uid_hash_t): Record removed_nodes by their uids.
(remove_cgraph_node_from_order): Use the removed_nodes set.
(do_per_function_toporder): Likwise.
* symbol-summary.h (symtab_insertion): Use cgraph_node::uid
instead of summary_uid.
(symtab_removal): Likewise.
(symtab_duplication): Likewise.

gcc/lto/ChangeLog:

2018-05-16  Martin Liska  

* lto-partition.c (lto_balanced_map): Use cgraph_node::uid
instead of summary_uid.
---
 gcc/cgraph.c|  3 +--
 gcc/cgraph.h| 20 ++--
 gcc/lto/lto-partition.c | 26 +++---
 gcc/passes.c| 37 -
 gcc/symbol-summary.h| 18 +-
 5 files changed, 39 insertions(+), 65 deletions(-)

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 9a7d54d7cee..a24a5ffe521 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1805,7 +1805,6 @@ void
 cgraph_node::remove (void)
 {
   cgraph_node *n;
-  int uid = this->uid;
 
   if (symtab->ipa_clones_dump_file && symtab->cloned_nodes.contains (this))
 fprintf (symtab->ipa_clones_dump_file,
@@ -1907,7 +1906,7 @@ cgraph_node::remove (void)
   instrumented_version = NULL;
 }
 
-  symtab->release_symbol (this, uid);
+  symtab->release_symbol (this);
 }
 
 /* Likewise indicate that a node is having address taken.  */
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index ee7ebb41c24..0e3b1a1785e 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1396,8 +1396,6 @@ public:
   int count_materialization_scale;
   /* Unique id of the node.  */
   int uid;
-  /* Summary unique id of the node.  */
-  int summary_uid;
   /* ID assigned by the profiling.  */
   unsigned int profile_id;
   /* Time profiler: first run of function.  */
@@ -2020,7 +2018,7 @@ public:
   friend class cgraph_node;
   friend class cgraph_edge;
 
-  symbol_table (): cgraph_max_summary_uid (1)
+  symbol_table (): cgraph_max_uid (1)
   {
   }
 
@@ -2080,9 +2078,8 @@ public:
   /* Allocate new callgraph node and insert it into basic data structures.  */
   cgraph_node *create_empty (void);
 
-  /* Release a callgraph NODE with UID and put in to the list
- of free nodes.  */
-  void release_symbol (cgraph_node *node, int uid);
+  /* Release a callgraph NODE.  */
+  void release_symbol (cgraph_node *node);
 
   /* Output all variables enqueued to be assembled.  */
   bool output_variables (void);
@@ -2230,7 +2227,6 @@ public:
 
   int cgraph_count;
   int cgraph_max_uid;
-  int cgraph_max_summary_uid;
 
   int edges_count;
   int edges_max_uid;
@@ -2598,7 +2594,7 @@ symbol_table::unregister (symtab_node *node)
 /* Release a callgraph NODE with UID and put in to the list of free nodes.  */
 
 inline void
-symbol_table::release_symbol (cgraph_node *node, int uid)
+symbol_table::release_symbol (cgraph_node *node)
 {
   cgraph_count--;
 
@@ -2606,7 +2602,6 @@ symbol_table::release_symbol (cgraph_node *node, int uid)
  list.  */
   memset (node, 0, sizeof (*node));
   node->type = SYMTAB_FUNCTION;
-  node->uid = uid;
   SET_NEXT_FREE_NODE (node, free_nodes);
   free_nodes = node;
 }
@@ -2624,12 +2619,9 @@ symbol_table::allocate_cgraph_symbol (void)
   free_nodes = NEXT_FREE_NODE (node);
 }
   else
-{
-  node = ggc_cleared_alloc ();
-  node->uid = cgraph_max_uid++;
-}
+node = ggc_cleared_alloc ();
 
-  node->summary_uid = cgraph_max_summary_uid++;
+  node->uid = cgraph_max_uid++;
   return node;
 }
 
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 76086a2ba2e..9049a372256 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -506,12 +506,10 @@ account_reference_p (symtab_node *n1, symtab_node *n2)
 void
 lto_balanced_map (int n_lto_partitions, int max_partition_size)
 {
-  int n_nodes = 0;
   int n_varpool_nodes = 0, varpool_pos = 0, best_varpool_pos = 0;
-  struct cgraph_node **order = XNEWVEC (cgraph_node *, symtab->cgraph_max_uid);
+  auto_vec  order (symtab->cgraph_count);
   auto_vec noreorder;
   auto_vec varpool_order;
-  int i;
   struct cgraph_node *node;
   int64_t original_total_size, total_size = 0;
   int64_t partition_size;
@@ -519,7 +517,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
   int last_visited_node = 0;
   varpool_node *vnode;
   int64_t cost = 0, internal = 0;
-  int best_n_nodes = 0, best_i = 0;
+  unsigned int best_n_nodes = 0, best_i = 0;
   int64_t best_cost = -1, best_internal = 0, best_size = 0;
   int npartitions;
   int current_order = -1;
@@ -527,14 +525,14 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
 
   FOR_EACH_VARIABLE (vnode)
 gcc_assert (!vnode->aux);
-
+
   FOR_EACH_DEFINED_FUNCTION (node)
 if (node-

[PATCH 13/14] Make cgraph_edge::uid really unique.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* cgraph.c (symbol_table::create_edge): Always assign a new
unique number.
(symbol_table::free_edge): Do not recycle numbers.
* cgraph.h (cgraph_edge::get): New method.
* symbol-summary.h (symtab_removal): Use it.
(symtab_duplication): Likewise.
(call_summary::hashable_uid): Remove.
---
 gcc/cgraph.c |  9 ++---
 gcc/cgraph.h | 14 +++---
 gcc/symbol-summary.h | 21 +++--
 3 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index a24a5ffe521..572c775c14c 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -846,13 +846,11 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
   free_edges = NEXT_FREE_EDGE (edge);
 }
   else
-{
-  edge = ggc_alloc ();
-  edge->uid = edges_max_uid++;
-}
+edge = ggc_alloc ();
 
   edges_count++;
 
+  edge->m_uid = edges_max_uid++;
   edge->aux = NULL;
   edge->caller = caller;
   edge->callee = callee;
@@ -1006,14 +1004,11 @@ cgraph_edge::remove_caller (void)
 void
 symbol_table::free_edge (cgraph_edge *e)
 {
-  int uid = e->uid;
-
   if (e->indirect_info)
 ggc_free (e->indirect_info);
 
   /* Clear out the edge so we do not dangle pointers.  */
   memset (e, 0, sizeof (*e));
-  e->uid = uid;
   NEXT_FREE_EDGE (e) = free_edges;
   free_edges = e;
   edges_count--;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0e3b1a1785e..1966893343d 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1633,6 +1633,7 @@ struct GTY(()) cgraph_indirect_call_info
 struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
 	for_user)) cgraph_edge {
   friend class cgraph_node;
+  friend class symbol_table;
 
   /* Remove the edge in the cgraph.  */
   void remove (void);
@@ -1696,6 +1697,12 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
   /* Return true if the call can be hot.  */
   bool maybe_hot_p (void);
 
+  /* Get unique identifier of the edge.  */
+  inline int get_uid ()
+  {
+return m_uid;
+  }
+
   /* Rebuild cgraph edges for current function node.  This needs to be run after
  passes that don't update the cgraph.  */
   static unsigned int rebuild_edges (void);
@@ -1723,8 +1730,6 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
   /* The stmt_uid of call_stmt.  This is used by LTO to recover the call_stmt
  when the function is serialized in.  */
   unsigned int lto_stmt_uid;
-  /* Unique id of the edge.  */
-  int uid;
   /* Whether this edge was made direct by indirect inlining.  */
   unsigned int indirect_inlining_edge : 1;
   /* Whether this edge describes an indirect call with an undetermined
@@ -1768,6 +1773,9 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
   /* Expected frequency of executions within the function.  */
   sreal sreal_frequency ();
 private:
+  /* Unique id of the edge.  */
+  int m_uid;
+
   /* Remove the edge from the list of the callers of the callee.  */
   void remove_caller (void);
 
@@ -2018,7 +2026,7 @@ public:
   friend class cgraph_node;
   friend class cgraph_edge;
 
-  symbol_table (): cgraph_max_uid (1)
+  symbol_table (): cgraph_max_uid (1), edges_max_uid (1)
   {
   }
 
diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index 12e50201125..8c80f309372 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -375,19 +375,19 @@ public:
  If a summary for an edge does not exist, it will be created.  */
   T* get_create (cgraph_edge *edge)
   {
-return get (hashable_uid (edge), true);
+return get (edge->get_uid (), true);
   }
 
   /* Getter for summary callgraph edge pointer.  */
   T* get (cgraph_edge *edge)
   {
-return get (hashable_uid (edge), false);
+return get (edge->get_uid (), false);
   }
 
   /* Remove edge from summary.  */
   void remove (cgraph_edge *edge)
   {
-int uid = hashable_uid (edge);
+int uid = edge->get_uid ();
 T **v = m_map.get (uid);
 if (v)
   {
@@ -405,7 +405,7 @@ public:
   /* Return true if a summary for the given EDGE already exists.  */
   bool exists (cgraph_edge *edge)
   {
-return m_map.get (hashable_uid (edge)) != NULL;
+return m_map.get (edge->get_uid ()) != NULL;
   }
 
   /* Symbol removal hook that is registered to symbol table.  */
@@ -428,13 +428,6 @@ private:
   /* Getter for summary callgraph ID.  */
   T *get (int uid, bool lazy_insert);
 
-  /* Get a hashable uid of EDGE.  */
-  int hashable_uid (cgraph_edge *edge)
-  {
-/* Edge uids start at zero which our hash_map does not like.  */
-return edge->uid + 1;
-  }
-
   /* Main summary store, where summary ID is used as key.  */
   hash_map  m_map;
   /* Internal summary removal hook pointer.  */
@@ -511,7 +504,7 @@ call_summary::symtab_removal (cgraph_edge *edge, void *data)
 {
   call_summary *summary = (call_summary  *) (data);
 
-  int h_uid = summ

[PATCH 01/14] Code refactoring of symtab_summary.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* symbol-summary.h (function_summary): Move constructor
implementation out of class declaration.
(release): Likewise.
(symtab_insertion): Likewise.
(symtab_removal): Likewise.
(symtab_duplication): Likewise.
(get): Likewise.
---
 gcc/symbol-summary.h | 219 ++-
 1 file changed, 130 insertions(+), 89 deletions(-)

diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index d11b70b5946..13f8f04342a 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -31,26 +31,23 @@ private:
   function_summary();
 };
 
+/* Function summary is a helper class that is used to associate a data structure
+   related to a callgraph node.  Typical usage can be seen in IPA passes which
+   create a temporary pass-related structures.  The summary class registers
+   hooks that are triggered when a new node is inserted, duplicated and deleted.
+   A user of a summary class can ovewrite virtual methods than are triggered by
+   the summary if such hook is triggered.  Apart from a callgraph node, the user
+   is given a data structure tied to the node.
+
+   The function summary class can work both with a heap-allocated memory and
+   a memory gained by garbage collected memory.  */
+
 template 
 class GTY((user)) function_summary 
 {
 public:
   /* Default construction takes SYMTAB as an argument.  */
-  function_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
-m_insertion_enabled (true), m_released (false), m_map (13, ggc),
-m_symtab (symtab)
-  {
-m_symtab_insertion_hook =
-  symtab->add_cgraph_insertion_hook
-  (function_summary::symtab_insertion, this);
-
-m_symtab_removal_hook =
-  symtab->add_cgraph_removal_hook
-  (function_summary::symtab_removal, this);
-m_symtab_duplication_hook =
-  symtab->add_cgraph_duplication_hook
-  (function_summary::symtab_duplication, this);
-  }
+  function_summary (symbol_table *symtab, bool ggc = false);
 
   /* Destructor.  */
   virtual ~function_summary ()
@@ -59,22 +56,7 @@ public:
   }
 
   /* Destruction method that can be called for GGT purpose.  */
-  void release ()
-  {
-if (m_released)
-  return;
-
-m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
-m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
-m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
-
-/* Release all summaries.  */
-typedef typename hash_map ::iterator map_iterator;
-for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
-  release ((*it).second);
-
-m_released = true;
-  }
+  void release ();
 
   /* Traverses all summarys with a function F called with
  ARG as argument.  */
@@ -102,16 +84,7 @@ public:
   }
 
   /* Release an item that is stored within map.  */
-  void release (T *item)
-  {
-if (m_ggc)
-  {
-	item->~T ();
-	ggc_free (item);
-  }
-else
-  delete item;
-  }
+  void release (T *item);
 
   /* Getter for summary callgraph node pointer.  */
   T* get (cgraph_node *node)
@@ -145,50 +118,14 @@ public:
   }
 
   /* Symbol insertion hook that is registered to symbol table.  */
-  static void symtab_insertion (cgraph_node *node, void *data)
-  {
-gcc_checking_assert (node->summary_uid);
-function_summary *summary = (function_summary  *) (data);
-
-if (summary->m_insertion_enabled)
-  summary->insert (node, summary->get (node));
-  }
+  static void symtab_insertion (cgraph_node *node, void *data);
 
   /* Symbol removal hook that is registered to symbol table.  */
-  static void symtab_removal (cgraph_node *node, void *data)
-  {
-gcc_checking_assert (node->summary_uid);
-function_summary *summary = (function_summary  *) (data);
-
-int summary_uid = node->summary_uid;
-T **v = summary->m_map.get (summary_uid);
-
-if (v)
-  {
-	summary->remove (node, *v);
-	summary->release (*v);
-	summary->m_map.remove (summary_uid);
-  }
-  }
+  static void symtab_removal (cgraph_node *node, void *data);
 
   /* Symbol duplication hook that is registered to symbol table.  */
   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
-  void *data)
-  {
-function_summary *summary = (function_summary  *) (data);
-T **v = summary->m_map.get (node->summary_uid);
-
-gcc_checking_assert (node2->summary_uid > 0);
-
-if (v)
-  {
-	/* This load is necessary, because we insert a new value!  */
-	T *data = *v;
-	T *duplicate = summary->allocate_new ();
-	summary->m_map.put (node2->summary_uid, duplicate);
-	summary->duplicate (node, node2, data, duplicate);
-  }
-  }
+  void *data);
 
 protected:
   /* Indication if we use ggc summary.  */
@@ -198,15 +135,7 @@ private:
   typedef int_hash  map_hash;
 
   /* Getter for summary callgraph ID.  */
-  T* get (int uid)
-  {
-bool existed;
-T **v = &m_map.get_o

[PATCH 06/14] Use symtab_summary in ipa-reference.c.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* ipa-reference.c (remove_node_data): Remove.
(duplicate_node_data): Likewise.
(class ipa_ref_var_info_summary_t): New class.
(class ipa_ref_opt_summary_t): Likewise.
(get_reference_vars_info): Use ipa_ref_var_info_summaries.
(get_reference_optimization_summary): Use
ipa_ref_opt_sum_summaries.
(set_reference_vars_info): Remove.
(set_reference_optimization_summary): Likewise.
(ipa_init): Create summaries.
(init_function_info): Use function summary.
(ipa_ref_opt_summary_t::duplicate): New function.
(ipa_ref_opt_summary_t::remove): New function.
(get_read_write_all_from_node): Fix GNU coding style.
(propagate): Use function summary.
(write_node_summary_p): Fix GNU coding style.
(stream_out_bitmap): Likewise.
(ipa_reference_read_optimization_summary): Use function summary.
(ipa_reference_c_finalize): Do not release hooks.
---
 gcc/ipa-reference.c | 205 
 1 file changed, 95 insertions(+), 110 deletions(-)

diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 6490c03f8d0..9a9e94c3414 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -49,12 +49,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "splay-tree.h"
 #include "ipa-utils.h"
 #include "ipa-reference.h"
-
-static void remove_node_data (struct cgraph_node *node,
-			  void *data ATTRIBUTE_UNUSED);
-static void duplicate_node_data (struct cgraph_node *src,
- struct cgraph_node *dst,
- void *data ATTRIBUTE_UNUSED);
+#include "symbol-summary.h"
 
 /* The static variables defined within the compilation unit that are
loaded or stored directly by function that owns this structure.  */
@@ -84,9 +79,10 @@ struct ipa_reference_optimization_summary_d
   bitmap statics_not_written;
 };
 
-typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
-typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
-typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
+typedef ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
+typedef ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
+typedef ipa_reference_optimization_summary_d *
+  ipa_reference_optimization_summary_t;
 
 struct ipa_reference_vars_info_d
 {
@@ -114,57 +110,55 @@ static bitmap_obstack local_info_obstack;
 /* Obstack holding global analysis live forever.  */
 static bitmap_obstack optimization_summary_obstack;
 
-/* Holders of ipa cgraph hooks: */
-static struct cgraph_2node_hook_list *node_duplication_hook_holder;
-static struct cgraph_node_hook_list *node_removal_hook_holder;
+class ipa_ref_var_info_summary_t: public function_summary
+			  
+{
+public:
+  ipa_ref_var_info_summary_t (symbol_table *symtab):
+function_summary  (symtab) {}
+};
 
-/* Vector where the reference var infos are actually stored. 
-   Indexed by UID of call graph nodes.  */
-static vec ipa_reference_vars_vector;
+static ipa_ref_var_info_summary_t *ipa_ref_var_info_summaries = NULL;
 
-/* TODO: find a place where we should release the vector.  */
-static vec ipa_reference_opt_sum_vector;
+class ipa_ref_opt_summary_t: public function_summary
+			 
+{
+public:
+  ipa_ref_opt_summary_t (symbol_table *symtab):
+function_summary  (symtab) {}
+
+
+  virtual void remove (cgraph_node *src_node,
+		   ipa_reference_optimization_summary_d *data);
+  virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node,
+			  ipa_reference_optimization_summary_d *src_data,
+			  ipa_reference_optimization_summary_d *dst_data);
+};
+
+static ipa_ref_opt_summary_t *ipa_ref_opt_sum_summaries = NULL;
 
 /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
 static inline ipa_reference_vars_info_t
 get_reference_vars_info (struct cgraph_node *node)
 {
-  if (!ipa_reference_vars_vector.exists ()
-  || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
+  if (ipa_ref_var_info_summaries == NULL)
 return NULL;
-  return ipa_reference_vars_vector[node->uid];
+
+  ipa_reference_vars_info_t v = ipa_ref_var_info_summaries->get (node);
+  return v == NULL ? NULL : v;
 }
 
 /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
 static inline ipa_reference_optimization_summary_t
 get_reference_optimization_summary (struct cgraph_node *node)
 {
-  if (!ipa_reference_opt_sum_vector.exists ()
-  || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
+  if (ipa_ref_opt_sum_summaries == NULL)
 return NULL;
-  return ipa_reference_opt_sum_vector[node->uid];
-}
 
-/* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
-static inline void
-set_reference_vars_info (struct cgraph_node *node,
-			 ipa_reference_vars_info_t info)
-{
-

[PATCH 05/14] Use summaries->get where possible. Small refactoring of multiple calls.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* ipa-fnsummary.c (dump_ipa_call_summary): Use ::get method.
(analyze_function_body): Extract multiple calls of get_create.
* ipa-inline-analysis.c (simple_edge_hints): Likewise.
* ipa-inline.c (recursive_inlining): Use ::get method.
* ipa-inline.h (estimate_edge_growth): Likewise.
---
 gcc/ipa-fnsummary.c   | 14 +++---
 gcc/ipa-inline-analysis.c |  2 +-
 gcc/ipa-inline.c  |  8 
 gcc/ipa-inline.h  |  7 +++
 4 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 8a6c5d0b5d8..e40b537bf61 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -850,7 +850,7 @@ dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node,
 	  }
   if (!edge->inline_failed)
 	{
-	  ipa_fn_summary *s = ipa_fn_summaries->get_create (callee);
+	  ipa_fn_summary *s = ipa_fn_summaries->get (callee);
 	  fprintf (f, "%*sStack frame offset %i, callee self size %i,"
 		   " callee size %i\n",
 		   indent + 2, "",
@@ -2363,10 +2363,9 @@ analyze_function_body (struct cgraph_node *node, bool early)
 	}
 	  free (body);
 	}
-  set_hint_predicate (&ipa_fn_summaries->get_create (node)->loop_iterations,
-			  loop_iterations);
-  set_hint_predicate (&ipa_fn_summaries->get_create (node)->loop_stride,
-			  loop_stride);
+  ipa_fn_summary *s = ipa_fn_summaries->get_create (node);
+  set_hint_predicate (&s->loop_iterations, loop_iterations);
+  set_hint_predicate (&s->loop_stride, loop_stride);
   scev_finalize ();
 }
   FOR_ALL_BB_FN (bb, my_function)
@@ -2384,8 +2383,9 @@ analyze_function_body (struct cgraph_node *node, bool early)
 	  e->aux = NULL;
 	}
 }
-  ipa_fn_summaries->get_create (node)->time = time;
-  ipa_fn_summaries->get_create (node)->self_size = size;
+  ipa_fn_summary *s = ipa_fn_summaries->get_create (node);
+  s->time = time;
+  s->self_size = size;
   nonconstant_names.release ();
   ipa_release_body_info (&fbi);
   if (opt_for_fn (node->decl, optimize))
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index c4f904730e6..2e30a6d15ba 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -126,7 +126,7 @@ simple_edge_hints (struct cgraph_edge *edge)
 			? edge->caller->global.inlined_to : edge->caller);
   struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
   if (ipa_fn_summaries->get_create (to)->scc_no
-  && ipa_fn_summaries->get_create (to)->scc_no
+  && ipa_fn_summaries->get (to)->scc_no
 	 == ipa_fn_summaries->get_create (callee)->scc_no
   && !edge->recursive_p ())
 hints |= INLINE_HINT_same_scc;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index b015db07d15..12f5ebfd582 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1559,10 +1559,10 @@ recursive_inlining (struct cgraph_edge *edge,
 fprintf (dump_file,
 	 "\n   Inlined %i times, "
 	 "body grown from size %i to %i, time %f to %f\n", n,
-	 ipa_fn_summaries->get_create (master_clone)->size,
-	 ipa_fn_summaries->get_create (node)->size,
-	 ipa_fn_summaries->get_create (master_clone)->time.to_double (),
-	 ipa_fn_summaries->get_create (node)->time.to_double ());
+	 ipa_fn_summaries->get (master_clone)->size,
+	 ipa_fn_summaries->get (node)->size,
+	 ipa_fn_summaries->get (master_clone)->time.to_double (),
+	 ipa_fn_summaries->get (node)->time.to_double ());
 
   /* Remove master clone we used for inlining.  We rely that clones inlined
  into master clone gets queued just before master clone so we don't
diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h
index e8ae206d7b7..06bd38e551e 100644
--- a/gcc/ipa-inline.h
+++ b/gcc/ipa-inline.h
@@ -81,10 +81,9 @@ estimate_edge_size (struct cgraph_edge *edge)
 static inline int
 estimate_edge_growth (struct cgraph_edge *edge)
 {
-  gcc_checking_assert (ipa_call_summaries->get_create (edge)->call_stmt_size
-		   || !edge->callee->analyzed);
-  return (estimate_edge_size (edge)
-	  - ipa_call_summaries->get_create (edge)->call_stmt_size);
+  ipa_call_summary *s = ipa_call_summaries->get_create (edge);
+  gcc_checking_assert (s->call_stmt_size || !edge->callee->analyzed);
+  return (estimate_edge_size (edge) - s->call_stmt_size);
 }
 
 /* Return estimated callee runtime increase after inlining


[PATCH 10/14] Add call_summary::get method and m_initialize_when_cloning.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* symbol-summary.h (get): New function.
(call_summary::m_initialize_when_cloning): New class member.
---
 gcc/symbol-summary.h | 66 +++-
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index dda3ae5718f..4896c97a1cd 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -326,7 +326,8 @@ class GTY((user)) call_summary 
 public:
   /* Default construction takes SYMTAB as an argument.  */
   call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
-m_map (13, ggc), m_released (false), m_symtab (symtab)
+m_initialize_when_cloning (false), m_map (13, ggc), m_released (false),
+m_symtab (symtab)
   {
 m_symtab_removal_hook =
   symtab->add_edge_removal_hook
@@ -374,7 +375,13 @@ public:
  If a summary for an edge does not exist, it will be created.  */
   T* get_create (cgraph_edge *edge)
   {
-return get_create (hashable_uid (edge));
+return get (hashable_uid (edge), true);
+  }
+
+  /* Getter for summary callgraph edge pointer.  */
+  T* get (cgraph_edge *edge)
+  {
+return get (hashable_uid (edge), false);
   }
 
   /* Return number of elements handled by data structure.  */
@@ -400,19 +407,14 @@ protected:
   /* Indication if we use ggc summary.  */
   bool m_ggc;
 
+  /* Initialize summary for an edge that is cloned.  */
+  bool m_initialize_when_cloning;
+
 private:
   typedef int_hash  map_hash;
 
   /* Getter for summary callgraph ID.  */
-  T* get_create (int uid)
-  {
-bool existed;
-T **v = &m_map.get_or_insert (uid, &existed);
-if (!existed)
-  *v = allocate_new ();
-
-return *v;
-  }
+  T *get (int uid, bool lazy_insert);
 
   /* Get a hashable uid of EDGE.  */
   int hashable_uid (cgraph_edge *edge)
@@ -438,6 +440,28 @@ private:
   gt_pointer_operator, void *);
 };
 
+template 
+T*
+call_summary::get (int uid, bool lazy_insert)
+{
+  gcc_checking_assert (uid > 0);
+
+  if (lazy_insert)
+{
+  bool existed;
+  T **v = &m_map.get_or_insert (uid, &existed);
+  if (!existed)
+	*v = allocate_new ();
+
+  return *v;
+}
+  else
+{
+  T **v = m_map.get (uid);
+  return v == NULL ? NULL : *v;
+}
+}
+
 template 
 void
 call_summary::release ()
@@ -492,15 +516,25 @@ call_summary::symtab_duplication (cgraph_edge *edge1,
    cgraph_edge *edge2, void *data)
 {
   call_summary *summary = (call_summary  *) (data);
-  T **v = summary->m_map.get (summary->hashable_uid (edge1));
+  T *edge1_summary = NULL;
 
-  if (v)
+  if (summary->m_initialize_when_cloning)
+edge1_summary = summary->get_create (edge1);
+  else
+{
+  T **v = summary->m_map.get (summary->hashable_uid (edge1));
+  if (v)
+	{
+	  /* This load is necessary, because we insert a new value!  */
+	  edge1_summary = *v;
+	}
+}
+
+  if (edge1_summary)
 {
-  /* This load is necessary, because we insert a new value!  */
-  T *data = *v;
   T *duplicate = summary->allocate_new ();
   summary->m_map.put (summary->hashable_uid (edge2), duplicate);
-  summary->duplicate (edge1, edge2, data, duplicate);
+  summary->duplicate (edge1, edge2, edge1_summary, duplicate);
 }
 }
 


[PATCH 11/14] Port IPA CP to edge_clone_summaries.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* ipa-cp.c (class edge_clone_summary): New summary.
(grow_edge_clone_vectors): Remove.
(ipcp_edge_duplication_hook): Remove.
(class edge_clone_summary_t): New call_summary class.
(ipcp_edge_removal_hook): Remove.
(edge_clone_summary_t::duplicate): New function.
(get_next_cgraph_edge_clone): Use edge_clone_summaries.
(create_specialized_node): Likewise.
(ipcp_driver): Initialize edge_clone_summaries and do not
register hooks.
---
 gcc/ipa-cp.c | 102 ---
 1 file changed, 49 insertions(+), 53 deletions(-)

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index d8b04d14310..ed756c5ccf2 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -3392,54 +3392,56 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
 ipa_update_overall_fn_summary (node);
 }
 
-/* Vector of pointers which for linked lists of clones of an original crgaph
-   edge. */
+class edge_clone_summary;
+static call_summary  *edge_clone_summaries = NULL;
 
-static vec next_edge_clone;
-static vec prev_edge_clone;
+/* Edge clone summary.  */
 
-static inline void
-grow_edge_clone_vectors (void)
+struct edge_clone_summary
 {
-  if (next_edge_clone.length ()
-  <=  (unsigned) symtab->edges_max_uid)
-next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
-  if (prev_edge_clone.length ()
-  <=  (unsigned) symtab->edges_max_uid)
-prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1);
-}
+  /* Default constructor.  */
+  edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {}
 
-/* Edge duplication hook to grow the appropriate linked list in
-   next_edge_clone. */
+  /* Default destructor.  */
+  ~edge_clone_summary ()
+  {
+if (prev_clone)
+  edge_clone_summaries->get (prev_clone)->next_clone = next_clone;
+if (next_clone)
+  edge_clone_summaries->get (next_clone)->prev_clone = prev_clone;
+  }
 
-static void
-ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
-			void *)
-{
-  grow_edge_clone_vectors ();
+  cgraph_edge *prev_clone;
+  cgraph_edge *next_clone;
+};
 
-  struct cgraph_edge *old_next = next_edge_clone[src->uid];
-  if (old_next)
-prev_edge_clone[old_next->uid] = dst;
-  prev_edge_clone[dst->uid] = src;
+class edge_clone_summary_t:
+  public call_summary 
+{
+public:
+  edge_clone_summary_t (symbol_table *symtab):
+call_summary  (symtab)
+{
+  m_initialize_when_cloning = true;
+}
 
-  next_edge_clone[dst->uid] = old_next;
-  next_edge_clone[src->uid] = dst;
-}
+  virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
+			  edge_clone_summary *src_data,
+			  edge_clone_summary *dst_data);
+};
 
-/* Hook that is called by cgraph.c when an edge is removed.  */
+/* Edge duplication hook.  */
 
-static void
-ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
+void
+edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge,
+ edge_clone_summary *src_data,
+ edge_clone_summary *dst_data)
 {
-  grow_edge_clone_vectors ();
-
-  struct cgraph_edge *prev = prev_edge_clone[cs->uid];
-  struct cgraph_edge *next = next_edge_clone[cs->uid];
-  if (prev)
-next_edge_clone[prev->uid] = next;
-  if (next)
-prev_edge_clone[next->uid] = prev;
+  if (src_data->next_clone)
+edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge;
+  dst_data->prev_clone = src_edge;
+  dst_data->next_clone = src_data->next_clone;
+  src_data->next_clone = dst_edge;
 }
 
 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
@@ -3567,7 +3569,8 @@ cgraph_edge_brings_value_p (cgraph_edge *cs,
 static inline struct cgraph_edge *
 get_next_cgraph_edge_clone (struct cgraph_edge *cs)
 {
-  return next_edge_clone[cs->uid];
+  edge_clone_summary *s = edge_clone_summaries->get (cs);
+  return s != NULL ? s->next_clone : NULL;
 }
 
 /* Given VAL that is intended for DEST, iterate over all its sources and if any
@@ -3871,7 +3874,7 @@ create_specialized_node (struct cgraph_node *node,
   bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
   for (unsigned j = 0; j < self_recursive_calls.length (); j++)
 {
-  cgraph_edge *cs = next_edge_clone[self_recursive_calls[j]->uid];
+  cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]);
   /* Cloned edges can disappear during cloning as speculation can be
 	 resolved, check that we have one and that it comes from the last
 	 cloning.  */
@@ -3881,8 +3884,8 @@ create_specialized_node (struct cgraph_node *node,
 	 edge would confuse this mechanism, so let's check that does not
 	 happen.  */
   gcc_checking_assert (!cs
-			   || !next_edge_clone[cs->uid]
-			   || next_edge_clone[cs->uid]->caller != new_node);
+			   || !get_next_cgraph_edge_clone (cs)
+			   || get_next_cgraph_edge_clone (cs)->caller != new_node);
 

[PATCH 03/14] Rename get methods in symbol-summary.h to get_create.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* config/i386/i386.c (ix86_can_inline_p): Use get_create instead
of get.
* hsa-common.c (hsa_summary_t::link_functions): Likewise.
(hsa_register_kernel): Likewise.
* hsa-common.h (hsa_gpu_implementation_p): Likewise.
* hsa-gen.c (hsa_get_host_function): Likewise.
(get_brig_function_name): Likewise.
(generate_hsa): Likewise.
(pass_gen_hsail::execute): Likewise.
* ipa-cp.c (ipcp_cloning_candidate_p): Likewise.
(devirtualization_time_bonus): Likewise.
(ipcp_propagate_stage): Likewise.
* ipa-fnsummary.c (redirect_to_unreachable): Likewise.
(edge_set_predicate): Likewise.
(evaluate_conditions_for_known_args): Likewise.
(evaluate_properties_for_edge): Likewise.
(ipa_fn_summary::reset): Likewise.
(ipa_fn_summary_t::duplicate): Likewise.
(dump_ipa_call_summary): Likewise.
(ipa_dump_fn_summary): Likewise.
(analyze_function_body): Likewise.
(compute_fn_summary): Likewise.
(estimate_edge_devirt_benefit): Likewise.
(estimate_edge_size_and_time): Likewise.
(estimate_calls_size_and_time): Likewise.
(estimate_node_size_and_time): Likewise.
(inline_update_callee_summaries): Likewise.
(remap_edge_change_prob): Likewise.
(remap_edge_summaries): Likewise.
(ipa_merge_fn_summary_after_inlining): Likewise.
(ipa_update_overall_fn_summary): Likewise.
(read_ipa_call_summary): Likewise.
(inline_read_section): Likewise.
(write_ipa_call_summary): Likewise.
(ipa_fn_summary_write): Likewise.
(ipa_free_fn_summary): Likewise.
* ipa-hsa.c (process_hsa_functions): Likewise.
(ipa_hsa_write_summary): Likewise.
(ipa_hsa_read_section): Likewise.
* ipa-icf.c (sem_function::merge): Likewise.
* ipa-inline-analysis.c (simple_edge_hints): Likewise.
(do_estimate_edge_time): Likewise.
(estimate_size_after_inlining): Likewise.
(estimate_growth): Likewise.
(growth_likely_positive): Likewise.
* ipa-inline-transform.c (clone_inlined_nodes): Likewise.
(inline_call): Likewise.
* ipa-inline.c (caller_growth_limits): Likewise.
(can_inline_edge_p): Likewise.
(can_inline_edge_by_limits_p): Likewise.
(compute_uninlined_call_time): Likewise.
(compute_inlined_call_time): Likewise.
(want_inline_small_function_p): Likewise.
(edge_badness): Likewise.
(update_caller_keys): Likewise.
(update_callee_keys): Likewise.
(recursive_inlining): Likewise.
(inline_small_functions): Likewise.
(inline_to_all_callers_1): Likewise.
(dump_overall_stats): Likewise.
(early_inline_small_functions): Likewise.
(early_inliner): Likewise.
* ipa-inline.h (estimate_edge_growth): Likewise.
* ipa-profile.c (ipa_propagate_frequency_1): Likewise.
* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
* ipa-prop.h (IPA_NODE_REF): Likewise.
(IPA_EDGE_REF): Likewise.
* ipa-pure-const.c (malloc_candidate_p): Likewise.
(propagate_malloc): Likewise.
* ipa-split.c (execute_split_functions): Likewise.
* symbol-summary.h: Rename get to get_create.
(get): Likewise.
(get_create): Likewise.
* tree-sra.c (ipa_sra_preliminary_function_checks): Likewise.

gcc/lto/ChangeLog:

2018-04-24  Martin Liska  

* lto-partition.c (add_symbol_to_partition_1): Use get_create instead
of get.
(undo_partition): Likewise.
(lto_balanced_map): Likewise.
---
 gcc/config/i386/i386.c |   2 +-
 gcc/hsa-common.c   |   6 +--
 gcc/hsa-common.h   |   3 +-
 gcc/hsa-gen.c  |  11 +++--
 gcc/ipa-cp.c   |   6 +--
 gcc/ipa-fnsummary.c| 112 -
 gcc/ipa-hsa.c  |  12 ++---
 gcc/ipa-icf.c  |   2 +-
 gcc/ipa-inline-analysis.c  |  21 +
 gcc/ipa-inline-transform.c |  12 ++---
 gcc/ipa-inline.c   |  72 +++--
 gcc/ipa-inline.h   |   4 +-
 gcc/ipa-profile.c  |   2 +-
 gcc/ipa-prop.c |   4 +-
 gcc/ipa-prop.h |   4 +-
 gcc/ipa-pure-const.c   |   6 +--
 gcc/ipa-split.c|   2 +-
 gcc/lto/lto-partition.c|   6 +--
 gcc/symbol-summary.h   |  22 +
 gcc/tree-sra.c |   2 +-
 20 files changed, 162 insertions(+), 149 deletions(-)

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0c7a6b7d98f..cba192e6cfb 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5803,7 +5803,7 @@ ix86_can_inline_p (tree caller, tree callee)
 	  for multi-versioning call optimization, so beware of
 	  ipa_fn_summaries not available.  */
 	   && (! ipa

[PATCH 12/14] Port edge_growth_cache to call_summary.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* ipa-inline-analysis.c (inline_edge_removal_hook): Remove.
(initialize_growth_caches): Remove.
(free_growth_caches): Likewise.
(do_estimate_edge_time): Use edge_growth_cache.
(do_estimate_edge_size): Likewise.
(do_estimate_edge_hints): Likewise.
* ipa-inline.c (reset_edge_caches): Likewise.
(recursive_inlining): Likewise.
(inline_small_functions): Likewise.
* ipa-inline.h (initialize_growth_caches): Remove.
(estimate_edge_size): Likewise.
(estimate_edge_time): Likewise.
(estimate_edge_hints): Likewise.
(reset_edge_growth_cache): Likewise.
* symbol-summary.h (call_summary::remove): New method.
---
 gcc/ipa-inline-analysis.c | 57 ---
 gcc/ipa-inline.c  | 31 --
 gcc/ipa-inline.h  | 44 ++--
 gcc/symbol-summary.h  | 12 ++
 4 files changed, 62 insertions(+), 82 deletions(-)

diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 2e30a6d15ba..9a7267395ea 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -51,9 +51,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 
 /* Cached node/edge growths.  */
-vec edge_growth_cache;
-static struct cgraph_edge_hook_list *edge_removal_hook_holder;
-
+call_summary *edge_growth_cache = NULL;
 
 /* Give initial reasons why inlining would fail on EDGE.  This gets either
nullified or usually overwritten by more precise reasons later.  */
@@ -80,40 +78,13 @@ initialize_inline_failed (struct cgraph_edge *e)
 }
 
 
-/* Keep edge cache consistent across edge removal.  */
-
-static void
-inline_edge_removal_hook (struct cgraph_edge *edge,
-			  void *data ATTRIBUTE_UNUSED)
-{
-  reset_edge_growth_cache (edge);
-}
-
-
-/* Initialize growth caches.  */
-
-void
-initialize_growth_caches (void)
-{
-  if (!edge_removal_hook_holder)
-edge_removal_hook_holder =
-  symtab->add_edge_removal_hook (&inline_edge_removal_hook, NULL);
-  if (symtab->edges_max_uid)
-edge_growth_cache.safe_grow_cleared (symtab->edges_max_uid);
-}
-
-
 /* Free growth caches.  */
 
 void
 free_growth_caches (void)
 {
-  if (edge_removal_hook_holder)
-{
-  symtab->remove_edge_removal_hook (edge_removal_hook_holder);
-  edge_removal_hook_holder = NULL;
-}
-  edge_growth_cache.release ();
+  delete edge_growth_cache;
+  edge_growth_cache = NULL;
 }
 
 /* Return hints derrived from EDGE.   */
@@ -188,17 +159,17 @@ do_estimate_edge_time (struct cgraph_edge *edge)
   gcc_checking_assert (time >= 0);
 
   /* When caching, update the cache entry.  */
-  if (edge_growth_cache.exists ())
+  if (edge_growth_cache != NULL)
 {
   ipa_fn_summaries->get_create (edge->callee)->min_size = min_size;
-  if ((int) edge_growth_cache.length () <= edge->uid)
-	edge_growth_cache.safe_grow_cleared (symtab->edges_max_uid);
-  edge_growth_cache[edge->uid].time = time;
-  edge_growth_cache[edge->uid].nonspec_time = nonspec_time;
+  edge_growth_cache_entry *entry
+	= edge_growth_cache->get_create (edge);
+  entry->time = time;
+  entry->nonspec_time = nonspec_time;
 
-  edge_growth_cache[edge->uid].size = size + (size >= 0);
+  entry->size = size + (size >= 0);
   hints |= simple_edge_hints (edge);
-  edge_growth_cache[edge->uid].hints = hints + 1;
+  entry->hints = hints + 1;
 }
   return time;
 }
@@ -219,10 +190,10 @@ do_estimate_edge_size (struct cgraph_edge *edge)
 
   /* When we do caching, use do_estimate_edge_time to populate the entry.  */
 
-  if (edge_growth_cache.exists ())
+  if (edge_growth_cache != NULL)
 {
   do_estimate_edge_time (edge);
-  size = edge_growth_cache[edge->uid].size;
+  size = edge_growth_cache->get (edge)->size;
   gcc_checking_assert (size);
   return size - (size > 0);
 }
@@ -260,10 +231,10 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
 
   /* When we do caching, use do_estimate_edge_time to populate the entry.  */
 
-  if (edge_growth_cache.exists ())
+  if (edge_growth_cache != NULL)
 {
   do_estimate_edge_time (edge);
-  hints = edge_growth_cache[edge->uid].hints;
+  hints = edge_growth_cache->get (edge)->hints;
   gcc_checking_assert (hints);
   return hints - 1;
 }
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 12f5ebfd582..97164716af8 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1287,9 +1287,10 @@ reset_edge_caches (struct cgraph_node *node)
   if (where->global.inlined_to)
 where = where->global.inlined_to;
 
-  for (edge = where->callers; edge; edge = edge->next_caller)
-if (edge->inline_failed)
-  reset_edge_growth_cache (edge);
+  if (edge_growth_cache != NULL)
+for (edge = where->callers; edge; edge = edge->next_caller)
+  if (edge->inline_failed)
+	edge_growt

[PATCH 14/14] Come up with cgraph_node::get_uid and make cgraph_node::uid private.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* cgraph.c (function_version_hasher::hash): Use
cgraph_node::get_uid ().
(function_version_hasher::equal):
* cgraph.h (cgraph_node::get_uid): New method.
* ipa-inline.c (update_caller_keys): Use
cgraph_node::get_uid ().
(update_callee_keys): Likewise.
* ipa-utils.c (searchc): Likewise.
(ipa_reduced_postorder): Likewise.
* lto-cgraph.c (input_node): Likewise.
* passes.c (is_pass_explicitly_enabled_or_disabled): Likewise.
* symbol-summary.h (symtab_insertion): Likewise.
(symtab_removal): Likewise.
(symtab_duplication): Likewise.
* tree-pretty-print.c (dump_function_header): Likewise.
* tree-sra.c (convert_callers_for_node): Likewise.
---
 gcc/cgraph.c|  4 ++--
 gcc/cgraph.h| 17 ++---
 gcc/ipa-inline.c|  4 ++--
 gcc/ipa-utils.c |  4 ++--
 gcc/lto-cgraph.c|  2 +-
 gcc/passes.c|  8 
 gcc/symbol-summary.h| 14 +++---
 gcc/tree-pretty-print.c |  2 +-
 gcc/tree-sra.c  |  2 +-
 9 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 572c775c14c..e7c9632a8c8 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -121,7 +121,7 @@ static GTY(()) hash_table *cgraph_fnver_htab = NULL;
 hashval_t
 function_version_hasher::hash (cgraph_function_version_info *ptr)
 {
-  int uid = ptr->this_node->uid;
+  int uid = ptr->this_node->get_uid ();
   return (hashval_t)(uid);
 }
 
@@ -130,7 +130,7 @@ bool
 function_version_hasher::equal (cgraph_function_version_info *n1,
 			   	cgraph_function_version_info *n2)
 {
-  return n1->this_node->uid == n2->this_node->uid;
+  return n1->this_node->get_uid () == n2->this_node->get_uid ();
 }
 
 /* Mark as GC root all allocated nodes.  */
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 1966893343d..a10ea04ef0d 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -97,6 +97,8 @@ class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
   symtab_node
 {
 public:
+  friend class symbol_table;
+
   /* Return name.  */
   const char *name () const;
 
@@ -890,6 +892,8 @@ struct cgraph_edge_hasher : ggc_ptr_hash
 
 struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node {
 public:
+  friend class symbol_table;
+
   /* Remove the node from cgraph and all inline clones inlined into it.
  Skip however removal of FORBIDDEN_NODE and return true if it needs to be
  removed.  This allows to call the function from outer loop walking clone
@@ -1268,6 +1272,12 @@ public:
 dump_cgraph (stderr);
   }
 
+  /* Get unique identifier of the node.  */
+  inline int get_uid ()
+  {
+return m_uid;
+  }
+
   /* Record that DECL1 and DECL2 are semantically identical function
  versions.  */
   static void record_function_versions (tree decl1, tree decl2);
@@ -1394,8 +1404,6 @@ public:
   /* How to scale counts at materialization time; used to merge
  LTO units with different number of profile runs.  */
   int count_materialization_scale;
-  /* Unique id of the node.  */
-  int uid;
   /* ID assigned by the profiling.  */
   unsigned int profile_id;
   /* Time profiler: first run of function.  */
@@ -1445,6 +1453,9 @@ public:
   unsigned indirect_call_target : 1;
 
 private:
+  /* Unique id of the node.  */
+  int m_uid;
+
   /* Worker for call_for_symbol_and_aliases.  */
   bool call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
 		void *),
@@ -2629,7 +2640,7 @@ symbol_table::allocate_cgraph_symbol (void)
   else
 node = ggc_cleared_alloc ();
 
-  node->uid = cgraph_max_uid++;
+  node->m_uid = cgraph_max_uid++;
   return node;
 }
 
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 97164716af8..9d22d208f3d 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1337,7 +1337,7 @@ update_caller_keys (edge_heap_t *heap, struct cgraph_node *node,
   if ((!node->alias && !ipa_fn_summaries->get_create (node)->inlinable)
   || node->global.inlined_to)
 return;
-  if (!bitmap_set_bit (updated_nodes, node->uid))
+  if (!bitmap_set_bit (updated_nodes, node->get_uid ()))
 return;
 
   FOR_EACH_ALIAS (node, ref)
@@ -1395,7 +1395,7 @@ update_callee_keys (edge_heap_t *heap, struct cgraph_node *node,
 	&& (callee = e->callee->ultimate_alias_target (&avail, e->caller))
 	&& ipa_fn_summaries->get_create (callee)->inlinable
 	&& avail >= AVAIL_AVAILABLE
-	&& !bitmap_bit_p (updated_nodes, callee->uid))
+	&& !bitmap_bit_p (updated_nodes, callee->get_uid ()))
 	  {
 	if (can_inline_edge_p (e, false)
 		&& want_inline_small_function_p (e, false)
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index aa586f5feb2..9985721f7da 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -86,7 +86,7 @@ searchc (struct searchc_env* env, struct cgraph_node *v,
 
   /* mark node as old */
   v_info->new_node = false;
-  splay_tree_remove (env->nodes_mar

[PATCH 00/14] Finish transition of {symbol,call}_summary.

2018-05-17 Thread marxin
Hi.

Following patch series finishes transition of IPA summary info that is
assigned either to cgraph_node or to cgraph_edge. Instead of using
a vector indexed with uid, we use summaries that are internally
implemented as hash_map.

Doing the transition we can remove summary_uid and uid property finally
happens unique identifier.

There are still places where ::get_create can be replaced with ::get,
but I made consensus with Honza that it can be done incrementally.

The series can bootstrap and survives regression tests on
ppc64le-linux-gnu and can build Libreoffice with LTO on
x86_64-linux-gnu.

Martin

marxin (14):
  Code refactoring of symtab_summary.
  Code refactoring for call_summary.
  Rename get methods in symbol-summary.h to get_create.
  Add {symbol,call}_summary::get method and use it in HSA.
  Use summaries->get where possible. Small refactoring of multiple
calls.
  Use symtab_summary in ipa-reference.c.
  Covert ipa-pure-const.c to symbol_summary.
  Convert IPA CP to symbol_summary.
  Remove cgraph_node::summary_uid and make cgraph_node::uid really
unique.
  Add call_summary::get method and m_initialize_when_cloning.
  Port IPA CP to edge_clone_summaries.
  Port edge_growth_cache to call_summary.
  Make cgraph_edge::uid really unique.
  Come up with cgraph_node::get_uid and make cgraph_node::uid private.

 gcc/cgraph.c   |  16 +-
 gcc/cgraph.h   |  47 +++--
 gcc/config/i386/i386.c |   2 +-
 gcc/hsa-common.c   |   6 +-
 gcc/hsa-common.h   |  12 +-
 gcc/hsa-gen.c  |  12 +-
 gcc/ipa-cp.c   | 116 ++--
 gcc/ipa-fnsummary.c| 116 ++--
 gcc/ipa-hsa.c  |  14 +-
 gcc/ipa-icf.c  |   2 +-
 gcc/ipa-inline-analysis.c  |  76 +++-
 gcc/ipa-inline-transform.c |  12 +-
 gcc/ipa-inline.c   |  99 ++-
 gcc/ipa-inline.h   |  51 +++---
 gcc/ipa-profile.c  |   2 +-
 gcc/ipa-prop.c |  62 +++
 gcc/ipa-prop.h |  40 +++--
 gcc/ipa-pure-const.c   | 199 -
 gcc/ipa-reference.c| 205 ++---
 gcc/ipa-split.c|   2 +-
 gcc/ipa-utils.c|   4 +-
 gcc/lto-cgraph.c   |   2 +-
 gcc/lto/lto-partition.c|  32 ++--
 gcc/passes.c   |  39 ++--
 gcc/symbol-summary.h   | 431 -
 gcc/tree-pretty-print.c|   2 +-
 gcc/tree-sra.c |   4 +-
 27 files changed, 810 insertions(+), 795 deletions(-)

-- 
2.16.3



[PATCH 04/14] Add {symbol,call}_summary::get method and use it in HSA.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* hsa-common.h (enum hsa_function_kind): Rename HSA_NONE to
HSA_INVALID.
(hsa_function_summary::hsa_function_summary): Use the new enum
value.
(hsa_gpu_implementation_p): Use hsa_summaries::get.
* hsa-gen.c (hsa_get_host_function): Likewise.
(get_brig_function_name): Likewise.
* ipa-hsa.c (process_hsa_functions): Likewise.
(ipa_hsa_write_summary): Likewise.
* symbol-summary.h (symtab_duplication): Use ::get function/
(get): New function.
---
 gcc/hsa-common.h | 15 ---
 gcc/hsa-gen.c|  9 +++--
 gcc/ipa-hsa.c| 22 +++---
 gcc/symbol-summary.h | 40 ++--
 4 files changed, 48 insertions(+), 38 deletions(-)

diff --git a/gcc/hsa-common.h b/gcc/hsa-common.h
index 849363c7b49..c72343fbdab 100644
--- a/gcc/hsa-common.h
+++ b/gcc/hsa-common.h
@@ -1208,7 +1208,7 @@ public:
 
 enum hsa_function_kind
 {
-  HSA_NONE,
+  HSA_INVALID,
   HSA_KERNEL,
   HSA_FUNCTION
 };
@@ -1234,7 +1234,7 @@ struct hsa_function_summary
 };
 
 inline
-hsa_function_summary::hsa_function_summary (): m_kind (HSA_NONE),
+hsa_function_summary::hsa_function_summary (): m_kind (HSA_INVALID),
   m_bound_function (NULL), m_gpu_implementation_p (false)
 {
 }
@@ -1244,7 +1244,10 @@ class hsa_summary_t: public function_summary 
 {
 public:
   hsa_summary_t (symbol_table *table):
-function_summary (table) { }
+function_summary (table)
+  {
+disable_insertion_hook ();
+  }
 
   /* Couple GPU and HOST as gpu-specific and host-specific implementation of
  the same function.  KIND determines whether GPU is a host-invokable kernel
@@ -1407,10 +1410,8 @@ hsa_gpu_implementation_p (tree decl)
   if (hsa_summaries == NULL)
 return false;
 
-  hsa_function_summary *s
-= hsa_summaries->get_create (cgraph_node::get_create (decl));
-
-  return s->m_gpu_implementation_p;
+  hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
+  return s != NULL && s->m_gpu_implementation_p;
 }
 
 #endif /* HSA_H */
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index b573bd57d20..5f9feb31067 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -961,9 +961,7 @@ get_symbol_for_decl (tree decl)
 tree
 hsa_get_host_function (tree decl)
 {
-  hsa_function_summary *s
-= hsa_summaries->get_create (cgraph_node::get_create (decl));
-  gcc_assert (s->m_kind != HSA_NONE);
+  hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (decl));
   gcc_assert (s->m_gpu_implementation_p);
 
   return s->m_bound_function ? s->m_bound_function->decl : NULL;
@@ -976,9 +974,8 @@ get_brig_function_name (tree decl)
 {
   tree d = decl;
 
-  hsa_function_summary *s
-= hsa_summaries->get_create (cgraph_node::get_create (d));
-  if (s->m_kind != HSA_NONE
+  hsa_function_summary *s = hsa_summaries->get (cgraph_node::get_create (d));
+  if (s != NULL
   && s->m_gpu_implementation_p
   && s->m_bound_function)
 d = s->m_bound_function->decl;
diff --git a/gcc/ipa-hsa.c b/gcc/ipa-hsa.c
index 90d193fe517..7cfeba08e58 100644
--- a/gcc/ipa-hsa.c
+++ b/gcc/ipa-hsa.c
@@ -76,13 +76,13 @@ process_hsa_functions (void)
 
   FOR_EACH_DEFINED_FUNCTION (node)
 {
-  hsa_function_summary *s = hsa_summaries->get_create (node);
+  hsa_function_summary *s = hsa_summaries->get (node);
 
   /* A linked function is skipped.  */
-  if (s->m_bound_function != NULL)
+  if (s != NULL && s->m_bound_function != NULL)
 	continue;
 
-  if (s->m_kind != HSA_NONE)
+  if (s != NULL)
 	{
 	  if (!check_warn_node_versionable (node))
 	continue;
@@ -130,11 +130,11 @@ process_hsa_functions (void)
 
   while (e)
 	{
-	  hsa_function_summary *src = hsa_summaries->get_create (node);
-	  if (src->m_kind != HSA_NONE && src->m_gpu_implementation_p)
+	  hsa_function_summary *src = hsa_summaries->get (node);
+	  if (src != NULL && src->m_gpu_implementation_p)
 	{
-	  hsa_function_summary *dst = hsa_summaries->get_create (e->callee);
-	  if (dst->m_kind != HSA_NONE && !dst->m_gpu_implementation_p)
+	  hsa_function_summary *dst = hsa_summaries->get (e->callee);
+	  if (dst != NULL && !dst->m_gpu_implementation_p)
 		{
 		  e->redirect_callee (dst->m_bound_function);
 		  if (dump_file)
@@ -174,9 +174,9 @@ ipa_hsa_write_summary (void)
lsei_next_function_in_partition (&lsei))
 {
   node = lsei_cgraph_node (lsei);
-  hsa_function_summary *s = hsa_summaries->get_create (node);
+  hsa_function_summary *s = hsa_summaries->get (node);
 
-  if (s->m_kind != HSA_NONE)
+  if (s != NULL)
 	count++;
 }
 
@@ -187,9 +187,9 @@ ipa_hsa_write_summary (void)
lsei_next_function_in_partition (&lsei))
 {
   node = lsei_cgraph_node (lsei);
-  hsa_function_summary *s = hsa_summaries->get_create (node);
+  hsa_function_summary *s = hsa_summaries->get (node);
 
-  if (s->

[PATCH 02/14] Code refactoring for call_summary.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* symbol-summary.h (release): Move definition out of class
declaration.
(symtab_removal): Likewise.
(symtab_duplication): Likewise.
---
 gcc/symbol-summary.h | 123 +--
 1 file changed, 70 insertions(+), 53 deletions(-)

diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index 13f8f04342a..a73472ef0ae 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -330,21 +330,7 @@ public:
   }
 
   /* Destruction method that can be called for GGT purpose.  */
-  void release ()
-  {
-if (m_released)
-  return;
-
-m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
-m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
-
-/* Release all summaries.  */
-typedef typename hash_map ::iterator map_iterator;
-for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
-  release ((*it).second);
-
-m_released = true;
-  }
+  void release ();
 
   /* Traverses all summarys with a function F called with
  ARG as argument.  */
@@ -369,16 +355,7 @@ public:
   }
 
   /* Release an item that is stored within map.  */
-  void release (T *item)
-  {
-if (m_ggc)
-  {
-	item->~T ();
-	ggc_free (item);
-  }
-else
-  delete item;
-  }
+  void release (T *item);
 
   /* Getter for summary callgraph edge pointer.  */
   T* get (cgraph_edge *edge)
@@ -399,37 +376,11 @@ public:
   }
 
   /* Symbol removal hook that is registered to symbol table.  */
-  static void symtab_removal (cgraph_edge *edge, void *data)
-  {
-call_summary *summary = (call_summary  *) (data);
-
-int h_uid = summary->hashable_uid (edge);
-T **v = summary->m_map.get (h_uid);
-
-if (v)
-  {
-	summary->remove (edge, *v);
-	summary->release (*v);
-	summary->m_map.remove (h_uid);
-  }
-  }
+  static void symtab_removal (cgraph_edge *edge, void *data);
 
   /* Symbol duplication hook that is registered to symbol table.  */
   static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
-  void *data)
-  {
-call_summary *summary = (call_summary  *) (data);
-T **v = summary->m_map.get (summary->hashable_uid (edge1));
-
-if (v)
-  {
-	/* This load is necessary, because we insert a new value!  */
-	T *data = *v;
-	T *duplicate = summary->allocate_new ();
-	summary->m_map.put (summary->hashable_uid (edge2), duplicate);
-	summary->duplicate (edge1, edge2, data, duplicate);
-  }
-  }
+  void *data);
 
 protected:
   /* Indication if we use ggc summary.  */
@@ -473,6 +424,72 @@ private:
   gt_pointer_operator, void *);
 };
 
+template 
+void
+call_summary::release ()
+{
+  if (m_released)
+return;
+
+  m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
+  m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
+
+  /* Release all summaries.  */
+  typedef typename hash_map ::iterator map_iterator;
+  for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
+release ((*it).second);
+
+  m_released = true;
+}
+
+template 
+void
+call_summary::release (T *item)
+{
+  if (m_ggc)
+{
+  item->~T ();
+  ggc_free (item);
+}
+  else
+delete item;
+}
+
+template 
+void
+call_summary::symtab_removal (cgraph_edge *edge, void *data)
+{
+  call_summary *summary = (call_summary  *) (data);
+
+  int h_uid = summary->hashable_uid (edge);
+  T **v = summary->m_map.get (h_uid);
+
+  if (v)
+{
+  summary->remove (edge, *v);
+  summary->release (*v);
+  summary->m_map.remove (h_uid);
+}
+}
+
+template 
+void
+call_summary::symtab_duplication (cgraph_edge *edge1,
+   cgraph_edge *edge2, void *data)
+{
+  call_summary *summary = (call_summary  *) (data);
+  T **v = summary->m_map.get (summary->hashable_uid (edge1));
+
+  if (v)
+{
+  /* This load is necessary, because we insert a new value!  */
+  T *data = *v;
+  T *duplicate = summary->allocate_new ();
+  summary->m_map.put (summary->hashable_uid (edge2), duplicate);
+  summary->duplicate (edge1, edge2, data, duplicate);
+}
+}
+
 template 
 void
 gt_ggc_mx(call_summary* const &summary)


[PATCH 08/14] Convert IPA CP to symbol_summary.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* ipa-cp.c (ipcp_store_bits_results): Use
ipcp_transformation_sum.
(ipcp_store_vr_results): Likewise.
* ipa-prop.c (ipcp_grow_transformations_if_necessary): Renamed
to ...
(ipcp_transformation_initialize): ... this.
(ipa_set_node_agg_value_chain):
(ipa_node_params_t::duplicate): Use ipcp_transformation_sum.
(write_ipcp_transformation_info): Likewise.
(read_ipcp_transformation_info): Likewise.
(ipcp_update_bits): Likewise.
(ipcp_update_vr): Likewise.
(ipcp_transform_function): Likewise.
* ipa-prop.h: Rename ipcp_transformation_summary to
ipcp_transformation.
(class ipcp_transformation_t): New function summary.
(ipcp_get_transformation_summary): Use ipcp_transformation_sum.
(ipa_get_agg_replacements_for_node): Likewise.
---
 gcc/ipa-cp.c   |  8 
 gcc/ipa-prop.c | 58 +-
 gcc/ipa-prop.h | 36 
 3 files changed, 61 insertions(+), 41 deletions(-)

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index f682ee30dec..d8b04d14310 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -4969,8 +4969,8 @@ ipcp_store_bits_results (void)
   if (!found_useful_result)
 	continue;
 
-  ipcp_grow_transformations_if_necessary ();
-  ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
+  ipcp_transformation_initialize ();
+  ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
   vec_safe_reserve_exact (ts->bits, count);
 
   for (unsigned i = 0; i < count; i++)
@@ -5042,8 +5042,8 @@ ipcp_store_vr_results (void)
   if (!found_useful_result)
 	continue;
 
-  ipcp_grow_transformations_if_necessary ();
-  ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
+  ipcp_transformation_initialize ();
+  ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
   vec_safe_reserve_exact (ts->m_vr, count);
 
   for (unsigned i = 0; i < count; i++)
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index c725b30c33d..daada4d55a5 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -55,8 +55,9 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Function summary where the parameter infos are actually stored. */
 ipa_node_params_t *ipa_node_params_sum = NULL;
-/* Vector of IPA-CP transformation data for each clone.  */
-vec *ipcp_transformations;
+
+function_summary  *ipcp_transformation_sum = NULL;
+
 /* Edge summary for IPA-CP edge information.  */
 ipa_edge_args_sum_t *ipa_edge_args_sum;
 
@@ -3729,19 +3730,18 @@ ipa_free_all_node_params (void)
   ipa_node_params_sum = NULL;
 }
 
-/* Grow ipcp_transformations if necessary.  Also allocate any necessary hash
+/* Initialize IPA CP transformation summary and also allocate any necessary hash
tables if they do not already exist.  */
 
 void
-ipcp_grow_transformations_if_necessary (void)
+ipcp_transformation_initialize (void)
 {
-  if (vec_safe_length (ipcp_transformations)
-  <= (unsigned) symtab->cgraph_max_uid)
-vec_safe_grow_cleared (ipcp_transformations, symtab->cgraph_max_uid + 1);
   if (!ipa_bits_hash_table)
 ipa_bits_hash_table = hash_table::create_ggc (37);
   if (!ipa_vr_hash_table)
 ipa_vr_hash_table = hash_table::create_ggc (37);
+  if (ipcp_transformation_sum == NULL)
+ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
 }
 
 /* Set the aggregate replacements of NODE to be AGGVALS.  */
@@ -3750,8 +3750,9 @@ void
 ipa_set_node_agg_value_chain (struct cgraph_node *node,
 			  struct ipa_agg_replacement_value *aggvals)
 {
-  ipcp_grow_transformations_if_necessary ();
-  (*ipcp_transformations)[node->uid].agg_values = aggvals;
+  ipcp_transformation_initialize ();
+  ipcp_transformation *s = ipcp_transformation_sum->get_create (node);
+  s->agg_values = aggvals;
 }
 
 /* Hook that is called by cgraph.c when an edge is removed.  Adjust reference
@@ -3915,15 +3916,14 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst,
   ipa_set_node_agg_value_chain (dst, new_av);
 }
 
-  ipcp_transformation_summary *src_trans
-= ipcp_get_transformation_summary (src);
+  ipcp_transformation *src_trans = ipcp_get_transformation_summary (src);
 
   if (src_trans)
 {
-  ipcp_grow_transformations_if_necessary ();
-  src_trans = ipcp_get_transformation_summary (src);
-  ipcp_transformation_summary *dst_trans
-	= ipcp_get_transformation_summary (dst);
+  ipcp_transformation_initialize ();
+  src_trans = ipcp_transformation_sum->get_create (src);
+  ipcp_transformation *dst_trans
+	= ipcp_transformation_sum->get_create (dst);
 
   dst_trans->bits = vec_safe_copy (src_trans->bits);
 
@@ -4565,7 +4565,7 @@ write_ipcp_transformation_info (output_block *ob, cgraph_node *node)
   streamer_write_bitpack (&bp);

[PATCH 07/14] Covert ipa-pure-const.c to symbol_summary.

2018-05-17 Thread marxin

gcc/ChangeLog:

2018-04-24  Martin Liska  

* ipa-pure-const.c (struct funct_state_d): Do it class instead
of struct.
(class funct_state_summary_t): New function_summary class.
(has_function_state): Remove.
(get_function_state): Likewise.
(set_function_state): Likewise.
(add_new_function): Likewise.
(funct_state_summary_t::insert): New function.
(duplicate_node_data): Remove.
(remove_node_data): Remove.
(funct_state_summary_t::duplicate): New function.
(register_hooks): Create new funct_state_summaries.
(pure_const_generate_summary): Use it.
(pure_const_write_summary): Likewise.
(pure_const_read_summary): Likewise.
(propagate_pure_const): Likewise.
(propagate_nothrow): Likewise.
(dump_malloc_lattice): Likewise.
(propagate_malloc): Likewise.
(execute): Do not register hooks, just remove summary
instead.
(pass_ipa_pure_const::pass_ipa_pure_const): Simplify
constructor.
---
 gcc/ipa-pure-const.c | 193 ++-
 1 file changed, 66 insertions(+), 127 deletions(-)

diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 1f624965f1a..4ac2021c04e 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -85,8 +85,20 @@ static const char *malloc_state_names[] = {"malloc_top", "malloc", "malloc_botto
 
 /* Holder for the const_state.  There is one of these per function
decl.  */
-struct funct_state_d
+class funct_state_d
 {
+public:
+  funct_state_d (): pure_const_state (IPA_NEITHER),
+state_previously_known (IPA_NEITHER), looping_previously_known (true),
+looping (true), can_throw (true), can_free (true),
+malloc_state (STATE_MALLOC_BOTTOM) {}
+
+  funct_state_d (const funct_state_d &s): pure_const_state (s.pure_const_state),
+state_previously_known (s.state_previously_known),
+looping_previously_known (s.looping_previously_known),
+looping (s.looping), can_throw (s.can_throw), can_free (s.can_free),
+malloc_state (s.malloc_state) {}
+
   /* See above.  */
   enum pure_const_state_e pure_const_state;
   /* What user set here; we can be always sure about this.  */
@@ -110,20 +122,25 @@ struct funct_state_d
   enum malloc_state_e malloc_state;
 };
 
-/* State used when we know nothing about function.  */
-static struct funct_state_d varying_state
-   = { IPA_NEITHER, IPA_NEITHER, true, true, true, true, STATE_MALLOC_BOTTOM };
-
-
 typedef struct funct_state_d * funct_state;
 
 /* The storage of the funct_state is abstracted because there is the
possibility that it may be desirable to move this to the cgraph
local info.  */
 
-/* Array, indexed by cgraph node uid, of function states.  */
+class funct_state_summary_t: public function_summary 
+{
+public:
+  funct_state_summary_t (symbol_table *symtab):
+function_summary  (symtab) {}
+
+  virtual void insert (cgraph_node *, funct_state_d *state);
+  virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node,
+			  funct_state_d *src_data,
+			  funct_state_d *dst_data);
+};
 
-static vec funct_state_vec;
+static funct_state_summary_t *funct_state_summaries = NULL;
 
 static bool gate_pure_const (void);
 
@@ -155,12 +172,6 @@ public:
 
 private:
   bool init_p;
-
-  /* Holders of ipa cgraph hooks: */
-  struct cgraph_node_hook_list *function_insertion_hook_holder;
-  struct cgraph_2node_hook_list *node_duplication_hook_holder;
-  struct cgraph_node_hook_list *node_removal_hook_holder;
-
 }; // class pass_ipa_pure_const
 
 } // anon namespace
@@ -286,48 +297,6 @@ warn_function_cold (tree decl)
 			 true, warned_about, "cold");
 }
 
-/* Return true if we have a function state for NODE.  */
-
-static inline bool
-has_function_state (struct cgraph_node *node)
-{
-  if (!funct_state_vec.exists ()
-  || funct_state_vec.length () <= (unsigned int)node->uid)
-return false;
-  return funct_state_vec[node->uid] != NULL;
-}
-
-/* Return the function state from NODE.  */
-
-static inline funct_state
-get_function_state (struct cgraph_node *node)
-{
-  if (!funct_state_vec.exists ()
-  || funct_state_vec.length () <= (unsigned int)node->uid
-  || !funct_state_vec[node->uid])
-/* We might want to put correct previously_known state into varying.  */
-return &varying_state;
- return funct_state_vec[node->uid];
-}
-
-/* Set the function state S for NODE.  */
-
-static inline void
-set_function_state (struct cgraph_node *node, funct_state s)
-{
-  if (!funct_state_vec.exists ()
-  || funct_state_vec.length () <= (unsigned int)node->uid)
- funct_state_vec.safe_grow_cleared (node->uid + 1);
-
-  /* If funct_state_vec already contains a funct_state, we have to release
- it before it's going to be ovewritten.  */
-  if (funct_state_vec[node->uid] != NULL
-  && funct_state_vec[node->uid] != &varying_state)
-free (funct_state_vec[node->uid]);
-
-  funct_state_ve

[PATCH 1/3] Add vec::reverse.

2018-05-25 Thread marxin

gcc/ChangeLog:

2018-05-25  Martin Liska  
David Malcolm  

* vec.c (test_reverse): New.
(vec_c_tests): Add new test.
* vec.h (vl_ptr>::reverse): New function.
---
 gcc/vec.c | 38 ++
 gcc/vec.h | 14 ++
 2 files changed, 52 insertions(+)

diff --git a/gcc/vec.c b/gcc/vec.c
index 2941715a34a..beb857fd838 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -476,6 +476,43 @@ test_qsort ()
   ASSERT_EQ (10, v.length ());
 }
 
+/* Verify that vec::reverse works correctly.  */
+
+static void
+test_reverse ()
+{
+  /* Reversing an empty vec ought to be a no-op.  */
+  {
+auto_vec  v;
+ASSERT_EQ (0, v.length ());
+v.reverse ();
+ASSERT_EQ (0, v.length ());
+  }
+
+  /* Verify reversing a vec with even length.  */
+  {
+auto_vec  v;
+safe_push_range (v, 0, 4);
+v.reverse ();
+ASSERT_EQ (3, v[0]);
+ASSERT_EQ (2, v[1]);
+ASSERT_EQ (1, v[2]);
+ASSERT_EQ (0, v[3]);
+ASSERT_EQ (4, v.length ());
+  }
+
+  /* Verify reversing a vec with odd length.  */
+  {
+auto_vec  v;
+safe_push_range (v, 0, 3);
+v.reverse ();
+ASSERT_EQ (2, v[0]);
+ASSERT_EQ (1, v[1]);
+ASSERT_EQ (0, v[2]);
+ASSERT_EQ (3, v.length ());
+  }
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -492,6 +529,7 @@ vec_c_tests ()
   test_unordered_remove ();
   test_block_remove ();
   test_qsort ();
+  test_reverse ();
 }
 
 } // namespace selftest
diff --git a/gcc/vec.h b/gcc/vec.h
index 2d1f468ca1c..a9f3bcf09eb 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -1389,6 +1389,7 @@ public:
   T *bsearch (const void *key, int (*compar)(const void *, const void *));
   unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
   bool contains (const T &search) const;
+  void reverse (void);
 
   bool using_auto_storage () const;
 
@@ -1900,6 +1901,19 @@ vec::contains (const T &search) const
   return m_vec ? m_vec->contains (search) : false;
 }
 
+/* Reverse content of the vector.  */
+
+template
+inline void
+vec::reverse (void)
+{
+  unsigned l = length ();
+  T *ptr = address ();
+
+  for (unsigned i = 0; i < l / 2; i++)
+std::swap (ptr[i], ptr[l - i - 1]);
+}
+
 template
 inline bool
 vec::using_auto_storage () const


[PATCH 0/3] Extend -falign-FOO=N to N[,M[,N2[,M2]]] version 9

2018-05-25 Thread marxin
Hello.

This is new version of Denis's patch series:
https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00792.html

There are quite some changes from last iteration that I would like
to mention:

- -malign-* flags are not removed, it was not welcomed and can be
eventually done independently
- in the meantime -falign-* became Optimization flags:
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84100#c4
  Due to that we need to stream the flags for LTO, we need to preperly
  compare it (strcmp) in cl_optimization_eq function.
- I changed separator from ',' to ':'. It's needed because
  #pragma GCC optimize uses comma as option separator
- I simplified default values for processor_target_table from
  "16:16:8" -> "16". Because secondary alignment will never happen.
- Per function support is working, one can see an example in added
test-case: gcc/testsuite/gcc.target/i386/falign-functions-2.c

The patchset is so far tested just on x86_64-linux-gnu with default
values. I'll do more testing, but I want to show the to get a feedback.

Thanks,
Martin

marxin (3):
  Add vec::reverse.
  Temporary remove "at least 8 byte alignment" code from x86
  Extend -falign-FOO=N to N[:M[:N2[:M2]]]

 gcc/common.opt |  16 +--
 gcc/common/config/i386/i386-common.c   |  16 ++-
 gcc/config/aarch64/aarch64-protos.h|   6 +-
 gcc/config/aarch64/aarch64.c   |  60 -
 gcc/config/alpha/alpha.c   |  12 +-
 gcc/config/arm/arm.c   |   7 +-
 gcc/config/i386/dragonfly.h|  10 +-
 gcc/config/i386/freebsd.h  |  16 +--
 gcc/config/i386/gas.h  |  10 +-
 gcc/config/i386/gnu-user.h |  16 +--
 gcc/config/i386/i386.c | 110 -
 gcc/config/i386/i386.h |   2 +-
 gcc/config/i386/iamcu.h|  16 +--
 gcc/config/i386/lynx.h |   6 +-
 gcc/config/i386/netbsd-elf.h   |   6 +-
 gcc/config/i386/openbsdelf.h   |  16 +--
 gcc/config/i386/x86-64.h   |  16 +--
 gcc/config/mips/mips.c |  18 +--
 gcc/config/rs6000/rs6000.c |  28 ++---
 gcc/config/rx/rx.c |  18 ++-
 gcc/config/rx/rx.h |   6 +-
 gcc/config/sh/sh.c |  26 ++--
 gcc/config/spu/spu.c   |   3 +-
 gcc/config/visium/visium.c |  19 ++-
 gcc/doc/invoke.texi|  66 +++---
 gcc/final.c|   6 +
 gcc/flags.h|  66 ++
 gcc/function.c |   3 +
 gcc/ipa-icf.c  |   2 +-
 gcc/lto-streamer.h |   6 +-
 gcc/lto/lto.c  |   4 +-
 gcc/optc-save-gen.awk  |  95 ++-
 gcc/opth-gen.awk   |   3 +
 gcc/opts.c | 108 ++---
 gcc/opts.h |   7 ++
 gcc/testsuite/gcc.dg/pr84100.c |   2 +-
 gcc/testsuite/gcc.target/i386/falign-functions-2.c |  30 +
 gcc/testsuite/gcc.target/i386/falign-functions.c   |   8 ++
 gcc/toplev.c   | 135 +
 gcc/toplev.h   |   7 ++
 gcc/tree-streamer-in.c |   2 +-
 gcc/tree-streamer-out.c|   2 +-
 gcc/tree.c |  20 +--
 gcc/varasm.c   |   9 +-
 gcc/vec.c  |  38 ++
 gcc/vec.h  |  14 +++
 46 files changed, 736 insertions(+), 356 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/falign-functions-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/falign-functions.c

-- 
2.16.3



[PATCH 2/3] Temporary remove "at least 8 byte alignment" code from x86

2018-05-25 Thread marxin

gcc/ChangeLog:

2017-04-18  Denys Vlasenko  

* config/i386/i386-common.c (ix86_handle_option): Remove support
for obsolete -malign-loops, -malign-jumps and -malign-functions
options.
* config/i386/i386.opt: Likewise.
---
 gcc/config/i386/dragonfly.h  | 10 ++
 gcc/config/i386/freebsd.h| 16 +---
 gcc/config/i386/gas.h| 10 ++
 gcc/config/i386/gnu-user.h   | 16 +---
 gcc/config/i386/i386.h   |  2 +-
 gcc/config/i386/iamcu.h  | 16 +---
 gcc/config/i386/lynx.h   |  6 --
 gcc/config/i386/netbsd-elf.h |  6 --
 gcc/config/i386/openbsdelf.h | 16 +---
 gcc/config/i386/x86-64.h | 16 ++--
 10 files changed, 47 insertions(+), 67 deletions(-)

diff --git a/gcc/config/i386/dragonfly.h b/gcc/config/i386/dragonfly.h
index a05b36435de..5432af9aa01 100644
--- a/gcc/config/i386/dragonfly.h
+++ b/gcc/config/i386/dragonfly.h
@@ -69,10 +69,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
 #undef  ASM_OUTPUT_MAX_SKIP_ALIGN
-#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE, LOG, MAX_SKIP)	\
-  if ((LOG) != 0) {		\
-if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG));	\
-else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE, LOG, MAX_SKIP)			\
+  if ((LOG) != 0) {			\
+if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1<<(LOG))-1)			\
+  fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
+else\
+  fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
   }
 #endif
 
diff --git a/gcc/config/i386/freebsd.h b/gcc/config/i386/freebsd.h
index 0f38e6d859a..40f7a21dfd6 100644
--- a/gcc/config/i386/freebsd.h
+++ b/gcc/config/i386/freebsd.h
@@ -92,25 +92,19 @@ along with GCC; see the file COPYING3.  If not see
 
 /* A C statement to output to the stdio stream FILE an assembler
command to advance the location counter to a multiple of 1<= (1<<(LOG))-1)		\
+	fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
+  else\
 	fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
-	/* Make sure that we have at least 8 byte alignment if > 8 byte \
-	   alignment is preferred.  */	\
-	if ((LOG) > 3			\
-	&& (1 << (LOG)) > ((MAX_SKIP) + 1)\
-	&& (MAX_SKIP) >= 7)		\
-	  fputs ("\t.p2align 3\n", (FILE));\
-  }	\
 }	\
   } while (0)
 #endif
diff --git a/gcc/config/i386/gas.h b/gcc/config/i386/gas.h
index 25d5f7809b5..e86c10588b8 100644
--- a/gcc/config/i386/gas.h
+++ b/gcc/config/i386/gas.h
@@ -68,10 +68,12 @@ along with GCC; see the file COPYING3.  If not see
 
 #ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
 #  define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
- if ((LOG) != 0) {\
-   if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
-   else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
- }
+if ((LOG) != 0) { \
+  if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1<<(LOG))-1)		\
+	fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
+  else\
+	fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
+}
 #endif
 
 /* A C statement or statements which output an assembler instruction
diff --git a/gcc/config/i386/gnu-user.h b/gcc/config/i386/gnu-user.h
index d1dad685e72..7c4d40c2eae 100644
--- a/gcc/config/i386/gnu-user.h
+++ b/gcc/config/i386/gnu-user.h
@@ -95,24 +95,18 @@ along with GCC; see the file COPYING3.  If not see
 
 /* A C statement to output to the stdio stream FILE an assembler
command to advance the location counter to a multiple of 1<= (1<<(LOG))-1)		\
+	fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
+  else\
 	fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
-	/* Make sure that we have at least 8 byte alignment if > 8 byte \
-	   alignment is preferred.  */	\
-	if ((LOG) > 3			\
-	&& (1 << (LOG)) > ((MAX_SKIP) + 1)\
-	&& (MAX_SKIP) >= 7)		\
-	  fputs ("\t.p2align 3\n", (FILE));\
-  }	\
 }	\
   } while (0)
 #endif
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 6ee99d36207..2da01394478 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2220,7 +2220,7 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
 #define ASM_OUTPUT_MAX_SKIP_PAD(FILE, LOG, MAX_SKIP)			\
   if ((LOG) != 0)			\
 {	\
-  if ((MAX_SKIP) == 0)		\
+  if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1<<(LOG))-1)		\
 fprintf ((FILE), "\t.p2align %d\n", (LOG));			\
   else\
 fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP));	\
diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h
index b30132f377a..07ecbec60d3 100644
--- a/gcc/config/i386/iamcu.h
+++ b/gcc/config/i386/iamcu.h
@@ -62,23 +62,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 /* A C stateme

[PATCH 3/3] Extend -falign-FOO=N to N[:M[:N2[:M2]]]

2018-05-25 Thread marxin

gcc/ChangeLog:

2018-05-25  Denys Vlasenko  
Martin Liska  

PR middle-end/66240
PR target/45996
PR c/84100
* common.opt: Rename align options with 'str_' prefix.
* common/config/i386/i386-common.c (set_malign_value): New
function.
(ix86_handle_option): Use it to set -falign-* options/
* config/aarch64/aarch64-protos.h (struct tune_params): Change
type from int to string.
* config/aarch64/aarch64.c: Update default values from int
to string.
* config/alpha/alpha.c (alpha_override_options_after_change):
Likewise.
* config/arm/arm.c (arm_override_options_after_change_1): Likewise.
* config/i386/dragonfly.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Print
max skip conditionally.
* config/i386/freebsd.h (SUBALIGN_LOG): New.
(ASM_OUTPUT_MAX_SKIP_ALIGN): Print
max skip conditionally.
* config/i386/gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Print
max skip conditionally.
* config/i386/gnu-user.h (SUBALIGN_LOG): New.
(ASM_OUTPUT_MAX_SKIP_ALIGN): Print
max skip conditionally.
* config/i386/i386.c (struct ptt): Change type from int to
string.
(ix86_default_align): Set default values.
* config/i386/i386.h (ASM_OUTPUT_MAX_SKIP_PAD): Print
max skip conditionally.
* config/i386/iamcu.h (SUBALIGN_LOG): New.
(ASM_OUTPUT_MAX_SKIP_ALIGN):
* config/i386/lynx.h (ASM_OUTPUT_MAX_SKIP_ALIGN):
* config/i386/netbsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Print
max skip conditionally.
* config/i386/openbsdelf.h (SUBALIGN_LOG): New.
(ASM_OUTPUT_MAX_SKIP_ALIGN) Print max skip conditionally.:
* config/i386/x86-64.h (SUBALIGN_LOG): New.
(ASM_OUTPUT_MAX_SKIP_ALIGN): Print
max skip conditionally.
(ASM_OUTPUT_MAX_SKIP_PAD): Likewise.
* config/mips/mips.c (mips_set_compression_mode): Change
type of constants.
* config/rs6000/rs6000.c (rs6000_option_override_internal):
Likewise.
* config/rx/rx.c (rx_option_override): Likewise.
* config/rx/rx.h (JUMP_ALIGN): Use align_jumps_log.
(LABEL_ALIGN): Use align_labels_log.
(LOOP_ALIGN): Use align_loops_align.
* config/sh/sh.c (sh_override_options_after_change):
Change type of constants.
* config/spu/spu.c (spu_sched_init): Likewise.
* config/visium/visium.c (visium_option_override): Likewise.
* doc/invoke.texi: Document extended format of -falign-*.
* final.c: Use align_labels alignment.
* flags.h (struct target_flag_state): Change type to use
align_flags.
(struct align_flags_tuple): New.
(struct align_flags): Likewise.
(align_loops_log): Redefine macro to use new types.
(align_loops_max_skip): Redefine macro to use new types.
(align_jumps_log): Redefine macro to use new types.
(align_jumps_max_skip): Redefine macro to use new types.
(align_labels_log): Redefine macro to use new types.
(align_labels_max_skip): Redefine macro to use new types.
(align_functions_log): Redefine macro to use new types.
(align_loops): Redefine macro to use new types.
(align_jumps): Redefine macro to use new types.
(align_labels): Redefine macro to use new types.
(align_functions): Redefine macro to use new types.
(align_functions_max_skip): Redefine macro to use new types.
* function.c (invoke_set_current_function_hook): Propagate
alignment values from flags to global variables default in
topleev.h.
* ipa-icf.c (sem_function::equals_wpa): Use
cl_optimization_option_eq instead of memcmp.
* lto-streamer.h (cl_optimization_stream_out): Support streaming
of string types.
(cl_optimization_stream_in): Likewise.
* optc-save-gen.awk: Support strings in cl_optimization.
* opth-gen.awk: Likewise.
* opts.c (finish_options): Remove error checking of invalid
value ranges.
(MAX_CODE_ALIGN): Remove.
(MAX_CODE_ALIGN_VALUE): Likewise.
(parse_and_check_align_values): New function.
(check_alignment_argument): Likewise.
(common_handle_option): Use check_alignment_argument.
* opts.h (parse_and_check_align_values): Declare.
* toplev.c (init_alignments): Remove.
(read_log_maxskip): New.
(parse_N_M): Likewise.
(parse_alignment_opts): Likewise.
(backend_init_target): Remove usage of init_alignments.
* toplev.h (parse_alignment_opts): Declare.
* tree-streamer-in.c (streamer_read_tree_bitfields): Add new
argument.
* tree-streamer-out.c (streamer_write_tree_bitfields): Likewise.
* tree.c (cl_option_hasher::equal): New.
* varasm.c: Use new global macros.

gcc/lto/ChangeLog:

2018-05-25  Ma

[PATCH 4/4] Update a bit dump format.

2019-06-04 Thread marxin

gcc/ChangeLog:

2019-06-04  Martin Liska  

* value-prof.c (dump_histogram_value): Change dump format.
(gimple_mod_subtract_transform): Remove legacy comment.
---
 gcc/value-prof.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 25b957d0c0a..5de91595811 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -230,18 +230,21 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
 case HIST_TYPE_INTERVAL:
   if (hist->hvalue.counters)
 	{
-	  fprintf (dump_file, "Interval counter range %d -- %d",
+	  fprintf (dump_file, "Interval counter range [%d,%d]: [",
 		   hist->hdata.intvl.int_start,
 		   (hist->hdata.intvl.int_start
 		+ hist->hdata.intvl.steps - 1));
 
 	  unsigned int i;
-	  fprintf (dump_file, " [");
 	  for (i = 0; i < hist->hdata.intvl.steps; i++)
-	fprintf (dump_file, " %d:%" PRId64,
-		 hist->hdata.intvl.int_start + i,
-		 (int64_t) hist->hvalue.counters[i]);
-	  fprintf (dump_file, " ] outside range:%" PRId64 ".\n",
+	{
+	  fprintf (dump_file, "%d:%" PRId64,
+		   hist->hdata.intvl.int_start + i,
+		   (int64_t) hist->hvalue.counters[i]);
+	  if (i != hist->hdata.intvl.steps - 1)
+		fprintf (dump_file, ", ");
+	}
+	  fprintf (dump_file, "] outside range: %" PRId64 ".\n",
 		   (int64_t) hist->hvalue.counters[i]);
 	}
   break;
@@ -1094,7 +1097,6 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si)
   count1 = histogram->hvalue.counters[0];
   count2 = histogram->hvalue.counters[1];
 
-  /* Compute probability of taking the optimal path.  */
   if (check_counter (stmt, "interval", &count1, &all, gimple_bb (stmt)->count))
 {
   gimple_remove_histogram_value (cfun, stmt, histogram);


[PATCH 1/4] Remove indirect call top N counter type.

2019-06-04 Thread marxin

gcc/ChangeLog:

2019-06-04  Martin Liska  

* doc/invoke.texi: Remove param.
* gcov-counter.def (GCOV_COUNTER_ICALL_TOPNV):
Remove.
* gcov-io.h (GCOV_ICALL_TOPN_VAL): Likewise.
(GCOV_ICALL_TOPN_NCOUNTS): Likewise.
* params.def (PARAM_INDIR_CALL_TOPN_PROFILE): Likewise.
* profile.c (instrument_values): Remove
HIST_TYPE_INDIR_CALL_TOPN.
* tree-profile.c (init_ic_make_global_vars):
Always build __gcov_indirect_call only.
(gimple_init_gcov_profiler): Remove usage
of PARAM_INDIR_CALL_TOPN_PROFILE.
(gimple_gen_ic_profiler): Likewise.
* value-prof.c (dump_histogram_value): Likewise.
(stream_in_histogram_value): Likewise.
(gimple_indirect_call_to_profile): Likewise.
(gimple_find_values_to_profile): Likewise.
* value-prof.h (enum hist_type): Likewise.

libgcc/ChangeLog:

2019-06-04  Martin Liska  

* Makefile.in: Remove usage of
_gcov_merge_icall_topn.
* libgcov-driver.c (gcov_sort_n_vals): Remove.
(gcov_sort_icall_topn_counter): Likewise.
(gcov_sort_topn_counter_arrays): Likewise.
(dump_one_gcov): Remove call to gcov_sort_topn_counter_arrays.
* libgcov-merge.c (__gcov_merge_icall_topn): Remove.
* libgcov-profiler.c (__gcov_topn_value_profiler_body):
Likewise.
(GCOV_ICALL_COUNTER_CLEAR_THRESHOLD): Remove.
(struct indirect_call_tuple): Remove.
(__gcov_indirect_call_topn_profiler): Remove.
* libgcov-util.c (__gcov_icall_topn_counter_op): Remove.
* libgcov.h (gcov_sort_n_vals): Remove.
(L_gcov_merge_icall_topn): Likewise.
(__gcov_merge_icall_topn): Likewise.
(__gcov_indirect_call_topn_profiler): Likewise.
---
 gcc/doc/invoke.texi   |   3 -
 gcc/gcov-counter.def  |   3 -
 gcc/gcov-io.h |   6 --
 gcc/params.def|   8 ---
 gcc/profile.c |   1 -
 gcc/tree-profile.c|  14 +---
 gcc/value-prof.c  |  32 +
 gcc/value-prof.h  |   2 -
 libgcc/Makefile.in|   5 +-
 libgcc/libgcov-driver.c   |  80 ---
 libgcc/libgcov-merge.c|  62 --
 libgcc/libgcov-profiler.c | 133 --
 libgcc/libgcov-util.c |  19 --
 libgcc/libgcov.h  |   7 --
 14 files changed, 5 insertions(+), 370 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 91c9bb89651..50e50e39413 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -12140,9 +12140,6 @@ will not try to thread through its block.
 Maximum number of nested calls to search for control dependencies
 during uninitialized variable analysis.
 
-@item indir-call-topn-profile
-Track top N target addresses in indirect-call profile.
-
 @item max-once-peeled-insns
 The maximum number of insns of a peeled loop that rolls only once.
 
diff --git a/gcc/gcov-counter.def b/gcc/gcov-counter.def
index 3a0e620987a..b0596c8dc6b 100644
--- a/gcc/gcov-counter.def
+++ b/gcc/gcov-counter.def
@@ -49,6 +49,3 @@ DEF_GCOV_COUNTER(GCOV_COUNTER_IOR, "ior", _ior)
 
 /* Time profile collecting first run of a function */
 DEF_GCOV_COUNTER(GCOV_TIME_PROFILER, "time_profiler", _time_profile)
-
-/* Top N value tracking for indirect calls.  */
-DEF_GCOV_COUNTER(GCOV_COUNTER_ICALL_TOPNV, "indirect_call_topn", _icall_topn)
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index 9edb2923982..69c9a73dba8 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -266,12 +266,6 @@ GCOV_COUNTERS
 #define GCOV_N_VALUE_COUNTERS \
   (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1)
 
-/* The number of hottest callees to be tracked.  */
-#define GCOV_ICALL_TOPN_VAL  2
-
-/* The number of counter entries per icall callsite.  */
-#define GCOV_ICALL_TOPN_NCOUNTS (1 + GCOV_ICALL_TOPN_VAL * 4)
-
 /* Convert a counter index to a tag.  */
 #define GCOV_TAG_FOR_COUNTER(COUNT)\
 	(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
diff --git a/gcc/params.def b/gcc/params.def
index 6b7f7eb5bae..b4a4e4a4190 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -992,14 +992,6 @@ DEFPARAM (PARAM_PROFILE_FUNC_INTERNAL_ID,
 	  "Use internal function id in profile lookup.",
 	  0, 0, 1)
 
-/* When the parameter is 1, track the most frequent N target
-   addresses in indirect-call profile. This disables
-   indirect_call_profiler_v3 which tracks single target.  */
-DEFPARAM (PARAM_INDIR_CALL_TOPN_PROFILE,
-	  "indir-call-topn-profile",
-	  "Track top N target addresses in indirect-call profile.",
-	  0, 0, 1)
-
 /* Avoid SLP vectorization of large basic blocks.  */
 DEFPARAM (PARAM_SLP_MAX_INSNS_IN_BB,
 	  "slp-max-insns-in-bb",
diff --git a/gcc/profile.c b/gcc/profile.c
index a1dba1ac8fb..9aff9ef2b21 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -172,7 +172,6 @@ instrument_values (histogram_values values)
 	  break;
 
  	case HIST_TYPE_INDIR_CALL:
- 	case HIST_TYPE_INDIR_CALL_TOPN:
  

[PATCH 3/4] Dump histograms only if present.

2019-06-04 Thread marxin

gcc/ChangeLog:

2019-06-04  Martin Liska  

* value-prof.c (dump_histogram_value): Print histogram values
only if present.
---
 gcc/value-prof.c | 72 +++-
 1 file changed, 28 insertions(+), 44 deletions(-)

diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index e893ca084c9..25b957d0c0a 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -228,42 +228,38 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
   switch (hist->type)
 {
 case HIST_TYPE_INTERVAL:
-  fprintf (dump_file, "Interval counter range %d -- %d",
-	   hist->hdata.intvl.int_start,
-	   (hist->hdata.intvl.int_start
-	+ hist->hdata.intvl.steps - 1));
   if (hist->hvalue.counters)
 	{
-	   unsigned int i;
-	   fprintf (dump_file, " [");
-   for (i = 0; i < hist->hdata.intvl.steps; i++)
-	 fprintf (dump_file, " %d:%" PRId64,
-		  hist->hdata.intvl.int_start + i,
-		  (int64_t) hist->hvalue.counters[i]);
-	   fprintf (dump_file, " ] outside range:%" PRId64,
-		(int64_t) hist->hvalue.counters[i]);
+	  fprintf (dump_file, "Interval counter range %d -- %d",
+		   hist->hdata.intvl.int_start,
+		   (hist->hdata.intvl.int_start
+		+ hist->hdata.intvl.steps - 1));
+
+	  unsigned int i;
+	  fprintf (dump_file, " [");
+	  for (i = 0; i < hist->hdata.intvl.steps; i++)
+	fprintf (dump_file, " %d:%" PRId64,
+		 hist->hdata.intvl.int_start + i,
+		 (int64_t) hist->hvalue.counters[i]);
+	  fprintf (dump_file, " ] outside range:%" PRId64 ".\n",
+		   (int64_t) hist->hvalue.counters[i]);
 	}
-  fprintf (dump_file, ".\n");
   break;
 
 case HIST_TYPE_POW2:
-  fprintf (dump_file, "Pow2 counter ");
   if (hist->hvalue.counters)
-	{
-	   fprintf (dump_file, "pow2:%" PRId64
-		" nonpow2:%" PRId64,
-		(int64_t) hist->hvalue.counters[1],
-		(int64_t) hist->hvalue.counters[0]);
-	}
-  fprintf (dump_file, ".\n");
+	fprintf (dump_file, "Pow2 counter pow2:%" PRId64
+		 " nonpow2:%" PRId64 ".\n",
+		 (int64_t) hist->hvalue.counters[1],
+		 (int64_t) hist->hvalue.counters[0]);
   break;
 
 case HIST_TYPE_SINGLE_VALUE:
 case HIST_TYPE_INDIR_CALL:
-  fprintf (dump_file, (hist->type == HIST_TYPE_SINGLE_VALUE
-			   ? "Single values " : "Indirect call "));
   if (hist->hvalue.counters)
 	{
+	  fprintf (dump_file, (hist->type == HIST_TYPE_SINGLE_VALUE
+			   ? "Single values " : "Indirect call "));
 	  for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++)
 	{
 	  fprintf (dump_file, "[%" PRId64 ":%" PRId64 "]",
@@ -272,40 +268,28 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
 	  if (i != GCOV_DISK_SINGLE_VALUES - 1)
 		fprintf (dump_file, ", ");
 	}
+	  fprintf (dump_file, ".\n");
 	}
-  fprintf (dump_file, ".\n");
   break;
 
 case HIST_TYPE_AVERAGE:
-  fprintf (dump_file, "Average value ");
   if (hist->hvalue.counters)
-	{
-	   fprintf (dump_file, "sum:%" PRId64
-		" times:%" PRId64,
-		(int64_t) hist->hvalue.counters[0],
-		(int64_t) hist->hvalue.counters[1]);
-	}
-  fprintf (dump_file, ".\n");
+	fprintf (dump_file, "Average value sum:%" PRId64
+		 " times:%" PRId64 ".\n",
+		 (int64_t) hist->hvalue.counters[0],
+		 (int64_t) hist->hvalue.counters[1]);
   break;
 
 case HIST_TYPE_IOR:
-  fprintf (dump_file, "IOR value ");
   if (hist->hvalue.counters)
-	{
-	   fprintf (dump_file, "ior:%" PRId64,
-		(int64_t) hist->hvalue.counters[0]);
-	}
-  fprintf (dump_file, ".\n");
+	fprintf (dump_file, "IOR value ior:%" PRId64 ".\n",
+		 (int64_t) hist->hvalue.counters[0]);
   break;
 
 case HIST_TYPE_TIME_PROFILE:
-  fprintf (dump_file, "Time profile ");
   if (hist->hvalue.counters)
-  {
-fprintf (dump_file, "time:%" PRId64,
- (int64_t) hist->hvalue.counters[0]);
-  }
-  fprintf (dump_file, ".\n");
+	fprintf (dump_file, "Time profile time:%" PRId64 ".\n",
+		 (int64_t) hist->hvalue.counters[0]);
   break;
 case HIST_TYPE_MAX:
   gcc_unreachable ();


[PATCH 2/4] Implement N disk counters for single value and indirect call counters.

2019-06-04 Thread marxin

gcc/ChangeLog:

2019-06-04  Martin Liska  

* gcov-io.h (GCOV_DISK_SINGLE_VALUES): New.
(GCOV_SINGLE_VALUE_COUNTERS): Likewise.
* ipa-profile.c (ipa_profile_generate_summary):
Use get_most_common_single_value.
* tree-profile.c (gimple_init_gcov_profiler):
Instrument with __gcov_one_value_profiler_v2
and __gcov_indirect_call_profiler_v4.
* value-prof.c (dump_histogram_value):
Print all values for HIST_TYPE_SINGLE_VALUE.
(stream_in_histogram_value): Set number of
counters for HIST_TYPE_SINGLE_VALUE.
(get_most_common_single_value): New.
(gimple_divmod_fixed_value_transform):
Use get_most_common_single_value.
(gimple_ic_transform): Likewise.
(gimple_stringops_transform): Likewise.
(gimple_find_values_to_profile): Set number
of counters for HIST_TYPE_SINGLE_VALUE.
* value-prof.h (get_most_common_single_value):
New.

libgcc/ChangeLog:

2019-06-04  Martin Liska  

* Makefile.in: Add __gcov_one_value_profiler_v2 and
__gcov_indirect_call_profiler_v4.
* libgcov-merge.c (__gcov_merge_single): Change
function signature.
(merge_single_value_set): New.
* libgcov-profiler.c (__gcov_one_value_profiler_body):
Do not update counters[2].
(__gcov_one_value_profiler): Remove.
(__gcov_one_value_profiler_atomic): Rename to ...
(__gcov_one_value_profiler_v2): ... this.
(__gcov_indirect_call_profiler_v3): Rename to ...
(__gcov_indirect_call_profiler_v4): ... this.
* libgcov.h (__gcov_one_value_profiler): Remove.
(__gcov_one_value_profiler_atomic): Remove.
(__gcov_indirect_call_profiler_v3): Remove.
(__gcov_one_value_profiler_v2): New.
(__gcov_indirect_call_profiler_v4): New.
---
 gcc/gcov-io.h |   7 +++
 gcc/ipa-profile.c |  13 +++--
 gcc/tree-profile.c|   9 ++-
 gcc/value-prof.c  | 120 --
 gcc/value-prof.h  |   2 +
 libgcc/Makefile.in|   5 +-
 libgcc/libgcov-merge.c|  77 
 libgcc/libgcov-profiler.c |  43 +++---
 libgcc/libgcov.h  |   5 +-
 9 files changed, 147 insertions(+), 134 deletions(-)

diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index 69c9a73dba8..161518176a0 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -266,6 +266,13 @@ GCOV_COUNTERS
 #define GCOV_N_VALUE_COUNTERS \
   (GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1)
 
+/* Number of single value histogram values that live
+   on disk representation.  */
+#define GCOV_DISK_SINGLE_VALUES 4
+
+/* Total number of single value counters.  */
+#define GCOV_SINGLE_VALUE_COUNTERS (2 * GCOV_DISK_SINGLE_VALUES)
+
 /* Convert a counter index to a tag.  */
 #define GCOV_TAG_FOR_COUNTER(COUNT)\
 	(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c
index de9563d808c..fc2ffbd84f7 100644
--- a/gcc/ipa-profile.c
+++ b/gcc/ipa-profile.c
@@ -191,17 +191,18 @@ ipa_profile_generate_summary (void)
 		 takes away bad histograms.  */
 		  if (h)
 		{
-		  /* counter 0 is target, counter 1 is number of execution we called target,
-			 counter 2 is total number of executions.  */
-		  if (h->hvalue.counters[2])
+		  gcov_type val, count;
+		  if (get_most_common_single_value (h, &val, &count))
 			{
 			  struct cgraph_edge * e = node->get_edge (stmt);
 			  if (e && !e->indirect_unknown_callee)
 			continue;
-			  e->indirect_info->common_target_id
-			= h->hvalue.counters [0];
+
+			  gcov_type all
+			= gimple_bb (stmt)->count.ipa ().to_gcov_type ();
+			  e->indirect_info->common_target_id = val;
 			  e->indirect_info->common_target_probability
-			= GCOV_COMPUTE_SCALE (h->hvalue.counters [1], h->hvalue.counters [2]);
+			= GCOV_COMPUTE_SCALE (count, all);
 			  if (e->indirect_info->common_target_probability > REG_BR_PROB_BASE)
 			{
 			  if (dump_file)
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index f2cf4047579..008a1271979 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -165,10 +165,9 @@ gimple_init_gcov_profiler (void)
 	  = build_function_type_list (void_type_node,
 	  gcov_type_ptr, gcov_type_node,
 	  NULL_TREE);
-  fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
-  tree_one_value_profiler_fn = build_fn_decl (fn_name,
-		  one_value_profiler_fn_type);
-  free (CONST_CAST (char *, fn_name));
+  tree_one_value_profiler_fn
+	= build_fn_decl ("__gcov_one_value_profiler_v2",
+			 one_value_profiler_fn_type);
   TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
   DECL_ATTRIBUTES (tree_one_value_profiler_fn)
 	= tree_cons (get_identifier ("leaf"), NULL,
@@ -182,7 +181,7 @@ gimple_init_gcov_profiler (void)
 	  gcov_type_node,
 	  ptr_type_node,
 	  NULL_TREE);

[PATCH 4/7] Apply LOCAL_PATCHES and remove not used ones.

2018-10-25 Thread marxin

libsanitizer/ChangeLog:

2018-10-24  Martin Liska  

* LOCAL_PATCHES: Update patch list.
* asan/asan_globals.cc (CheckODRViolationViaIndicator): Apply
patches from GCC's trunk.
(CheckODRViolationViaPoisoning): Likewise.
(RegisterGlobal): Likewise.
* sanitizer_common/sanitizer_mac.cc (defined): Likewise.
* sanitizer_common/sanitizer_stacktrace.cc (GetCanonicFrame): Likewise.
* ubsan/ubsan_handlers.cc (__ubsan::__ubsan_handle_cfi_bad_icall): 
Likewise.
(__ubsan::__ubsan_handle_cfi_bad_icall_abort): Likewise.
* ubsan/ubsan_handlers.h (struct CFIBadIcallData): Likewise.
(struct CFICheckFailData): Likewise.
(RECOVERABLE): Likewise.
---
 libsanitizer/LOCAL_PATCHES|  2 --
 libsanitizer/asan/asan_globals.cc | 19 ---
 .../sanitizer_common/sanitizer_mac.cc |  2 +-
 .../sanitizer_common/sanitizer_stacktrace.cc  |  4 ++--
 libsanitizer/ubsan/ubsan_handlers.cc  | 15 +++
 libsanitizer/ubsan/ubsan_handlers.h   |  8 
 6 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/libsanitizer/LOCAL_PATCHES b/libsanitizer/LOCAL_PATCHES
index 822e2f34ad9..69544c33a89 100644
--- a/libsanitizer/LOCAL_PATCHES
+++ b/libsanitizer/LOCAL_PATCHES
@@ -1,6 +1,4 @@
-r241978
 r241980
 r241981
 r242478
 r242633
-r243014
diff --git a/libsanitizer/asan/asan_globals.cc b/libsanitizer/asan/asan_globals.cc
index 34963156346..a59a2dc27a4 100644
--- a/libsanitizer/asan/asan_globals.cc
+++ b/libsanitizer/asan/asan_globals.cc
@@ -147,23 +147,6 @@ static void CheckODRViolationViaIndicator(const Global *g) {
   }
 }
 
-// Check ODR violation for given global G by checking if it's already poisoned.
-// We use this method in case compiler doesn't use private aliases for global
-// variables.
-static void CheckODRViolationViaPoisoning(const Global *g) {
-  if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
-// This check may not be enough: if the first global is much larger
-// the entire redzone of the second global may be within the first global.
-for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
-  if (g->beg == l->g->beg &&
-  (flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
-  !IsODRViolationSuppressed(g->name))
-ReportODRViolation(g, FindRegistrationSite(g),
-   l->g, FindRegistrationSite(l->g));
-}
-  }
-}
-
 // Clang provides two different ways for global variables protection:
 // it can poison the global itself or its private alias. In former
 // case we may poison same symbol multiple times, that can help us to
@@ -211,8 +194,6 @@ static void RegisterGlobal(const Global *g) {
 // where two globals with the same name are defined in different modules.
 if (UseODRIndicator(g))
   CheckODRViolationViaIndicator(g);
-else
-  CheckODRViolationViaPoisoning(g);
   }
   if (CanPoisonMemory())
 PoisonRedZones(*g);
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc
index df7a897e45a..28b2906e226 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc
@@ -35,7 +35,7 @@
 extern char **environ;
 #endif
 
-#if defined(__has_include) && __has_include()
+#if defined(__has_include) && __has_include() && defined(__BLOCKS__)
 #define SANITIZER_OS_TRACE 1
 #include 
 #else
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
index db51f5926d2..699fd9fdce0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
@@ -59,8 +59,8 @@ static inline uhwptr *GetCanonicFrame(uptr bp,
   // Nope, this does not look right either. This means the frame after next does
   // not have a valid frame pointer, but we can still extract the caller PC.
   // Unfortunately, there is no way to decide between GCC and LLVM frame
-  // layouts. Assume LLVM.
-  return bp_prev;
+  // layouts. Assume GCC.
+  return bp_prev - 1;
 #else
   return (uhwptr*)bp;
 #endif
diff --git a/libsanitizer/ubsan/ubsan_handlers.cc b/libsanitizer/ubsan/ubsan_handlers.cc
index 927ad4c9531..f67b9e30fb9 100644
--- a/libsanitizer/ubsan/ubsan_handlers.cc
+++ b/libsanitizer/ubsan/ubsan_handlers.cc
@@ -771,6 +771,21 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
 
 }  // namespace __ubsan
 
+void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *CallData,
+   ValueHandle Function) {
+  GET_REPORT_OPTIONS(false);
+  CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
+  handleCFIBadIcall(&Data, Function, Opts);
+}
+
+void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *CallData,
+ ValueHandle 

[PATCH 1/7] Update merge script and HOWTO_MERGE documentation.

2018-10-25 Thread marxin

libsanitizer/ChangeLog:

2018-10-24  Martin Liska  

* HOWTO_MERGE: Enhance documentation.
* merge.sh: Add support for git as well.
---
 libsanitizer/HOWTO_MERGE | 9 ++---
 libsanitizer/merge.sh| 6 --
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/libsanitizer/HOWTO_MERGE b/libsanitizer/HOWTO_MERGE
index 81121aa385f..a47a26a4a74 100644
--- a/libsanitizer/HOWTO_MERGE
+++ b/libsanitizer/HOWTO_MERGE
@@ -3,7 +3,8 @@ track various ABI changes and GCC-specific patches carefully.  Here is a
 general list of actions required to perform the merge:
 
 * Checkout recent GCC tree.
-* Run merge.sh script from libsanitizer directory.
+* Run merge.sh script from libsanitizer directory.  The script accepts one
+  argument that is control version system (svn or git).
 * Modify Makefile.am files into asan/tsan/lsan/ubsan/sanitizer_common/interception
   directories if needed.  In particular, you may need to add new source files
   and remove old ones in source files list, add new flags to {C, CXX}FLAGS if
@@ -20,7 +21,7 @@ general list of actions required to perform the merge:
 * Update ASan testsuite with corresponding tests from lib/asan/tests directory.
   Not all tests can be migrated easily, so you don't need them all to be adapted.
 * Modify configure.ac file if needed (e.g. if you need to add link against new
-  library for sanitizer lilbs).
+  library for sanitizer libs).
 * Add new target platforms in configure.tgt script if needed.
 * Bump SONAME for sanitizer libraries in asan/tsan/ubsan libtool-version files
   if ABI has changed.
@@ -30,7 +31,9 @@ general list of actions required to perform the merge:
 * Run regression testing on at least three platforms (e.g. x86-linux-gnu, x86_64-linux-gnu,
   aarch64-linux-gnu, arm-linux-gnueabi).
 * Run {A, UB}San bootstrap on at least three platforms.
-* Compare ABI of corresponding libclang_rt-asan and newly build libasan libraries.
+* Compare ABI of corresponding libclang_rt.asan and newly build libasan libraries.
+  Similarly you can compare latest GCC release with the newly built libraries
+  (libasan.so.*, libubsan.so.*, libtsan.so*).
   You can use a pretty good libabigail tool (https://sourceware.org/libabigail/index.html)
   to perform such a comparision.  Note, that the list of exported symbols may differ,
   e.g. because libasan currently does not include UBSan runtime.
diff --git a/libsanitizer/merge.sh b/libsanitizer/merge.sh
index 2e5ec2527b8..fa340bedbac 100755
--- a/libsanitizer/merge.sh
+++ b/libsanitizer/merge.sh
@@ -4,6 +4,8 @@
 
 # This script merges libsanitizer sources from upstream.
 
+VCS=${1:-svn}
+
 get_upstream() {
   rm -rf upstream
   #cp -rf orig upstream
@@ -46,10 +48,10 @@ merge() {
 elif [ -f $upstream_path/$f ]; then
   echo "FOUND IN UPSTREAM :" $f
   cp -v $upstream_path/$f $local_path
-  svn add $local_path/$f
+  $VCS add $local_path/$f
 elif [ -f $local_path/$f ]; then
   echo "FOUND IN LOCAL:" $f
-  svn remove $local_path/$f
+  $VCS rm $local_path/$f
 fi
   done
 


[PATCH 3/7] Update build system: include new files and run autoheader, autoconf, automake

2018-10-25 Thread marxin

libsanitizer/ChangeLog:

2018-10-24  Martin Liska  

* config.h.in: Regenerate.
* configure: Likewise.
* sanitizer_common/Makefile.am: Include new files, remove old
files.
* sanitizer_common/Makefile.in: Regenerate.
* ubsan/Makefile.am: Include new files, remove old
files.
* ubsan/Makefile.in: Likewise.
---
 libsanitizer/config.h.in  |  6 +++---
 libsanitizer/configure|  8 
 libsanitizer/sanitizer_common/Makefile.am |  4 +++-
 libsanitizer/sanitizer_common/Makefile.in | 17 +++--
 libsanitizer/ubsan/Makefile.am|  1 +
 libsanitizer/ubsan/Makefile.in|  8 +---
 6 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/libsanitizer/config.h.in b/libsanitizer/config.h.in
index f716c2421cf..a64b6a16a17 100644
--- a/libsanitizer/config.h.in
+++ b/libsanitizer/config.h.in
@@ -40,12 +40,12 @@
 /* Define to 1 if you have the  header file. */
 #undef HAVE_LINK_H
 
-/* Define to 1 if you have the  header file. */
-#undef HAVE_MEMORY_H
-
 /* Define to 1 if you have the `lstat' function. */
 #undef HAVE_LSTAT
 
+/* Define to 1 if you have the  header file. */
+#undef HAVE_MEMORY_H
+
 /* Define to 1 if you have the `readlink' function. */
 #undef HAVE_READLINK
 
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 5836450063d..31726c92f47 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -13308,20 +13308,20 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	  prelink_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
-		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+		compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
 	  old_archive_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
-		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
 		$RANLIB $oldlib'
 	  archive_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
-		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
 	  archive_expsym_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
-		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 	  ;;
 	*) # Version 6 and above use weak symbols
 	  archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am
index 246985b9933..dda484d38d4 100644
--- a/libsanitizer/sanitizer_common/Makefile.am
+++ b/libsanitizer/sanitizer_common/Makefile.am
@@ -24,6 +24,7 @@ sanitizer_common_files = \
 	sancov_flags.cc \
 	sanitizer_allocator.cc \
 	sanitizer_allocator_checks.cc \
+	sanitizer_allocator_report.cc \
 	sanitizer_common.cc \
 	sanitizer_common_libcdep.cc \
 	sanitizer_coverage_libcdep_new.cc \
@@ -46,14 +47,15 @@ sanitizer_common_files = \
 	sanitizer_posix.cc \
 	sanitizer_posix_libcdep.cc \
 	sanitizer_printf.cc \
+	sanitizer_procmaps_bsd.cc \
 	sanitizer_procmaps_common.cc \
-	sanitizer_procmaps_freebsd.cc \
 	sanitizer_procmaps_linux.cc \
 	sanitizer_procmaps_mac.cc \
 	sanitizer_stackdepot.cc \
 	sanitizer_stacktrace.cc \
 	sanitizer_stacktrace_libcdep.cc \
 	sanitizer_symbolizer_mac.cc \
+	sanitizer_symbolizer_report.cc \
 	sanitizer_stacktrace_printer.cc \
 	sanitizer_stoptheworld_linux_libcdep.cc \
 	sanitizer_stoptheworld_mac.cc \
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index b0f5ac25a7f..46209b780fd 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -82,8 +82,9 @@ CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 am__objects_1 = sancov_flags.lo sanitizer_allocator.lo \
-	sanitizer

[PATCH 0/7] libsanitizer: merge from trunk

2018-10-25 Thread marxin
Hi.

I've just finished my first merge from libsanitizer mainline. Overall it
looks fine, apparently ABI hasn't changed and so that SONAME bump is not
needed.

I tested ubsan and asan bootstrap on x86_64-linux-gnu and run regression
tests and bootstraped on aarch64-linux-gnu, ppc64le-linux-gnu and
also on x86_64-linux-gnu.

I run abidiff comparison for GCC 8.2:

$ abidiff /usr/lib64/libtsan.so.0.0.0 
./x86_64-pc-linux-gnu/libsanitizer/tsan/.libs/libtsan.so --stat
Functions changes summary: 0 Removed, 0 Changed, 38 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 1 Removed, 0 Added function symbol not 
referenced by debug info
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not 
referenced by debug info

$ abidiff /usr/lib64/libasan.so.5.0.0 
./x86_64-pc-linux-gnu/libsanitizer/asan/.libs/libasan.so --stat
Functions changes summary: 0 Removed, 0 Changed, 30 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 3 Removed, 0 Added function symbols not 
referenced by debug info
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not 
referenced by debug info

$ abidiff /usr/lib64/libubsan.so.1.0.0 
./x86_64-pc-linux-gnu/libsanitizer/ubsan/.libs/libubsan.so.1.0.0 --stat
Functions changes summary: 0 Removed, 0 Changed, 8 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 1 Removed, 0 Added function symbol not 
referenced by debug info
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not 
referenced by debug info

And for libasan with current LLVM top:

$ abidiff 
/home/marxin/BIG/Programming/llvm/objdir/lib/clang/7.0.0/lib/linux/libclang_rt.asan-x86_64.so
  ./x86_64-pc-linux-gnu/libsanitizer/ubsan/.libs/libubsan.so --stat
ELF SONAME changed
Functions changes summary: 763 Removed, 0 Changed, 43 Added functions
Variables changes summary: 4 Removed, 0 Changed, 2 Added variables
Function symbols changes summary: 518 Removed, 4 Added function symbols not 
referenced by debug info
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not 
referenced by debug info

I'll briefly comment what each patch in the series does:

marxin (7):
  Update merge script and HOWTO_MERGE documentation.

I tweaked documentation a bit and added support for git to be used.

  Merge from upstream 345033.

Result of the merge.sh script file as is without any additional
adjustment.

  Update build system: include new files and run autoheader, autoconf,
automake
  Apply LOCAL_PATCHES and remove not used ones.
  New local GCC patch for CAN_SANITIZE_UB ifdef.

Application of local patches, on of them was just partially applied.

  Adjust asan_shadow_offset for powerpc64 targets.

Sync about shodow memory offset that was changes in libsanitizer.

  Update test-suite expected output after rewording in libsanitizer.

Change in wording that was changed.

 gcc/config/powerpcspe/powerpcspe.c|2 +-
 gcc/config/rs6000/rs6000.c|2 +-
 gcc/testsuite/c-c++-common/ubsan/pr63839.c|2 +-
 .../c-c++-common/ubsan/unreachable-1.c|2 +-
 .../c-c++-common/ubsan/unreachable-2.c|2 +-
 .../c-c++-common/ubsan/unreachable-4.c|2 +-
 libsanitizer/HOWTO_MERGE  |9 +-
 libsanitizer/LOCAL_PATCHES|2 -
 libsanitizer/MERGE|2 +-
 libsanitizer/asan/asan_activation.cc  |7 +-
 libsanitizer/asan/asan_allocator.cc   |  166 +-
 libsanitizer/asan/asan_allocator.h|9 +-
 libsanitizer/asan/asan_debugging.cc   |3 +-
 libsanitizer/asan/asan_descriptions.cc|   71 +-
 libsanitizer/asan/asan_descriptions.h |   18 +-
 libsanitizer/asan/asan_errors.cc  |  204 +-
 libsanitizer/asan/asan_errors.h   |  281 +-
 libsanitizer/asan/asan_fake_stack.cc  |4 +-
 libsanitizer/asan/asan_flags.cc   |   12 +-
 libsanitizer/asan/asan_flags.inc  |3 +-
 libsanitizer/asan/asan_fuchsia.cc |2 +-
 libsanitizer/asan/asan_globals.cc |   11 +-
 libsanitizer/asan/asan_globals_win.cc |6 +-
 libsanitizer/asan/asan_init_version.h |7 +
 libsanitizer/asan/asan_interceptors.cc|   59 +-
 libsanitizer/asan/asan_interceptors.h |   28 +-
 .../asan/asan_interceptors_memintrinsics.cc   |   16 +-
 .../asan/asan_interceptors_memintrinsics.h|   25 +-
 libsanitizer/asan/asan_internal.h |7 +-
 libsanitizer/asan/asan_linux.cc   |   73 +-
 libsanitizer/asan/asan_lock.h |1 -
 libsanitizer/asan/asan_mac.cc |   28 +-
 libsanitizer/asan/asan_malloc_linux.cc|   81 +-
 libsanitizer/asan/asan_malloc_local.h |   42 +
 li

[PATCH 7/7] Update test-suite expected output after rewording in libsanitizer.

2018-10-25 Thread marxin

gcc/testsuite/ChangeLog:

2018-10-24  Martin Liska  

* c-c++-common/ubsan/pr63839.c: Update to new sanitizer message.
* c-c++-common/ubsan/unreachable-1.c (main): Likewise.
* c-c++-common/ubsan/unreachable-2.c: Likewise.
* c-c++-common/ubsan/unreachable-4.c (main): Likewise.
---
 gcc/testsuite/c-c++-common/ubsan/pr63839.c   | 2 +-
 gcc/testsuite/c-c++-common/ubsan/unreachable-1.c | 2 +-
 gcc/testsuite/c-c++-common/ubsan/unreachable-2.c | 2 +-
 gcc/testsuite/c-c++-common/ubsan/unreachable-4.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/c-c++-common/ubsan/pr63839.c b/gcc/testsuite/c-c++-common/ubsan/pr63839.c
index e3933f7fe66..f0cffa6cf7b 100644
--- a/gcc/testsuite/c-c++-common/ubsan/pr63839.c
+++ b/gcc/testsuite/c-c++-common/ubsan/pr63839.c
@@ -20,4 +20,4 @@ main (void)
   foo ();
 }
 
-/* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */
+/* { dg-output "execution reached an unreachable program point" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/unreachable-1.c b/gcc/testsuite/c-c++-common/ubsan/unreachable-1.c
index 336240c96cb..a72a5fd99a8 100644
--- a/gcc/testsuite/c-c++-common/ubsan/unreachable-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/unreachable-1.c
@@ -7,4 +7,4 @@ main (void)
 {
   __builtin_unreachable ();
 }
- /* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */
+/* { dg-output "execution reached an unreachable program point" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c b/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
index 783ebc24913..8299ff203fc 100644
--- a/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
@@ -11,4 +11,4 @@ main (void)
   return e ? 0 : (__builtin_unreachable (), 1);
 }
 
-/* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */
+/* { dg-output "execution reached an unreachable program point" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/unreachable-4.c b/gcc/testsuite/c-c++-common/ubsan/unreachable-4.c
index 71b56e3f9cc..126572a6e23 100644
--- a/gcc/testsuite/c-c++-common/ubsan/unreachable-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/unreachable-4.c
@@ -7,4 +7,4 @@ main (void)
 {
   __builtin_unreachable ();
 }
- /* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */
+/* { dg-output "execution reached an unreachable program point" } */


[PATCH 5/7] New local GCC patch for CAN_SANITIZE_UB ifdef.

2018-10-25 Thread marxin

libsanitizer/ChangeLog:

2018-10-24  Martin Liska  

* ubsan/ubsan_platform.h: Add ifndef as we define it with
-DCAN_SANITIZE_UB CFLAGS.
---
 libsanitizer/ubsan/ubsan_platform.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libsanitizer/ubsan/ubsan_platform.h b/libsanitizer/ubsan/ubsan_platform.h
index 75d06646ce8..67c4e079724 100644
--- a/libsanitizer/ubsan/ubsan_platform.h
+++ b/libsanitizer/ubsan/ubsan_platform.h
@@ -11,6 +11,7 @@
 #ifndef UBSAN_PLATFORM_H
 #define UBSAN_PLATFORM_H
 
+#ifndef CAN_SANITIZE_UB
 // Other platforms should be easy to add, and probably work as-is.
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||\
 defined(__NetBSD__) || defined(__OpenBSD__) || \
@@ -20,5 +21,6 @@
 #else
 # define CAN_SANITIZE_UB 0
 #endif
+#endif //CAN_SANITIZE_UB
 
 #endif


[PATCH 6/7] Adjust asan_shadow_offset for powerpc64 targets.

2018-10-25 Thread marxin

gcc/ChangeLog:

2018-10-25  Martin Liska  

* config/powerpcspe/powerpcspe.c (rs6000_asan_shadow_offset):
Aligh with value changed in libsanitizer/asan/asan_mapping.h.
* config/rs6000/rs6000.c (rs6000_asan_shadow_offset):
Likewise.
---
 gcc/config/powerpcspe/powerpcspe.c | 2 +-
 gcc/config/rs6000/rs6000.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/config/powerpcspe/powerpcspe.c b/gcc/config/powerpcspe/powerpcspe.c
index 90170c35c8f..2e76eb2f7b7 100644
--- a/gcc/config/powerpcspe/powerpcspe.c
+++ b/gcc/config/powerpcspe/powerpcspe.c
@@ -39354,7 +39354,7 @@ rs6000_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
 static unsigned HOST_WIDE_INT
 rs6000_asan_shadow_offset (void)
 {
-  return (unsigned HOST_WIDE_INT) 1 << (TARGET_64BIT ? 41 : 29);
+  return (unsigned HOST_WIDE_INT) 1 << (TARGET_64BIT ? 44 : 29);
 }
 #endif
 
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 75e30ce9784..32452eb36f3 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -35966,7 +35966,7 @@ rs6000_stack_protect_fail (void)
 static unsigned HOST_WIDE_INT
 rs6000_asan_shadow_offset (void)
 {
-  return (unsigned HOST_WIDE_INT) 1 << (TARGET_64BIT ? 41 : 29);
+  return (unsigned HOST_WIDE_INT) 1 << (TARGET_64BIT ? 44 : 29);
 }
 #endif
 


[PATCH 3/4] Fix vector memory statistics.

2018-11-05 Thread marxin

gcc/ChangeLog:

2018-11-02  Martin Liska  

* mem-stats.h (mem_alloc_description::release_instance_overhead):
Return T *.
* vec.c (struct vec_usage): Register m_element_size.
(vec_prefix::register_overhead): New arguments: elements and
element_size.
(vec_prefix::release_overhead): Subtract elements.
* vec.h (struct vec_prefix): Change signature.
(va_heap::reserve): Pass proper arguments.
(va_heap::release): Likewise.
---
 gcc/mem-stats.h | 14 --
 gcc/vec.c   | 34 +-
 gcc/vec.h   | 12 
 3 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h
index 3ef6d53dfa6..860908cf585 100644
--- a/gcc/mem-stats.h
+++ b/gcc/mem-stats.h
@@ -341,8 +341,8 @@ public:
 
   /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
  remove the instance from reverse map.  */
-  void release_instance_overhead (void *ptr, size_t size,
-  bool remove_from_map = false);
+  T * release_instance_overhead (void *ptr, size_t size,
+ bool remove_from_map = false);
 
   /* Release intance object identified by PTR pointer.  */
   void release_object_overhead (void *ptr);
@@ -503,7 +503,7 @@ mem_alloc_description::register_overhead (size_t size,
 /* Release PTR pointer of SIZE bytes.  */
 
 template 
-inline void
+inline T *
 mem_alloc_description::release_instance_overhead (void *ptr, size_t size,
 		 bool remove_from_map)
 {
@@ -512,14 +512,16 @@ mem_alloc_description::release_instance_overhead (void *ptr, size_t size,
   if (!slot)
 {
   /* Due to PCH, it can really happen.  */
-  return;
+  return NULL;
 }
 
-  mem_usage_pair usage_pair = *slot;
-  usage_pair.usage->release_overhead (size);
+  T *usage = (*slot).usage;
+  usage->release_overhead (size);
 
   if (remove_from_map)
 m_reverse_map->remove (ptr);
+
+  return usage;
 }
 
 /* Release intance object identified by PTR pointer.  */
diff --git a/gcc/vec.c b/gcc/vec.c
index ff2456aead9..bfd52856e46 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -52,13 +52,14 @@ vnull vNULL;
 struct vec_usage: public mem_usage
 {
   /* Default constructor.  */
-  vec_usage (): m_items (0), m_items_peak (0) {}
+  vec_usage (): m_items (0), m_items_peak (0), m_element_size (0) {}
 
   /* Constructor.  */
   vec_usage (size_t allocated, size_t times, size_t peak,
-	 size_t items, size_t items_peak)
+	 size_t items, size_t items_peak, size_t element_size)
 : mem_usage (allocated, times, peak),
-m_items (items), m_items_peak (items_peak) {}
+m_items (items), m_items_peak (items_peak),
+m_element_size (element_size) {}
 
   /* Sum the usage with SECOND usage.  */
   vec_usage
@@ -68,7 +69,7 @@ struct vec_usage: public mem_usage
 		  m_times + second.m_times,
 		  m_peak + second.m_peak,
 		  m_items + second.m_items,
-		  m_items_peak + second.m_items_peak);
+		  m_items_peak + second.m_items_peak, 0);
   }
 
   /* Dump usage coupled to LOC location, where TOTAL is sum of all rows.  */
@@ -81,7 +82,8 @@ struct vec_usage: public mem_usage
 
 s[48] = '\0';
 
-fprintf (stderr, "%-48s %10li:%4.1f%%%10li%10li:%4.1f%%%11li%11li\n", s,
+fprintf (stderr, "%-48s %10li%11li:%4.1f%%%10li%10li:%4.1f%%%11li%11li\n", s,
+	 (long)m_element_size,
 	 (long)m_allocated, m_allocated * 100.0 / total.m_allocated,
 	 (long)m_peak, (long)m_times, m_times * 100.0 / total.m_times,
 	 (long)m_items, (long)m_items_peak);
@@ -101,8 +103,8 @@ struct vec_usage: public mem_usage
   static inline void
   dump_header (const char *name)
   {
-fprintf (stderr, "%-48s %11s%15s%10s%17s%11s\n", name, "Leak", "Peak",
-	 "Times", "Leak items", "Peak items");
+fprintf (stderr, "%-48s %10s%11s%16s%10s%17s%11s\n", name, "sizeof(T)",
+	 "Leak", "Peak", "Times", "Leak items", "Peak items");
 print_dash_line ();
   }
 
@@ -110,6 +112,8 @@ struct vec_usage: public mem_usage
   size_t m_items;
   /* Peak value of number of allocated items.  */
   size_t m_items_peak;
+  /* Size of element of the vector.  */
+  size_t m_element_size;
 };
 
 /* Vector memory description.  */
@@ -118,12 +122,14 @@ static mem_alloc_description  vec_mem_desc;
 /* Account the overhead.  */
 
 void
-vec_prefix::register_overhead (void *ptr, size_t size, size_t elements
-			   MEM_STAT_DECL)
+vec_prefix::register_overhead (void *ptr, size_t elements,
+			   size_t element_size MEM_STAT_DECL)
 {
   vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN, false
 FINAL_PASS_MEM_STAT);
-  vec_usage *usage = vec_mem_desc.register_instance_overhead (size, ptr);
+  vec_usage *usage
+= vec_mem_desc.register_instance_overhead (elements * element_size, ptr);
+  usage->m_element_size = element_size;
   usage->m_items += elements;
   if (usage->m_items_peak < usage->m_items)
 usage->m_items_peak = usage->m_items;
@@ -132,13 +138,15 @@ vec_prefix::reg

[PATCH 1/4] Fix string pool statistics.

2018-11-05 Thread marxin

libcpp/ChangeLog:

2018-11-02  Martin Liska  

* include/symtab.h (ht_identifier):
Make room for ggc flag.
* symtab.c (ht_lookup_with_hash): Mark
GGC and non-GGC allocated strings.
(ht_dump_statistics): Use the information.
---
 libcpp/include/symtab.h |  4 +++-
 libcpp/symtab.c | 28 +++-
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/libcpp/include/symtab.h b/libcpp/include/symtab.h
index c08a4f29ca2..da92192849f 100644
--- a/libcpp/include/symtab.h
+++ b/libcpp/include/symtab.h
@@ -30,12 +30,14 @@ typedef struct ht_identifier ht_identifier;
 typedef struct ht_identifier *ht_identifier_ptr;
 struct GTY(()) ht_identifier {
   const unsigned char *str;
-  unsigned int len;
   unsigned int hash_value;
+  unsigned int len : 31;
+  unsigned int ggc : 1;
 };
 
 #define HT_LEN(NODE) ((NODE)->len)
 #define HT_STR(NODE) ((NODE)->str)
+#define HT_GGC(NODE) ((NODE)->ggc)
 
 typedef struct ht cpp_hash_table;
 typedef struct ht_identifier *hashnode;
diff --git a/libcpp/symtab.c b/libcpp/symtab.c
index fd86c849f7f..1c62a16d335 100644
--- a/libcpp/symtab.c
+++ b/libcpp/symtab.c
@@ -164,10 +164,14 @@ ht_lookup_with_hash (cpp_hash_table *table, const unsigned char *str,
   memcpy (chars, str, len);
   chars[len] = '\0';
   HT_STR (node) = (const unsigned char *) chars;
+  HT_GGC (node) = 1;
 }
   else
-HT_STR (node) = (const unsigned char *) obstack_copy0 (&table->stack,
-			   str, len);
+{
+  HT_STR (node) = (const unsigned char *) obstack_copy0 (&table->stack,
+			 str, len);
+  HT_GGC (node) = 1;
+}
 
   if (++table->nelements * 4 >= table->nslots * 3)
 /* Must expand the string table.  */
@@ -274,7 +278,7 @@ void
 ht_dump_statistics (cpp_hash_table *table)
 {
   size_t nelts, nids, overhead, headers;
-  size_t total_bytes, longest, deleted = 0;
+  size_t total_bytes_obstack = 0, total_bytes_ggc = 0, longest, deleted = 0;
   double sum_of_squares, exp_len, exp_len2, exp2_len;
   hashnode *p, *limit;
 
@@ -285,7 +289,7 @@ ht_dump_statistics (cpp_hash_table *table)
 		 : (x) / (1024*1024
 #define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
 
-  total_bytes = longest = sum_of_squares = nids = 0;
+  longest = sum_of_squares = nids = 0;
   p = table->entries;
   limit = p + table->nslots;
   do
@@ -295,7 +299,11 @@ ht_dump_statistics (cpp_hash_table *table)
   {
 	size_t n = HT_LEN (*p);
 
-	total_bytes += n;
+	if (HT_GGC (*p))
+	  total_bytes_ggc += n;
+	else
+	  total_bytes_obstack += n;
+
 	sum_of_squares += (double) n * n;
 	if (n > longest)
 	  longest = n;
@@ -304,7 +312,7 @@ ht_dump_statistics (cpp_hash_table *table)
   while (++p < limit);
 
   nelts = table->nelements;
-  overhead = obstack_memory_used (&table->stack) - total_bytes;
+  overhead = obstack_memory_used (&table->stack) - total_bytes_obstack;
   headers = table->nslots * sizeof (hashnode);
 
   fprintf (stderr, "\nString pool\nentries\t\t%lu\n",
@@ -315,13 +323,15 @@ ht_dump_statistics (cpp_hash_table *table)
 	   (unsigned long) table->nslots);
   fprintf (stderr, "deleted\t\t%lu\n",
 	   (unsigned long) deleted);
-  fprintf (stderr, "bytes\t\t%lu%c (%lu%c overhead)\n",
-	   SCALE (total_bytes), LABEL (total_bytes),
+  fprintf (stderr, "GGC bytes\t%lu%c\n",
+	   SCALE (total_bytes_ggc), LABEL (total_bytes_ggc));
+  fprintf (stderr, "obstack bytes\t%lu%c (%lu%c overhead)\n",
+	   SCALE (total_bytes_obstack), LABEL (total_bytes_obstack),
 	   SCALE (overhead), LABEL (overhead));
   fprintf (stderr, "table size\t%lu%c\n",
 	   SCALE (headers), LABEL (headers));
 
-  exp_len = (double)total_bytes / (double)nelts;
+  exp_len = (double)total_bytes_obstack / (double)nelts;
   exp2_len = exp_len * exp_len;
   exp_len2 = (double) sum_of_squares / (double) nelts;
 


[PATCH 4/4] Come up with SIZE_AMOUNT and use it in memory statistics and sort stats.

2018-11-05 Thread marxin

gcc/ChangeLog:

2018-11-02  Martin Liska  

* alloc-pool.h (struct pool_usage): Use SIZE_AMOUNT.
* bitmap.h (struct bitmap_usage): Likewise.
* ggc-common.c (SCALE): Remove.
(LABEL): Likewise.
(struct ggc_usage): Use SIZE_AMOUNT. And update
compare method.
* ggc-page.c (SCALE): Remove.
(STAT_LABEL): Remove.
(ggc_print_statistics): Use SIZE_AMOUNT.
* gimple.h (SCALE): Remove.
(LABEL): Likewise.
* input.c (ONE_K): Remove.
(ONE_M): Likewise.
(SCALE): Likewise.
(STAT_LABEL): Likewise.
(FORMAT_AMOUNT): Likewise.
(dump_line_table_statistics): Use SIZE_AMOUNT.
* mem-stats.h (struct mem_usage): Likewise.
* rtl.c (dump_rtx_statistics): Likewise.
(rtx_alloc_counts): Change type to size_t.
(rtx_alloc_sizes): Likewise.
(rtx_count_cmp): New.
(dump_rtx_statistics): Sort first based on counts.
* tree.c (tree_nodes_cmp): New.
(tree_codes_cmp): New.
(dump_tree_statistics): Sort first based on counts.
* system.h (ONE_K): New.
(ONE_M): Likewise.
(SIZE_SCALE): Likewise.
(SIZE_LABEL): Likewise.
(SIZE_AMOUNT): Likewise.
* tree-cfg.c (dump_cfg_stats): Use SIZE_AMOUNT.
* tree-dfa.c (dump_dfa_stats): Likewise.
* tree-phinodes.c (phinodes_print_statistics): Likewise.
* tree-ssanames.c (ssanames_print_statistics): Likewise.
* tree.c (dump_tree_statistics): Likewise.
* vec.c (struct vec_usage): Likewise.
* trans-mem.c (tm_mangle): Enlarge buffer in order to not
trigger a -Werror=format-overflow with
--enable-gather-detailed-stats.
---
 gcc/alloc-pool.h| 18 +
 gcc/bitmap.h| 12 +++---
 gcc/ggc-common.c| 32 ++--
 gcc/ggc-page.c  | 86 +-
 gcc/gimple.c| 11 +++---
 gcc/gimple.h| 10 -
 gcc/input.c | 75 ++---
 gcc/mem-stats.h | 12 +++---
 gcc/rtl.c   | 66 +---
 gcc/system.h| 25 +
 gcc/trans-mem.c |  2 +-
 gcc/tree-cfg.c  |  8 ++--
 gcc/tree-dfa.c  | 16 
 gcc/tree-phinodes.c |  5 ++-
 gcc/tree-ssanames.c |  6 ++-
 gcc/tree.c  | 91 +
 gcc/vec.c   | 20 ++
 17 files changed, 272 insertions(+), 223 deletions(-)

diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h
index d2ee0005761..d17a05ca4fb 100644
--- a/gcc/alloc-pool.h
+++ b/gcc/alloc-pool.h
@@ -63,12 +63,16 @@ struct pool_usage: public mem_usage
   {
 char *location_string = loc->to_string ();
 
-fprintf (stderr, "%-32s%-48s %6li%10li:%5.1f%%%10li%10li:%5.1f%%%12li\n",
-	 m_pool_name, location_string, (long)m_instances,
-	 (long)m_allocated, get_percent (m_allocated, total.m_allocated),
-	 (long)m_peak, (long)m_times,
+fprintf (stderr, "%-32s%-48s %5zu%c%9zu%c:%5.1f%%%9zu"
+	 "%c%9zu%c:%5.1f%%%12zu\n",
+	 m_pool_name, location_string,
+	 SIZE_AMOUNT (m_instances),
+	 SIZE_AMOUNT (m_allocated),
+	 get_percent (m_allocated, total.m_allocated),
+	 SIZE_AMOUNT (m_peak),
+	 SIZE_AMOUNT (m_times),
 	 get_percent (m_times, total.m_times),
-	 (long)m_element_size);
+	 m_element_size);
 
 free (location_string);
   }
@@ -87,8 +91,8 @@ struct pool_usage: public mem_usage
   dump_footer ()
   {
 print_dash_line ();
-fprintf (stderr, "%s%82li%10li\n", "Total", (long)m_instances,
-	 (long)m_allocated);
+fprintf (stderr, "%s%82zu%c%10zu%c\n", "Total",
+	 SIZE_AMOUNT (m_instances), SIZE_AMOUNT (m_allocated));
 print_dash_line ();
   }
 
diff --git a/gcc/bitmap.h b/gcc/bitmap.h
index 5d3e8a5088e..973ea846baf 100644
--- a/gcc/bitmap.h
+++ b/gcc/bitmap.h
@@ -239,14 +239,14 @@ struct bitmap_usage: public mem_usage
   {
 char *location_string = loc->to_string ();
 
-fprintf (stderr, "%-48s %10" PRIu64 ":%5.1f%%"
-	 "%10" PRIu64 "%10" PRIu64 ":%5.1f%%"
-	 "%12" PRIu64 "%12" PRIu64 "%10s\n",
-	 location_string, (uint64_t)m_allocated,
+fprintf (stderr, "%-48s %9zu%c:%5.1f%%"
+	 "%9zu%c%9zu%c:%5.1f%%"
+	 "%11" PRIu64 "%c%11" PRIu64 "%c%10s\n",
+	 location_string, SIZE_AMOUNT (m_allocated),
 	 get_percent (m_allocated, total.m_allocated),
-	 (uint64_t)m_peak, (uint64_t)m_times,
+	 SIZE_AMOUNT (m_peak), SIZE_AMOUNT (m_times),
 	 get_percent (m_times, total.m_times),
-	 m_nsearches, m_search_iter,
+	 SIZE_AMOUNT (m_nsearches), SIZE_AMOUNT (m_search_iter),
 	 loc->m_ggc ? "ggc" : "heap");
 
 free (location_string);
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index f83fc136d04..9fdba23ce4c 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -195,14 +195,6 @@ ggc_splay_dont_free (void * x ATTRIBUTE_UNUSED, void *nl)
   gcc_assert (!nl);
 }
 
-/* Print statistics

[PATCH 2/4] Fix GNU coding style.

2018-11-05 Thread marxin

gcc/ChangeLog:

2018-11-02  Martin Liska  

* mem-stats.h (mem_alloc_description::get_list): Fix GNU coding
style.
* vec.c: Likewise.
---
 gcc/mem-stats.h | 61 +
 gcc/vec.c   |  1 -
 2 files changed, 26 insertions(+), 36 deletions(-)

diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h
index 140691e8ec1..3ef6d53dfa6 100644
--- a/gcc/mem-stats.h
+++ b/gcc/mem-stats.h
@@ -282,21 +282,21 @@ public:
 static hashval_t
 hash (value_type l)
 {
-	inchash::hash hstate;
+  inchash::hash hstate;
 
-	hstate.add_ptr ((const void *)l->m_filename);
-	hstate.add_ptr (l->m_function);
-	hstate.add_int (l->m_line);
+  hstate.add_ptr ((const void *)l->m_filename);
+  hstate.add_ptr (l->m_function);
+  hstate.add_int (l->m_line);
 
-	return hstate.end ();
+  return hstate.end ();
 }
 
 static bool
 equal (value_type l1, value_type l2)
 {
-  return l1->m_filename == l2->m_filename
-	&& l1->m_function == l2->m_function
-	&& l1->m_line == l2->m_line;
+  return (l1->m_filename == l2->m_filename
+	  && l1->m_function == l2->m_function
+	  && l1->m_line == l2->m_line);
 }
   };
 
@@ -313,59 +313,50 @@ public:
   ~mem_alloc_description ();
 
   /* Returns true if instance PTR is registered by the memory description.  */
-  bool
-  contains_descriptor_for_instance (const void *ptr);
+  bool contains_descriptor_for_instance (const void *ptr);
 
   /* Return descriptor for instance PTR.  */
-  T *
-  get_descriptor_for_instance (const void *ptr);
+  T * get_descriptor_for_instance (const void *ptr);
 
   /* Register memory allocation descriptor for container PTR which is
  described by a memory LOCATION.  */
-  T *
-  register_descriptor (const void *ptr, mem_location *location);
+  T * register_descriptor (const void *ptr, mem_location *location);
 
   /* Register memory allocation descriptor for container PTR.  ORIGIN identifies
  type of container and GGC identifes if the allocation is handled in GGC
  memory.  Each location is identified by file NAME, LINE in source code and
  FUNCTION name.  */
-  T *
-  register_descriptor (const void *ptr, mem_alloc_origin origin,
-			  bool ggc, const char *name, int line,
-			  const char *function);
+  T * register_descriptor (const void *ptr, mem_alloc_origin origin,
+			   bool ggc, const char *name, int line,
+			   const char *function);
 
   /* Register instance overhead identified by PTR pointer. Allocation takes
  SIZE bytes.  */
-  T *
-  register_instance_overhead (size_t size, const void *ptr);
+  T * register_instance_overhead (size_t size, const void *ptr);
 
   /* For containers (and GGC) where we want to track every instance object,
  we register allocation of SIZE bytes, identified by PTR pointer, belonging
  to USAGE descriptor.  */
-  void
-  register_object_overhead (T *usage, size_t size, const void *ptr);
+  void register_object_overhead (T *usage, size_t size, const void *ptr);
 
   /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
  remove the instance from reverse map.  */
-  void
-  release_instance_overhead (void *ptr, size_t size,
+  void release_instance_overhead (void *ptr, size_t size,
   bool remove_from_map = false);
 
   /* Release intance object identified by PTR pointer.  */
-  void
-  release_object_overhead (void *ptr);
+  void release_object_overhead (void *ptr);
 
   /* Get sum value for ORIGIN type of allocation for the descriptor.  */
-  T
-  get_sum (mem_alloc_origin origin);
+  T get_sum (mem_alloc_origin origin);
 
   /* Get all tracked instances registered by the description. Items
  are filtered by ORIGIN type, LENGTH is return value where we register
  the number of elements in the list. If we want to process custom order,
  CMP comparator can be provided.  */
-  mem_list_t *
-  get_list (mem_alloc_origin origin, unsigned *length,
-	int (*cmp) (const void *first, const void *second) = NULL);
+  mem_list_t * get_list (mem_alloc_origin origin, unsigned *length,
+			 int (*cmp) (const void *first,
+ const void *second) = NULL);
 
   /* Dump all tracked instances of type ORIGIN. If we want to process custom
  order, CMP comparator can be provided.  */
@@ -391,7 +382,6 @@ private:
   reverse_mem_map_t *m_reverse_map;
 };
 
-
 /* Returns true if instance PTR is registered by the memory description.  */
 
 template 
@@ -410,9 +400,9 @@ mem_alloc_description::get_descriptor_for_instance (const void *ptr)
   return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
 }
 
+/* Register memory allocation descriptor for container PTR which is
+   described by a memory LOCATION.  */
 
-  /* Register memory allocation descriptor for container PTR which is
- described by a memory LOCATION.  */
 template 
 inline T*
 mem_alloc_description::register_descriptor (const void *ptr,
@@ -584,7 +574,8 @@ template 
 inline
 typena

[PATCH 0/4] Enhance and fix various issues in -fmem-report

2018-11-05 Thread marxin
Hi.

As I discussed with Richi, the patch set fixes few issues in memory
report. Apart from that it makes it more readable with usage of k (or M)
as units.

Survives bootstrap and regression tests on x86_64-linux-gnu. And there
are no new warnings on i586-linux-gnu.

Martin

marxin (4):
  Fix string pool statistics.
  Fix GNU coding style.
  Fix vector memory statistics.
  Come up with SIZE_AMOUNT and use it in memory statistics and sort
stats.

 gcc/alloc-pool.h| 18 
 gcc/bitmap.h| 12 +++---
 gcc/ggc-common.c| 32 +--
 gcc/ggc-page.c  | 86 +++---
 gcc/gimple.c| 11 ++---
 gcc/gimple.h| 10 -
 gcc/input.c | 75 +
 gcc/mem-stats.h | 85 ++
 gcc/rtl.c   | 66 --
 gcc/system.h| 25 +++
 gcc/trans-mem.c |  2 +-
 gcc/tree-cfg.c  |  8 ++--
 gcc/tree-dfa.c  | 16 
 gcc/tree-phinodes.c |  5 ++-
 gcc/tree-ssanames.c |  6 ++-
 gcc/tree.c  | 91 ++---
 gcc/vec.c   | 51 ++-
 gcc/vec.h   | 12 --
 libcpp/include/symtab.h |  4 +-
 libcpp/symtab.c | 28 +
 20 files changed, 354 insertions(+), 289 deletions(-)

-- 
2.19.1



[PATCH 0/3][stage1] [PATCH v2] LTO dump tool

2019-03-14 Thread marxin
Hi.

The patch series is a remake of Hrishikesh's LTO dump tool that was
part of GSoC last year. I decided to split the patch into 3 parts, where
the first one is purely mechanical splitting code into a newly created
one. The second part introduces the new tool. And the last one is about
GNU coding style fixes.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
Ready to be installed after stage1 opens?

Thanks,
Martin

marxin (3):
  Split part of functionality from lto.c to lto-common.c.
  Add lto-dump tool.
  Fix GNU coding style in lto-common.c.

 gcc/Makefile.in|2 +-
 gcc/cgraph.h   |6 +
 gcc/doc/gcc.texi   |5 +
 gcc/doc/lto-dump.texi  |  131 ++
 gcc/dumpfile.c |   85 +-
 gcc/dumpfile.h |5 +
 gcc/lto/Make-lang.in   |   22 +-
 gcc/lto/config-lang.in |4 +-
 gcc/lto/lang.opt   |   62 +
 gcc/lto/lto-common.c   | 2883 
 gcc/lto/lto-common.h   |   33 +
 gcc/lto/lto-dump.c |  344 +
 gcc/lto/lto-lang.c |7 +-
 gcc/lto/lto.c  | 2869 +--
 gcc/lto/lto.h  |2 +
 gcc/symtab.c   |   17 +
 16 files changed, 3612 insertions(+), 2865 deletions(-)
 create mode 100644 gcc/doc/lto-dump.texi
 create mode 100644 gcc/lto/lto-common.c
 create mode 100644 gcc/lto/lto-common.h
 create mode 100644 gcc/lto/lto-dump.c

-- 
2.21.0



[PATCH 2/3] Add lto-dump tool.

2019-03-14 Thread marxin

gcc/ChangeLog:

2019-03-14  Hrishikesh Kulkarni  
Martin Liska  

* Makefile.in: Add lto-dump.texi.
* cgraph.h: Add new functions dump_visibility and
dump_type_name.
* doc/gcc.texi: Include lto-dump section.
* doc/lto-dump.texi: New file.
* dumpfile.c (dump_switch_p_1): Use parse_dump_option.
(parse_dump_option): Factor out this function.
* dumpfile.h (enum dump_flag): Add new value TDF_ERROR.
(parse_dump_option): Export the function.
* symtab.c (symtab_node::dump_visibility): New function.
(symtab_node::dump_type_name): Likewise.

gcc/lto/ChangeLog:

2019-03-14  Hrishikesh Kulkarni  
Martin Liska  

* Make-lang.in: Add lto_dump-related definition.
* config-lang.in: Likewise.
* lang.opt: Add new language LTODump and options related
to LTO dump tool.
* lto-common.c (lto_read_decls): Support type statistics dump.
(lto_file_read): Likewise for object files.
* lto-dump.c: New file.
* lto-lang.c (lto_option_lang_mask): Move from ..
* lto.c (lto_option_lang_mask): .. here.
* lto.h (lto_option_lang_mask): New declaration.
---
 gcc/Makefile.in|   2 +-
 gcc/cgraph.h   |   6 +
 gcc/doc/gcc.texi   |   5 +
 gcc/doc/lto-dump.texi  | 131 
 gcc/dumpfile.c |  85 ++
 gcc/dumpfile.h |   5 +
 gcc/lto/Make-lang.in   |  20 ++-
 gcc/lto/config-lang.in |   4 +-
 gcc/lto/lang.opt   |  62 
 gcc/lto/lto-common.c   |  40 +
 gcc/lto/lto-dump.c | 344 +
 gcc/lto/lto-lang.c |   6 -
 gcc/lto/lto.c  |   6 +
 gcc/lto/lto.h  |   2 +
 gcc/symtab.c   |  17 ++
 15 files changed, 692 insertions(+), 43 deletions(-)
 create mode 100644 gcc/doc/lto-dump.texi
 create mode 100644 gcc/lto/lto-dump.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 508c674cbdc..c7e4ae94103 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3158,7 +3158,7 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi	\
 	 gcov.texi trouble.texi bugreport.texi service.texi		\
 	 contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi	\
 	 fdl.texi contrib.texi cppenv.texi cppopts.texi avr-mmcu.texi	\
-	 implement-c.texi implement-cxx.texi gcov-tool.texi gcov-dump.texi
+	 implement-c.texi implement-cxx.texi gcov-tool.texi gcov-dump.texi lto-dump.texi
 
 # we explicitly use $(srcdir)/doc/tm.texi here to avoid confusion with
 # the generated tm.texi; the latter might have a more recent timestamp,
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 9a19d83fffb..e2c2c00b5ed 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -119,6 +119,12 @@ public:
   /* Return dump name with assembler name.  */
   const char *dump_asm_name () const;
 
+  /* Return visibility name.  */
+  const char *dump_visibility () const;
+
+  /* Return type_name name.  */
+  const char *dump_type_name () const;
+
   /* Add node into symbol table.  This function is not used directly, but via
  cgraph/varpool node creation routines.  */
   void register_symbol (void);
diff --git a/gcc/doc/gcc.texi b/gcc/doc/gcc.texi
index 5297b9cb5d0..4d03e3a6d96 100644
--- a/gcc/doc/gcc.texi
+++ b/gcc/doc/gcc.texi
@@ -68,6 +68,8 @@ Texts being (a) (see below), and with the Back-Cover Texts being (b)
 * gcov: (gcc) Gcov.@command{gcov}---a test coverage program.
 * gcov-tool: (gcc) Gcov-tool.  @command{gcov-tool}---an offline gcda profile processing program.
 * gcov-dump: (gcc) Gcov-dump.  @command{gcov-dump}---an offline gcda and gcno profile dump tool.
+* lto-dump: (gcc) lto-dump.@command{lto-dump}---Tool for
+dumping LTO object files.
 @end direntry
 This file documents the use of the GNU compilers.
 @sp 1
@@ -142,6 +144,8 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
 * Gcov::@command{gcov}---a test coverage program.
 * Gcov-tool::   @command{gcov-tool}---an offline gcda profile processing program.
 * Gcov-dump::   @command{gcov-dump}---an offline gcda and gcno profile dump tool.
+* lto-dump::@command{lto-dump}---Tool for dumping LTO
+object files.
 * Trouble:: If you have trouble using GCC.
 * Bugs::How, why and where to report bugs.
 * Service:: How To Get Help with GCC
@@ -170,6 +174,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
 @include gcov.texi
 @include gcov-tool.texi
 @include gcov-dump.texi
+@include lto-dump.texi
 @include trouble.texi
 @include bugreport.texi
 @include service.texi
diff --git a/gcc/doc/lto-dump.texi b/gcc/doc/lto-dump.texi
new file mode 100644
index 000..d84397581c0
--- /dev/null
+++ b/gcc/doc/lto-dump.texi
@@ -0,0 +1,131 @@
+@c Copyright (C) 2018-2019 Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc.texi.
+
+@ignore
+@c man begin COPYRIGHT
+Copyrigh

[PATCH 3/3] Fix GNU coding style in lto-common.c.

2019-03-14 Thread marxin

gcc/lto/ChangeLog:

2019-03-14  Martin Liska  

* lto-common.c: Update coding style.
* lto.c (materialize_cgraph): Likewise.
---
 gcc/lto/lto-common.c | 214 ++-
 gcc/lto/lto.c|  30 +++---
 2 files changed, 128 insertions(+), 116 deletions(-)

diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index 01470c17080..aa64d8b779e 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -76,15 +76,15 @@ hash_name (const void *p)
 static int
 eq_name (const void *p1, const void *p2)
 {
-  const struct lto_section_slot *s1 =
-(const struct lto_section_slot *) p1;
-  const struct lto_section_slot *s2 =
-(const struct lto_section_slot *) p2;
+  const struct lto_section_slot *s1
+= (const struct lto_section_slot *) p1;
+  const struct lto_section_slot *s2
+= (const struct lto_section_slot *) p2;
 
   return strcmp (s1->name, s2->name) == 0;
 }
 
-/* Free lto_section_slot */
+/* Free lto_section_slot.  */
 
 static void
 free_with_string (void *arg)
@@ -95,9 +95,9 @@ free_with_string (void *arg)
   free (arg);
 }
 
-/* Create section hash table */
+/* Create section hash table.  */
 
-htab_t 
+htab_t
 lto_obj_create_section_hash_table (void)
 {
   return htab_create (37, hash_name, eq_name, free_with_string);
@@ -145,9 +145,9 @@ lto_splay_tree_id_equal_p (splay_tree_key key, unsigned HOST_WIDE_INT id)
   return *(unsigned HOST_WIDE_INT *) key == id;
 }
 
-/* Insert a splay tree node into tree T with ID as key and FILE_DATA as value. 
+/* Insert a splay tree node into tree T with ID as key and FILE_DATA as value.
The ID is allocated separately because we need HOST_WIDE_INTs which may
-   be wider than a splay_tree_key. */
+   be wider than a splay_tree_key.  */
 
 static void
 lto_splay_tree_insert (splay_tree t, unsigned HOST_WIDE_INT id,
@@ -164,13 +164,13 @@ static splay_tree
 lto_splay_tree_new (void)
 {
   return splay_tree_new (lto_splay_tree_compare_ids,
-	 	 lto_splay_tree_delete_id,
+			 lto_splay_tree_delete_id,
 			 NULL);
 }
 
 /* Decode the content of memory pointed to by DATA in the in decl
-   state object STATE. DATA_IN points to a data_in structure for
-   decoding. Return the address after the decoded object in the
+   state object STATE.  DATA_IN points to a data_in structure for
+   decoding.  Return the address after the decoded object in the
input.  */
 
 static const uint32_t *
@@ -255,7 +255,7 @@ hash_canonical_type (tree type)
 {
   hstate.add_int (TYPE_PRECISION (type));
   if (!type_with_interoperable_signedness (type))
-hstate.add_int (TYPE_UNSIGNED (type));
+	hstate.add_int (TYPE_UNSIGNED (type));
 }
 
   if (VECTOR_TYPE_P (type))
@@ -437,8 +437,8 @@ gimple_register_canonical_type (tree t)
 TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
   else
 {
-  gimple_register_canonical_type_1 (TYPE_MAIN_VARIANT (t),
-	hash_canonical_type (TYPE_MAIN_VARIANT (t)));
+  hashval_t h = hash_canonical_type (TYPE_MAIN_VARIANT (t));
+  gimple_register_canonical_type_1 (TYPE_MAIN_VARIANT (t), h);
   TYPE_CANONICAL (t) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
 }
 }
@@ -460,7 +460,7 @@ lto_register_canonical_types (tree node, bool first_p)
   || TREE_CODE (node) == ARRAY_TYPE)
 lto_register_canonical_types (TREE_TYPE (node), first_p);
 
- if (!first_p) 
+ if (!first_p)
 gimple_register_canonical_type (node);
 }
 
@@ -534,7 +534,7 @@ mentions_vars_p_decl_with_vis (tree t)
   if (mentions_vars_p_decl_common (t))
 return true;
 
-  /* Accessor macro has side-effects, use field-name here. */
+  /* Accessor macro has side-effects, use field-name here.  */
   CHECK_NO_VAR (DECL_ASSEMBLER_NAME_RAW (t));
   return false;
 }
@@ -594,7 +594,7 @@ mentions_vars_p_type (tree t)
   CHECK_VAR (TYPE_MIN_VALUE_RAW (t));
   CHECK_VAR (TYPE_MAX_VALUE_RAW (t));
 
-  /* Accessor is for derived node types only. */
+  /* Accessor is for derived node types only.  */
   CHECK_NO_VAR (TYPE_LANG_SLOT_1 (t));
 
   CHECK_VAR (TYPE_CONTEXT (t));
@@ -748,7 +748,7 @@ mentions_vars_p (tree t)
 }
 
 
-/* Return the resolution for the decl with index INDEX from DATA_IN. */
+/* Return the resolution for the decl with index INDEX from DATA_IN.  */
 
 static enum ld_plugin_symbol_resolution
 get_resolution (struct data_in *data_in, unsigned index)
@@ -758,7 +758,7 @@ get_resolution (struct data_in *data_in, unsigned index)
   ld_plugin_symbol_resolution_t ret;
   /* We can have references to not emitted functions in
 	 DECL_FUNCTION_PERSONALITY at least.  So we can and have
-	 to indeed return LDPR_UNKNOWN in some cases.   */
+	 to indeed return LDPR_UNKNOWN in some cases.  */
   if (data_in->globals_resolution.length () <= index)
 	return LDPR_UNKNOWN;
   ret = data_in->globals_resolution[index];
@@ -1090,7 +1090,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
   if (code == VAR_DECL)
 	{
 	  compare_values (DECL_HARD_REGISTER);

[PATCH 0/3] Fix and improve -fdbg-cnt option.

2019-03-27 Thread marxin
Hi.

While I was working on PR84201 it was very handy for me to use debug counters
for a particular source file. That's because I can't run a verification
on a spec result and I was unable to persuade runspec command to use a modified 
binary
for run.

Thus's I'm suggesting extension of the option to filter aux_base_name.

I've been testing the series right now.
Thoughts?
Thanks,
Martin

marxin (3):
  Fix multiple values for -fdbg-cnt.
  Extend format of -fdbg-cnt: add aux_base filter.
  Dump -fdbg-cnt limit reach also to stderr stream.

 gcc/dbgcnt.c | 60 
 gcc/doc/invoke.texi  |  8 +++--
 gcc/testsuite/gcc.dg/dbg-cnt-1.c |  6 
 3 files changed, 50 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/dbg-cnt-1.c

-- 
2.21.0



[PATCH 3/3] Dump -fdbg-cnt limit reach also to stderr stream.

2019-03-27 Thread marxin

gcc/ChangeLog:

2019-03-27  Martin Liska  

* dbgcnt.c (print_limit_reach): New function.
(dbg_cnt): Use it.
---
 gcc/dbgcnt.c | 26 --
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index 5a7c9a8bf6e..cfa03d611ee 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -59,21 +59,27 @@ dbg_cnt_is_enabled (enum debug_counter index)
   return v > limit_low[index] && v <= limit_high[index];
 }
 
+static void
+print_limit_reach (const char *counter, int limit, bool upper_p)
+{
+  char buffer[128];
+  sprintf (buffer, "***dbgcnt: %s limit %d reached for %s.***\n",
+	   upper_p ? "upper" : "lower", limit, counter);
+  fputs (buffer, stderr);
+  if (dump_file)
+fputs (buffer, dump_file);
+}
+
 bool
 dbg_cnt (enum debug_counter index)
 {
   count[index]++;
 
-  if (dump_file)
-{
-  /* Do not print the info for default lower limit.  */
-  if (count[index] == limit_low[index] && limit_low[index] > 0)
-	fprintf (dump_file, "***dbgcnt: lower limit %d reached for %s.***\n",
-		 limit_low[index], map[index].name);
-  else if (count[index] == limit_high[index])
-	fprintf (dump_file, "***dbgcnt: upper limit %d reached for %s.***\n",
-		 limit_high[index], map[index].name);
-}
+  /* Do not print the info for default lower limit.  */
+  if (count[index] == limit_low[index] && limit_low[index] > 0)
+print_limit_reach (map[index].name, limit_low[index], false);
+  else if (count[index] == limit_high[index])
+print_limit_reach (map[index].name, limit_high[index], true);
 
   return dbg_cnt_is_enabled (index);
 }


[PATCH 1/3] Fix multiple values for -fdbg-cnt.

2019-03-27 Thread marxin

gcc/ChangeLog:

2019-03-27  Martin Liska  

* dbgcnt.c (dbg_cnt_process_single_pair): Fix GNU coding style.
(dbg_cnt_process_opt): Parse first tokens aas
dbg_cnt_process_single_pair is also using strtok.
---
 gcc/dbgcnt.c | 25 +++--
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index ebaa310821c..e2f65f449e5 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -151,30 +151,35 @@ dbg_cnt_process_single_pair (const char *arg)
   high = strtol (value2, NULL, 10);
 }
 
-   return dbg_cnt_set_limit_by_name (name, low, high);
+  return dbg_cnt_set_limit_by_name (name, low, high);
 }
 
 void
 dbg_cnt_process_opt (const char *arg)
 {
   char *str = xstrdup (arg);
-  const char *next = strtok (str, ",");
   unsigned int start = 0;
 
-   do {
- if (!dbg_cnt_process_single_pair (arg))
+  auto_vec tokens;
+  for (const char *next = strtok (str, ","); next != NULL;
+   next = strtok (NULL, ","))
+tokens.safe_push (next);
+
+  unsigned i;
+  for (i = 0; i < tokens.length (); i++)
+{
+ if (!dbg_cnt_process_single_pair (tokens[i]))
break;
- start += strlen (arg) + 1;
- next = strtok (NULL, ",");
-   } while (next != NULL);
+ start += strlen (tokens[i]) + 1;
+}
 
-   if (next != NULL)
+   if (i != tokens.length ())
  {
char *buffer = XALLOCAVEC (char, start + 2);
sprintf (buffer, "%*c", start + 1, '^');
error ("cannot find a valid counter:value pair:");
-   error ("%<-fdbg-cnt=%s%>", next);
-   error ("  %s", buffer);
+   error ("%<-fdbg-cnt=%s%>", arg);
+   error ("   %s", buffer);
  }
 }
 


[PATCH 2/3] Extend format of -fdbg-cnt: add aux_base filter.

2019-03-27 Thread marxin

gcc/ChangeLog:

2019-03-27  Martin Liska  

* dbgcnt.c (dbg_cnt_set_limit_by_name): Add new argument
aux_base and filter based on aux_base_name.
(dbg_cnt_process_single_pair): Parse aux_base.
* doc/invoke.texi: Document new extended format.

gcc/testsuite/ChangeLog:

2019-03-27  Martin Liska  

* gcc.dg/dbg-cnt-1.c: New test.
---
 gcc/dbgcnt.c | 11 ---
 gcc/doc/invoke.texi  |  8 ++--
 gcc/testsuite/gcc.dg/dbg-cnt-1.c |  6 ++
 3 files changed, 20 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/dbg-cnt-1.c

diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index e2f65f449e5..5a7c9a8bf6e 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -24,6 +24,7 @@ See dbgcnt.def for usage information.  */
 #include "coretypes.h"
 #include "diagnostic-core.h"
 #include "dumpfile.h"
+#include "options.h"
 
 #include "dbgcnt.h"
 
@@ -87,8 +88,11 @@ dbg_cnt_set_limit_by_index (enum debug_counter index, int low, int high)
 }
 
 static bool
-dbg_cnt_set_limit_by_name (const char *name, int low, int high)
+dbg_cnt_set_limit_by_name (const char *name, int low, int high, char *aux_base)
 {
+  if (aux_base != NULL && strcmp (aux_base_name, aux_base) != 0)
+return true;
+
   if (high < low)
 {
   error ("%<-fdbg-cnt=%s:%d:%d%> has smaller upper limit than the lower",
@@ -123,7 +127,7 @@ dbg_cnt_set_limit_by_name (const char *name, int low, int high)
 }
 
 
-/* Process a single "name:value" pair.
+/* Process a single "name:value1[:value2][:aux_base]" tuple.
Returns NULL if there's no valid pair is found.
Otherwise returns a pointer to the end of the pair. */
 
@@ -134,6 +138,7 @@ dbg_cnt_process_single_pair (const char *arg)
   char *name = strtok (str, ":");
   char *value1 = strtok (NULL, ":");
   char *value2 = strtok (NULL, ":");
+  char *aux_base = strtok (NULL, ":");
 
   int high, low;
 
@@ -151,7 +156,7 @@ dbg_cnt_process_single_pair (const char *arg)
   high = strtol (value2, NULL, 10);
 }
 
-  return dbg_cnt_set_limit_by_name (name, low, high);
+  return dbg_cnt_set_limit_by_name (name, low, high, aux_base);
 }
 
 void
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4735b0ab673..d2934edd36d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -15386,10 +15386,14 @@ Print the name and the counter upper bound for all debug counters.
 @item -fdbg-cnt=@var{counter-value-list}
 @opindex fdbg-cnt
 Set the internal debug counter lower and upper bound.  @var{counter-value-list}
-is a comma-separated list of @var{name}:@var{lower_bound}:@var{upper_bound}
+is a comma-separated list of
+@var{name}:@var{lower_bound}:@var{upper_bound}:@var{aux_base_name}
 tuples which sets the lower and the upper bound of each debug
 counter @var{name}.  The @var{lower_bound} is optional and is zero
-initialized if not set.
+initialized if not set.  When @var{aux_base_name} is set, the debug counter
+is only applied to source files that match by @option{-auxbase}.
+The @var{aux_base_name} is also optional.
+
 All debug counters have the initial upper bound of @code{UINT_MAX};
 thus @code{dbg_cnt} returns true always unless the upper bound
 is set by this option.
diff --git a/gcc/testsuite/gcc.dg/dbg-cnt-1.c b/gcc/testsuite/gcc.dg/dbg-cnt-1.c
new file mode 100644
index 000..2afd2428eb9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dbg-cnt-1.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-fdbg-cnt=vect_loop:1:2,vect_slp:2,merged_ipa_icf:7:8:dbg-cnt-1" } */
+/* { dg-additional-options "-mavx2" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-prune-output "dbg_cnt 'vect_loop' set to 1-2" } */
+/* { dg-prune-output "dbg_cnt 'vect_slp' set to 0-2" } */
+/* { dg-prune-output "dbg_cnt 'merged_ipa_icf' set to 7-8" } */


[PATCH 0/3] Small clean up of profile_{count,probability}

2019-04-29 Thread marxin
The patch makes couple of adjustements:
1) I changed enum values to use capital letters. It's aligned with
   our coding style and it makes the code more readable. E.g.
   profile_quality::profile_guessed_local
   vs. static profile_probability guessed_always ()

2) I removed usage of fully qualified names.
3) I added vertical spaces to separate different functions (operators).

Survives bootstrap and tests on x86_64-linux-gnu.

Ready for trunk after 9.1 release?
Thanks,
Martin

marxin (3):
  Use cappital letters for enum value names.
  Do not use full qualified names if possible.
  Add vertical spacing in order to separate functions.

 gcc/profile-count.c |  76 +--
 gcc/profile-count.h | 320 +---
 2 files changed, 220 insertions(+), 176 deletions(-)

-- 
2.21.0



[PATCH 3/3] Add vertical spacing in order to separate functions.

2019-04-29 Thread marxin

gcc/ChangeLog:

2019-04-29  Martin Liska  

* profile-count.c: Add vertical spacing in order
to separate functions.
* profile-count.h: Likewise.
---
 gcc/profile-count.c | 25 +++---
 gcc/profile-count.h | 51 +++--
 2 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index 811f2583cdc..28ec2d11629 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -345,6 +345,7 @@ profile_count::adjust_for_ipa_scaling (profile_count *num,
if it is nonzero, not changing anything if IPA is uninitialized
and if IPA is zero, turning THIS into corresponding local profile with
global0.  */
+
 profile_count
 profile_count::combine_with_ipa_count (profile_count ipa)
 {
@@ -361,20 +362,20 @@ profile_count::combine_with_ipa_count (profile_count ipa)
 /* The profiling runtime uses gcov_type, which is usually 64bit integer.
Conversions back and forth are used to read the coverage and get it
into internal representation.  */
+
 profile_count
 profile_count::from_gcov_type (gcov_type v)
-  {
-profile_count ret;
-gcc_checking_assert (v >= 0);
-if (dump_file && v >= (gcov_type)max_count)
-  fprintf (dump_file,
-	   "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
-	   (int64_t) v, (int64_t) max_count);
-ret.m_val = MIN (v, (gcov_type)max_count);
-ret.m_quality = PRECISE;
-return ret;
-  }
-
+{
+  profile_count ret;
+  gcc_checking_assert (v >= 0);
+  if (dump_file && v >= (gcov_type)max_count)
+fprintf (dump_file,
+	 "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
+	 (int64_t) v, (int64_t) max_count);
+  ret.m_val = MIN (v, (gcov_type)max_count);
+  ret.m_quality = PRECISE;
+  return ret;
+}
 
 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
happens with COUNT2 probablity. Return probablity that either *THIS or
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 332af08a1ad..377d09e85b5 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -29,11 +29,13 @@ class profile_count;
 enum profile_quality {
   /* Uninitialized value.  */
   UNINITIALIZED_PROFILE,
+
   /* Profile is based on static branch prediction heuristics and may
  or may not match reality.  It is local to function and cannot be compared
  inter-procedurally.  Never used by probabilities (they are always local).
*/
   GUESSED_LOCAL,
+
   /* Profile was read by feedback and was 0, we used local heuristics to guess
  better.  This is the case of functions not run in profile fedback.
  Never used by probabilities.  */
@@ -48,12 +50,15 @@ enum profile_quality {
   with feedback and propagated from that).
  Never used by probablities.  */
   GUESSED,
+
   /* Profile was determined by autofdo.  */
   AFDO,
+
   /* Profile was originally based on feedback but it was adjusted
  by code duplicating optimization.  It may not precisely reflect the
  particular code path.  */
   ADJUSTED,
+
   /* Profile was read from profile feedback or determined by accurate static
  method.  */
   PRECISE
@@ -158,6 +163,7 @@ public:
   ret.m_quality = PRECISE;
   return ret;
 }
+
   static profile_probability guessed_never ()
 {
   profile_probability ret;
@@ -165,6 +171,7 @@ public:
   ret.m_quality = GUESSED;
   return ret;
 }
+
   static profile_probability very_unlikely ()
 {
   /* Be consistent with PROB_VERY_UNLIKELY in predict.h.  */
@@ -172,6 +179,7 @@ public:
   r.m_val--;
   return r;
 }
+
   static profile_probability unlikely ()
 {
   /* Be consistent with PROB_VERY_LIKELY in predict.h.  */
@@ -179,18 +187,22 @@ public:
   r.m_val--;
   return r;
 }
+
   static profile_probability even ()
 {
   return guessed_always ().apply_scale (1, 2);
 }
+
   static profile_probability very_likely ()
 {
   return always () - very_unlikely ();
 }
+
   static profile_probability likely ()
 {
   return always () - unlikely ();
 }
+
   static profile_probability guessed_always ()
 {
   profile_probability ret;
@@ -198,6 +210,7 @@ public:
   ret.m_quality = GUESSED;
   return ret;
 }
+
   static profile_probability always ()
 {
   profile_probability ret;
@@ -205,6 +218,7 @@ public:
   ret.m_quality = PRECISE;
   return ret;
 }
+
   /* Probabilities which has not been initialized. Either because
  initialization did not happen yet or because profile is unknown.  */
   static profile_probability uninitialized ()
@@ -215,12 +229,12 @@ public:
   return c;
 }
 
-
   /* Return true if value has been initialized.  */
   bool initialized_p () const
 {
   return m_val != uninitialized_probability;
 }
+
   /* Return true if value can be trusted.  */
   bool reliable_p () const
 {
@@ -237,6 +251,7 @@ public:
   ret.m_qu

[PATCH 2/3] Do not use full qualified names if possible.

2019-04-29 Thread marxin

gcc/ChangeLog:

2019-04-29  Martin Liska  

* profile-count.h: Do not use full qualified
names if possible.
* profile-count.c (profile_count::to_frequency): Likewise.
---
 gcc/profile-count.c |  15 ++---
 gcc/profile-count.h | 155 ++--
 2 files changed, 83 insertions(+), 87 deletions(-)

diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index c7d01e67c49..811f2583cdc 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -260,7 +260,7 @@ profile_count::to_frequency (struct function *fun) const
 {
   if (!initialized_p ())
 return BB_FREQ_MAX;
-  if (*this == profile_count::zero ())
+  if (*this == zero ())
 return 0;
   gcc_assert (REG_BR_PROB_BASE == BB_FREQ_MAX
 	  && fun->cfg->count_max.initialized_p ());
@@ -279,7 +279,7 @@ profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
 {
   if (!initialized_p () || !entry_bb_count.initialized_p ())
 return CGRAPH_FREQ_BASE;
-  if (*this == profile_count::zero ())
+  if (*this == zero ())
 return 0;
   gcc_checking_assert (entry_bb_count.initialized_p ());
   uint64_t scale;
@@ -302,7 +302,7 @@ profile_count::to_sreal_scale (profile_count in, bool *known) const
 }
   if (known)
 *known = true;
-  if (*this == profile_count::zero ())
+  if (*this == zero ())
 return 0;
 
   if (!in.m_val)
@@ -329,7 +329,7 @@ profile_count::adjust_for_ipa_scaling (profile_count *num,
   if (*num == *den)
 return;
   /* Scaling to zero is always zero.  */
-  if (*num == profile_count::zero ())
+  if (*num == zero ())
 return;
   /* If den is non-zero we are safe.  */
   if (den->force_nonzero () == *den)
@@ -351,9 +351,9 @@ profile_count::combine_with_ipa_count (profile_count ipa)
   ipa = ipa.ipa ();
   if (ipa.nonzero_p ())
 return ipa;
-  if (!ipa.initialized_p () || *this == profile_count::zero ())
+  if (!ipa.initialized_p () || *this == zero ())
 return *this;
-  if (ipa == profile_count::zero ())
+  if (ipa == zero ())
 return this->global0 ();
   return this->global0adjusted ();
 }
@@ -398,6 +398,5 @@ profile_probability::combine_with_count (profile_count count1,
 return *this * count1.probability_in (count1 + count2)
 	   + other * count2.probability_in (count1 + count2);
   else
-return *this * profile_probability::even ()
-	   + other * profile_probability::even ();
+return *this * even () + other * even ();
 }
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 2cf3dffc1d3..332af08a1ad 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -168,30 +168,28 @@ public:
   static profile_probability very_unlikely ()
 {
   /* Be consistent with PROB_VERY_UNLIKELY in predict.h.  */
-  profile_probability r
-	 = profile_probability::guessed_always ().apply_scale (1, 2000);
+  profile_probability r = guessed_always ().apply_scale (1, 2000);
   r.m_val--;
   return r;
 }
   static profile_probability unlikely ()
 {
   /* Be consistent with PROB_VERY_LIKELY in predict.h.  */
-  profile_probability r
-	 = profile_probability::guessed_always ().apply_scale (1, 5);
+  profile_probability r = guessed_always ().apply_scale (1, 5);
   r.m_val--;
   return r;
 }
   static profile_probability even ()
 {
-  return profile_probability::guessed_always ().apply_scale (1, 2);
+  return guessed_always ().apply_scale (1, 2);
 }
   static profile_probability very_likely ()
 {
-  return profile_probability::always () - very_unlikely ();
+  return always () - very_unlikely ();
 }
   static profile_probability likely ()
 {
-  return profile_probability::always () - unlikely ();
+  return always () - unlikely ();
 }
   static profile_probability guessed_always ()
 {
@@ -257,8 +255,7 @@ public:
 {
   gcc_checking_assert (initialized_p ());
   int ret = m_val * 8 + m_quality;
-  gcc_checking_assert (profile_probability::from_reg_br_prob_note (ret)
-			   == *this);
+  gcc_checking_assert (from_reg_br_prob_note (ret) == *this);
   return ret;
 }
 
@@ -288,12 +285,12 @@ public:
 }
   profile_probability operator+ (const profile_probability &other) const
 {
-  if (other == profile_probability::never ())
+  if (other == never ())
 	return *this;
-  if (*this == profile_probability::never ())
+  if (*this == never ())
 	return other;
   if (!initialized_p () || !other.initialized_p ())
-	return profile_probability::uninitialized ();
+	return uninitialized ();
 
   profile_probability ret;
   ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
@@ -302,15 +299,15 @@ public:
 }
   profile_probability &operator+= (const profile_probability &other)
 {
-  if (other == profile_probability::never ())
+  if (other == never ())
 	return *this;
-  if (*this == profile_probability::never ())
+  if (*this == never ())
 	{
 	  *this = othe

[PATCH 1/3] Use cappital letters for enum value names.

2019-04-29 Thread marxin

gcc/ChangeLog:

2019-04-29  Martin Liska  

* profile-count.h (enum profile_quality): Use cappital letters
for enum value names.  Use the adjusted names.
* profile-count.c: Use the adjusted names.
---
 gcc/profile-count.c |  38 +++
 gcc/profile-count.h | 114 ++--
 2 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index 8c58f8666f0..c7d01e67c49 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -42,21 +42,21 @@ profile_quality_as_string (enum profile_quality quality)
 {
 default:
   gcc_unreachable ();
-case profile_uninitialized:
+case UNINITIALIZED_PROFILE:
   return "uninitialized";
-case profile_guessed_local:
+case GUESSED_LOCAL:
   return "guessed_local";
-case profile_guessed_global0:
+case GUESSED_GLOBAL0:
   return "guessed_global0";
-case profile_guessed_global0adjusted:
+case GUESSED_GLOBAL0_ADJUSTED:
   return "guessed_global0adjusted";
-case profile_guessed:
+case GUESSED:
   return "guessed";
-case profile_afdo:
+case AFDO:
   return "afdo";
-case profile_adjusted:
+case ADJUSTED:
   return "adjusted";
-case profile_precise:
+case PRECISE:
   return "precise";
 }
 }
@@ -71,19 +71,19 @@ profile_count::dump (FILE *f) const
   else
 {
   fprintf (f, "%" PRId64, m_val);
-  if (m_quality == profile_guessed_local)
+  if (m_quality == GUESSED_LOCAL)
 	fprintf (f, " (estimated locally)");
-  else if (m_quality == profile_guessed_global0)
+  else if (m_quality == GUESSED_GLOBAL0)
 	fprintf (f, " (estimated locally, globally 0)");
-  else if (m_quality == profile_guessed_global0adjusted)
+  else if (m_quality == GUESSED_GLOBAL0_ADJUSTED)
 	fprintf (f, " (estimated locally, globally 0 adjusted)");
-  else if (m_quality == profile_adjusted)
+  else if (m_quality == ADJUSTED)
 	fprintf (f, " (adjusted)");
-  else if (m_quality == profile_afdo)
+  else if (m_quality == AFDO)
 	fprintf (f, " (auto FDO)");
-  else if (m_quality == profile_guessed)
+  else if (m_quality == GUESSED)
 	fprintf (f, " (guessed)");
-  else if (m_quality == profile_precise)
+  else if (m_quality == PRECISE)
 	fprintf (f, " (precise)");
 }
 }
@@ -160,11 +160,11 @@ profile_probability::dump (FILE *f) const
 fprintf (f, "always");
   else
 fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
-  if (m_quality == profile_adjusted)
+  if (m_quality == ADJUSTED)
 	fprintf (f, " (adjusted)");
-  else if (m_quality == profile_afdo)
+  else if (m_quality == AFDO)
 	fprintf (f, " (auto FDO)");
-  else if (m_quality == profile_guessed)
+  else if (m_quality == GUESSED)
 	fprintf (f, " (guessed)");
 }
 }
@@ -371,7 +371,7 @@ profile_count::from_gcov_type (gcov_type v)
 	   "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
 	   (int64_t) v, (int64_t) max_count);
 ret.m_val = MIN (v, (gcov_type)max_count);
-ret.m_quality = profile_precise;
+ret.m_quality = PRECISE;
 return ret;
   }
 
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index d6de61f0a61..2cf3dffc1d3 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -28,35 +28,35 @@ class profile_count;
inside of classes, this is in global namespace.  */
 enum profile_quality {
   /* Uninitialized value.  */
-  profile_uninitialized,
+  UNINITIALIZED_PROFILE,
   /* Profile is based on static branch prediction heuristics and may
  or may not match reality.  It is local to function and cannot be compared
  inter-procedurally.  Never used by probabilities (they are always local).
*/
-  profile_guessed_local,
+  GUESSED_LOCAL,
   /* Profile was read by feedback and was 0, we used local heuristics to guess
  better.  This is the case of functions not run in profile fedback.
  Never used by probabilities.  */
-  profile_guessed_global0,
+  GUESSED_GLOBAL0,
 
-  /* Same as profile_guessed_global0 but global count is adjusted 0.  */
-  profile_guessed_global0adjusted,
+  /* Same as GUESSED_GLOBAL0 but global count is adjusted 0.  */
+  GUESSED_GLOBAL0_ADJUSTED,
 
   /* Profile is based on static branch prediction heuristics.  It may or may
  not reflect the reality but it can be compared interprocedurally
  (for example, we inlined function w/o profile feedback into function
   with feedback and propagated from that).
  Never used by probablities.  */
-  profile_guessed,
+  GUESSED,
   /* Profile was determined by autofdo.  */
-  profile_afdo,
+  AFDO,
   /* Profile was originally based on feedback but it was adjusted
  by code duplicating optimization.  It may not precisely reflect the
  particular code path.  */
-  profile_adjusted,
+  ADJUSTED,
   /* Profile was read from profile feedback or determined by accurate static
  metho

[PATCH 0/2] gcov for huge cyclic graph (PR gcov-profile/90380)

2019-05-09 Thread marxin
Hi.

The PR is about a huge number of basic blocks that belong to a line.
Apparently, it's a generated code coming from Fortran module end statement.
I'm doing fix in 2 steps:

1) I dropped NEGATIVE_LOOP as that can't happen. I've tested that on GCC
   and works fine.
2) Cycle detection algorithm should not use zero edges.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
I'll install it if there will be no objections.

Martin

marxin (2):
  Test for not existence of a negative loop (PR gcov-profile/90380).
  Do not follow zero edges in cycle detection (PR gcov-profile/90380).

 gcc/gcov.c | 61 +-
 1 file changed, 24 insertions(+), 37 deletions(-)

-- 
2.21.0



[PATCH 2/2] Do not follow zero edges in cycle detection (PR gcov-profile/90380).

2019-05-09 Thread marxin

gcc/ChangeLog:

2019-05-09  Martin Liska  

* gcov.c (circuit): Ignore zero count arcs.
---
 gcc/gcov.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 6bcd2b23748..f409d67e12c 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -742,7 +742,9 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
   for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
 {
   block_info *w = arc->dst;
-  if (w < start || !linfo.has_block (w))
+  if (w < start
+	  || arc->count == 0
+	  || !linfo.has_block (w))
 	continue;
 
   path.push_back (arc);
@@ -765,7 +767,9 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
   {
 	block_info *w = arc->dst;
-	if (w < start || !linfo.has_block (w))
+	if (w < start
+	|| arc->count == 0
+	|| !linfo.has_block (w))
 	  continue;
 
 	size_t index


[PATCH 1/2] Test for not existence of a negative loop (PR gcov-profile/90380).

2019-05-09 Thread marxin

gcc/ChangeLog:

2019-05-09  Martin Liska  

PR gcov-profile/90380
* gcov.c (enum loop_type): Remove the enum and
the operator.
(handle_cycle): Assert that we should not reach
a negative count.
(circuit): Use loop_found instead of a tri-state loop_type.
(get_cycles_count): Do not handle NEGATIVE_LOOP as it can't
happen.
---
 gcc/gcov.c | 53 ++---
 1 file changed, 18 insertions(+), 35 deletions(-)

diff --git a/gcc/gcov.c b/gcc/gcov.c
index 1fc37a07c34..6bcd2b23748 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -676,27 +676,11 @@ bool function_info::group_line_p (unsigned n, unsigned src_idx)
 typedef vector arc_vector_t;
 typedef vector block_vector_t;
 
-/* Enum with types of loop in CFG.  */
-
-enum loop_type
-{
-  NO_LOOP = 0,
-  LOOP = 1,
-  NEGATIVE_LOOP = 3
-};
-
-/* Loop_type operator that merges two values: A and B.  */
-
-inline loop_type& operator |= (loop_type& a, loop_type b)
-{
-return a = static_cast (a | b);
-}
-
 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
and subtract the value from all counts.  The subtracted value is added
to COUNT.  Returns type of loop.  */
 
-static loop_type
+static void
 handle_cycle (const arc_vector_t &edges, int64_t &count)
 {
   /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
@@ -712,7 +696,7 @@ handle_cycle (const arc_vector_t &edges, int64_t &count)
   for (unsigned i = 0; i < edges.size (); i++)
 edges[i]->cs_count -= cycle_count;
 
-  return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
+  gcc_assert (cycle_count >= 0);
 }
 
 /* Unblock a block U from BLOCKED.  Apart from that, iterate all blocks
@@ -743,12 +727,12 @@ unblock (const block_info *u, block_vector_t &blocked,
blocked by a block.  COUNT is accumulated count of the current LINE.
Returns what type of loop it contains.  */
 
-static loop_type
+static bool
 circuit (block_info *v, arc_vector_t &path, block_info *start,
 	 block_vector_t &blocked, vector &block_lists,
 	 line_info &linfo, int64_t &count)
 {
-  loop_type result = NO_LOOP;
+  bool loop_found = false;
 
   /* Add v to the block list.  */
   gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
@@ -763,15 +747,19 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
 
   path.push_back (arc);
   if (w == start)
-	/* Cycle has been found.  */
-	result |= handle_cycle (path, count);
+	{
+	  /* Cycle has been found.  */
+	  handle_cycle (path, count);
+	  loop_found = true;
+	}
   else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
-	result |= circuit (w, path, start, blocked, block_lists, linfo, count);
+	loop_found |= circuit (w, path, start, blocked, block_lists, linfo,
+			   count);
 
   path.pop_back ();
 }
 
-  if (result != NO_LOOP)
+  if (loop_found)
 unblock (v, blocked, block_lists);
   else
 for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
@@ -788,14 +776,13 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
 	  list.push_back (v);
   }
 
-  return result;
+  return loop_found;
 }
 
-/* Find cycles for a LINFO.  If HANDLE_NEGATIVE_CYCLES is set and the line
-   contains a negative loop, then perform the same function once again.  */
+/* Find cycles for a LINFO.  */
 
 static gcov_type
-get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
+get_cycles_count (line_info &linfo)
 {
   /* Note that this algorithm works even if blocks aren't in sorted order.
  Each iteration of the circuit detection is completely independent
@@ -803,7 +790,7 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
  Therefore, operating on a permuted order (i.e., non-sorted) only
  has the effect of permuting the output cycles.  */
 
-  loop_type result = NO_LOOP;
+  bool loop_found = false;
   gcov_type count = 0;
   for (vector::iterator it = linfo.blocks.begin ();
it != linfo.blocks.end (); it++)
@@ -811,14 +798,10 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
   arc_vector_t path;
   block_vector_t blocked;
   vector block_lists;
-  result |= circuit (*it, path, *it, blocked, block_lists, linfo,
-			 count);
+  loop_found |= circuit (*it, path, *it, blocked, block_lists, linfo,
+			 count);
 }
 
-  /* If we have a negative cycle, repeat the find_cycles routine.  */
-  if (result == NEGATIVE_LOOP && handle_negative_cycles)
-count += get_cycles_count (linfo, false);
-
   return count;
 }
 


[PATCH 1/3] Do a refactoring in linemap (PR preprocessor/90382).

2019-05-14 Thread marxin

libcpp/ChangeLog:

2019-05-13  Martin Liska  

PR preprocessor/90382
* include/line-map.h (get_data_from_adhoc_loc): Add const to
the first argument.
(get_location_from_adhoc_loc): Likewise.
* line-map.c(get_data_from_adhoc_loc):  Add const to
the first argument.
(get_location_from_adhoc_loc): Likewise.
(get_combined_adhoc_loc): Use get_location_from_adhoc_loc
(or get_data_from_adhoc_loc).
(get_range_from_adhoc_loc): Likewise.
(get_pure_location): Likewise.
(linemap_position_for_loc_and_offset): Likewise.
(linemap_lookup): Likewise.
(linemap_ordinary_map_lookup): Likewise.
(linemap_macro_map_lookup): Likewise.
(linemap_get_expansion_line): Likewise.
(linemap_get_expansion_filename): Likewise.
(linemap_location_in_system_header_p): Likewise.
(linemap_location_from_macro_expansion_p): Likewise.
(linemap_macro_loc_to_exp_point): Likewise.
(linemap_resolve_location): Likewise.
(linemap_unwind_toward_expansion): Likewise.
(linemap_unwind_to_first_non_reserved_loc): Likewise.
(linemap_expand_location): Likewise.
(linemap_dump_location): Likewise.
---
 libcpp/include/line-map.h |  4 ++--
 libcpp/line-map.c | 48 ---
 2 files changed, 22 insertions(+), 30 deletions(-)

diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 6c77c288855..7649700e8a5 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1054,8 +1054,8 @@ extern location_t get_combined_adhoc_loc (struct line_maps *,
 	   location_t,
 	   source_range,
 	   void *);
-extern void *get_data_from_adhoc_loc (struct line_maps *, location_t);
-extern location_t get_location_from_adhoc_loc (struct line_maps *,
+extern void *get_data_from_adhoc_loc (const struct line_maps *, location_t);
+extern location_t get_location_from_adhoc_loc (const struct line_maps *,
 		location_t);
 
 extern source_range get_range_from_loc (line_maps *set, location_t loc);
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index b73f5067c24..e1fc0e9faf4 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -163,8 +163,7 @@ get_combined_adhoc_loc (struct line_maps *set,
   struct location_adhoc_data **slot;
 
   if (IS_ADHOC_LOC (locus))
-locus
-  = set->location_adhoc_data_map.data[locus & MAX_LOCATION_T].locus;
+locus = get_location_from_adhoc_loc (set, locus);
   if (locus == 0 && data == NULL)
 return 0;
 
@@ -243,7 +242,7 @@ get_combined_adhoc_loc (struct line_maps *set,
 /* Return the data for the adhoc loc.  */
 
 void *
-get_data_from_adhoc_loc (struct line_maps *set, location_t loc)
+get_data_from_adhoc_loc (const struct line_maps *set, location_t loc)
 {
   linemap_assert (IS_ADHOC_LOC (loc));
   return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].data;
@@ -252,7 +251,7 @@ get_data_from_adhoc_loc (struct line_maps *set, location_t loc)
 /* Return the location for the adhoc loc.  */
 
 location_t
-get_location_from_adhoc_loc (struct line_maps *set, location_t loc)
+get_location_from_adhoc_loc (const struct line_maps *set, location_t loc)
 {
   linemap_assert (IS_ADHOC_LOC (loc));
   return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus;
@@ -261,7 +260,7 @@ get_location_from_adhoc_loc (struct line_maps *set, location_t loc)
 /* Return the source_range for adhoc location LOC.  */
 
 static source_range
-get_range_from_adhoc_loc (struct line_maps *set, location_t loc)
+get_range_from_adhoc_loc (const struct line_maps *set, location_t loc)
 {
   linemap_assert (IS_ADHOC_LOC (loc));
   return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].src_range;
@@ -321,8 +320,7 @@ location_t
 get_pure_location (line_maps *set, location_t loc)
 {
   if (IS_ADHOC_LOC (loc))
-loc
-  = set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus;
+loc = get_location_from_adhoc_loc (set, loc);
 
   if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
 return loc;
@@ -872,7 +870,7 @@ linemap_position_for_loc_and_offset (struct line_maps *set,
   const line_map_ordinary * map = NULL;
 
   if (IS_ADHOC_LOC (loc))
-loc = set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus;
+loc = get_location_from_adhoc_loc (set, loc);
 
   /* This function does not support virtual locations yet.  */
   if (linemap_location_from_macro_expansion_p (set, loc))
@@ -934,7 +932,7 @@ const struct line_map*
 linemap_lookup (struct line_maps *set, location_t line)
 {
   if (IS_ADHOC_LOC (line))
-line = set->location_adhoc_data_map.data[line & MAX_LOCATION_T].locus;
+line = get_location_from_adhoc_loc (set, line);
   if (linemap_location_from_macro_expansion_p (set, line))
 return linemap_macro_map_lookup (set, line);
   return linemap_ordinary_map_lookup (set, line);
@@ -952,7 +950,7 @@ linemap_ordinary_map_lookup (stru

[PATCH 0/3] Fix linemap assertation connected to PR preprocessor/90382.

2019-05-14 Thread marxin
Hi.

I'm sending series of 3 patches where first part is a refactoring in
order to use get_location_from_adhoc_loc and get_data_from_adhoc_loc.
Second part is dealing with the ICE and is about using
of get_location_from_adhoc_loc for IS_ADHOC_LOC.
Last one is reappliation of Paolo's patch.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready for trunk?
Thanks,
Martin

marxin (2):
  Do a refactoring in linemap (PR preprocessor/90382).
  Fix min_location usage in line-map.c (PR preprocessor/90382).

paolo (1):
  /cp 2018-05-14 Paolo Carlini 

 gcc/cp/decl.c   |  4 +-
 gcc/testsuite/g++.dg/diagnostic/trailing1.C |  5 ++
 libcpp/include/line-map.h   |  4 +-
 libcpp/line-map.c   | 57 ++---
 4 files changed, 36 insertions(+), 34 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/trailing1.C

-- 
2.21.0



[PATCH 2/3] Fix min_location usage in line-map.c (PR preprocessor/90382).

2019-05-14 Thread marxin

libcpp/ChangeLog:

2019-05-13  Martin Liska  

PR preprocessor/90382
* line-map.c (first_map_in_common_1): Handle ADHOC
locations.
---
 libcpp/line-map.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index e1fc0e9faf4..31439f4aba3 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1251,8 +1251,13 @@ first_map_in_common_1 (struct line_maps *set,
 		   location_t *loc1)
 {
   location_t l0 = *loc0, l1 = *loc1;
-  const struct line_map *map0 = linemap_lookup (set, l0),
-*map1 = linemap_lookup (set, l1);
+  const struct line_map *map0 = linemap_lookup (set, l0);
+  if (IS_ADHOC_LOC (l0))
+l0 = get_location_from_adhoc_loc (set, l0);
+
+  const struct line_map *map1 = linemap_lookup (set, l1);
+  if (IS_ADHOC_LOC (l1))
+l1 = get_location_from_adhoc_loc (set, l1);
 
   while (linemap_macro_expansion_map_p (map0)
 	 && linemap_macro_expansion_map_p (map1)


[PATCH 0/3] Better folding of 2 string builtin-ins

2016-08-16 Thread marxin
Hi.

During playing with -fprofile-values I've noticed that some builtins
are not folded ideally. Fixing in attached mini patch series.

Patch can bootstrap on ppc64le-redhat-linux and survives regression tests.

Ready to be installed?
Martin

marxin (3):
  Fold BUILT_IN_STRNCASECMP
  Smarter folding of __builtin_memchr
  Test folding of strn{case}cmp and memchr

 gcc/builtins.c   | 39 
 gcc/testsuite/gcc.dg/tree-ssa/builtins-folding.c | 59 
 2 files changed, 88 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/builtins-folding.c

-- 
2.9.2



  1   2   >