diff options
author | yroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-03-05 14:28:05 +0000 |
---|---|---|
committer | yroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-03-05 14:28:05 +0000 |
commit | 984a1f8a9b9b2e3c1a81588353b46930f49409fc (patch) | |
tree | 5005d3a84c488437fd79790ad6316f6c0146e152 | |
parent | 1d1384dd7748a6c2f6eaf36d348eaa5194ed08f2 (diff) |
gcc/
2015-03-05 Yvan Roux <yvan.roux@linaro.org>
Backport from trunk r212011, r214942, r214957, r215012, r215016, r218115,
r218733, r218746, r220491.
2015-02-06 Sebastian Pop <s.pop@samsung.com>
Brian Rzycki <b.rzycki@samsung.com>
PR tree-optimization/64878
* tree-ssa-threadedge.c: Include tree-ssa-loop.h.
(fsm_find_control_statement_thread_paths): Add parameter seen_loop_phi.
Stop recursion at loop phi nodes after having visited a loop phi node.
2014-12-15 Richard Biener <rguenther@suse.de>
PR middle-end/64246
* cfgloop.c (mark_loop_for_removal): Make safe against multiple
invocations on the same loop.
2014-12-15 Richard Biener <rguenther@suse.de>
PR tree-optimization/64284
* tree-ssa-threadupdate.c (duplicate_seme_region): Mark
the loop for removal if we copied the loop header.
2014-11-27 Richard Biener <rguenther@suse.de>
PR tree-optimization/64083
* tree-ssa-threadupdate.c (thread_through_all_blocks): Do not
forcibly mark loop for removal the wrong way.
2014-09-08 Richard Biener <rguenther@suse.de>
PR ipa/63196
* tree-inline.c (copy_loops): The source loop header should
always be non-NULL.
(tree_function_versioning): If loops need fixup after removing
unreachable blocks fix them.
* omp-low.c (simd_clone_adjust): Do not add incr block to
loop under construction.
2014-09-08 Richard Biener <rguenther@suse.de>
PR bootstrap/63204
* cfgloop.c (mark_loop_for_removal): Track former header
unconditionally.
* cfgloop.h (struct loop): Add former_header member unconditionally.
* loop-init.c (fix_loop_structure): Enable bogus loop removal
diagnostic unconditionally.
2014-09-05 Richard Biener <rguenther@suse.de>
* cfgloop.c (mark_loop_for_removal): Record former header
when ENABLE_CHECKING.
* cfgloop.h (strut loop): Add former_header member when
ENABLE_CHECKING.
* loop-init.c (fix_loop_structure): Sanity check loops
marked for removal if they re-appeared.
2014-09-05 Richard Biener <rguenther@suse.de>
* cfgloop.c (mark_loop_for_removal): New function.
* cfgloop.h (mark_loop_for_removal): Declare.
* cfghooks.c (delete_basic_block): Use mark_loop_for_removal.
(merge_blocks): Likewise.
(duplicate_block): Likewise.
* except.c (sjlj_emit_dispatch_table): Likewise.
* tree-eh.c (cleanup_empty_eh_merge_phis): Likewise.
* tree-ssa-threadupdate.c (ssa_redirect_edges): Likewise.
(thread_through_loop_header): Likewise.
2014-06-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/61607
* tree-ssa-threadupdate.c (ssa_redirect_edges): Cancel the
loop if we redirected its latch edge.
(thread_block_1): Do not cancel loops prematurely.
gcc/testsuite/
2015-03-05 Yvan Roux <yvan.roux@linaro.org>
Backport from trunk r218115, r218733, r218746, r220491.
2015-02-06 Sebastian Pop <s.pop@samsung.com>
Brian Rzycki <b.rzycki@samsung.com>
PR tree-optimization/64878
* testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c: New.
2014-12-15 Richard Biener <rguenther@suse.de>
PR middle-end/64246
* gnat.dg/opt46.adb: New testcase.
* gnat.dg/opt46.ads: Likewise.
* gnat.dg/opt46_pkg.adb: Likewise.
* gnat.dg/opt46_pkg.ads: Likewise.
2014-12-15 Richard Biener <rguenther@suse.de>
PR tree-optimization/64284
* gcc.dg/torture/pr64284.c: New testcase.
2014-11-27 Richard Biener <rguenther@suse.de>
PR tree-optimization/64083
* gcc.dg/torture/pr64083.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@221216 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog.linaro | 77 | ||||
-rw-r--r-- | gcc/cfghooks.c | 18 | ||||
-rw-r--r-- | gcc/cfgloop.c | 13 | ||||
-rw-r--r-- | gcc/cfgloop.h | 8 | ||||
-rw-r--r-- | gcc/except.c | 5 | ||||
-rw-r--r-- | gcc/loop-init.c | 31 | ||||
-rw-r--r-- | gcc/omp-low.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog.linaro | 27 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr64083.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr64284.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c | 440 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt46.adb | 45 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt46.ads | 16 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt46_pkg.adb | 8 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt46_pkg.ads | 31 | ||||
-rw-r--r-- | gcc/tree-eh.c | 5 | ||||
-rw-r--r-- | gcc/tree-inline.c | 12 | ||||
-rw-r--r-- | gcc/tree-ssa-threadedge.c | 19 | ||||
-rw-r--r-- | gcc/tree-ssa-threadupdate.c | 54 |
19 files changed, 776 insertions, 75 deletions
diff --git a/gcc/ChangeLog.linaro b/gcc/ChangeLog.linaro index ee9ef6ac71e..6801455023b 100644 --- a/gcc/ChangeLog.linaro +++ b/gcc/ChangeLog.linaro @@ -1,5 +1,82 @@ 2015-03-05 Yvan Roux <yvan.roux@linaro.org> + Backport from trunk r212011, r214942, r214957, r215012, r215016, r218115, + r218733, r218746, r220491. + 2015-02-06 Sebastian Pop <s.pop@samsung.com> + Brian Rzycki <b.rzycki@samsung.com> + + PR tree-optimization/64878 + * tree-ssa-threadedge.c: Include tree-ssa-loop.h. + (fsm_find_control_statement_thread_paths): Add parameter seen_loop_phi. + Stop recursion at loop phi nodes after having visited a loop phi node. + + 2014-12-15 Richard Biener <rguenther@suse.de> + + PR middle-end/64246 + * cfgloop.c (mark_loop_for_removal): Make safe against multiple + invocations on the same loop. + + 2014-12-15 Richard Biener <rguenther@suse.de> + + PR tree-optimization/64284 + * tree-ssa-threadupdate.c (duplicate_seme_region): Mark + the loop for removal if we copied the loop header. + + 2014-11-27 Richard Biener <rguenther@suse.de> + + PR tree-optimization/64083 + * tree-ssa-threadupdate.c (thread_through_all_blocks): Do not + forcibly mark loop for removal the wrong way. + + 2014-09-08 Richard Biener <rguenther@suse.de> + + PR ipa/63196 + * tree-inline.c (copy_loops): The source loop header should + always be non-NULL. + (tree_function_versioning): If loops need fixup after removing + unreachable blocks fix them. + * omp-low.c (simd_clone_adjust): Do not add incr block to + loop under construction. + + 2014-09-08 Richard Biener <rguenther@suse.de> + + PR bootstrap/63204 + * cfgloop.c (mark_loop_for_removal): Track former header + unconditionally. + * cfgloop.h (struct loop): Add former_header member unconditionally. + * loop-init.c (fix_loop_structure): Enable bogus loop removal + diagnostic unconditionally. + + 2014-09-05 Richard Biener <rguenther@suse.de> + + * cfgloop.c (mark_loop_for_removal): Record former header + when ENABLE_CHECKING. + * cfgloop.h (strut loop): Add former_header member when + ENABLE_CHECKING. + * loop-init.c (fix_loop_structure): Sanity check loops + marked for removal if they re-appeared. + + 2014-09-05 Richard Biener <rguenther@suse.de> + + * cfgloop.c (mark_loop_for_removal): New function. + * cfgloop.h (mark_loop_for_removal): Declare. + * cfghooks.c (delete_basic_block): Use mark_loop_for_removal. + (merge_blocks): Likewise. + (duplicate_block): Likewise. + * except.c (sjlj_emit_dispatch_table): Likewise. + * tree-eh.c (cleanup_empty_eh_merge_phis): Likewise. + * tree-ssa-threadupdate.c (ssa_redirect_edges): Likewise. + (thread_through_loop_header): Likewise. + + 2014-06-26 Richard Biener <rguenther@suse.de> + + PR tree-optimization/61607 + * tree-ssa-threadupdate.c (ssa_redirect_edges): Cancel the + loop if we redirected its latch edge. + (thread_block_1): Do not cancel loops prematurely. + +2015-03-05 Yvan Roux <yvan.roux@linaro.org> + Backport from trunk r220860. 2015-02-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com> diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index bc1634aac87..53da0d9a9f0 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -569,14 +569,10 @@ delete_basic_block (basic_block bb) struct loop *loop = bb->loop_father; /* If we remove the header or the latch of a loop, mark the loop for - removal by setting its header and latch to NULL. */ + removal. */ if (loop->latch == bb || loop->header == bb) - { - loop->header = NULL; - loop->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP); - } + mark_loop_for_removal (loop); remove_bb_from_loops (bb); } @@ -760,11 +756,7 @@ merge_blocks (basic_block a, basic_block b) /* ... we merge two loop headers, in which case we kill the inner loop. */ if (b->loop_father->header == b) - { - b->loop_father->header = NULL; - b->loop_father->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP); - } + mark_loop_for_removal (b->loop_father); } /* If we merge a loop header into its predecessor, update the loop structure. */ @@ -1103,9 +1095,7 @@ duplicate_block (basic_block bb, edge e, basic_block after) && cloop->header == bb) { add_bb_to_loop (new_bb, loop_outer (cloop)); - cloop->header = NULL; - cloop->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP); + mark_loop_for_removal (cloop); } else { diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 70744d83d19..ff25e012dbe 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -1919,3 +1919,16 @@ bb_loop_depth (const_basic_block bb) { return bb->loop_father ? loop_depth (bb->loop_father) : 0; } + +/* Marks LOOP for removal and sets LOOPS_NEED_FIXUP. */ + +void +mark_loop_for_removal (loop_p loop) +{ + if (loop->header == NULL) + return; + loop->former_header = loop->header; + loop->header = NULL; + loop->latch = NULL; + loops_state_set (LOOPS_NEED_FIXUP); +} diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 4b7c3d3985a..5a94fe7217d 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -192,6 +192,12 @@ struct GTY ((chain_next ("%h.next"))) loop { /* Number of iteration analysis data for RTL. */ struct niter_desc *simple_loop_desc; + + /* For sanity checking during loop fixup we record here the former + loop header for loops marked for removal. Note that this prevents + the basic-block from being collected but its index can still be + reused. */ + basic_block former_header; }; /* Flags for state of loop structure. */ @@ -335,6 +341,8 @@ struct loop * loop_version (struct loop *, void *, extern bool remove_path (edge); extern void unloop (struct loop *, bool *, bitmap); extern void scale_loop_frequencies (struct loop *, int, int); +void mark_loop_for_removal (loop_p); + /* Induction variable analysis. */ diff --git a/gcc/except.c b/gcc/except.c index 908954cbbbf..9ea813bdef1 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1394,10 +1394,7 @@ sjlj_emit_dispatch_table (rtx dispatch_label, int num_dispatch) { for (loop = bb->loop_father; loop_outer (loop); loop = loop_outer (loop)) - { - loop->header = NULL; - loop->latch = NULL; - } + mark_loop_for_removal (loop); } } diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 4cc561c2e7a..5f6e3db1327 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -245,6 +245,10 @@ fix_loop_structure (bitmap changed_bbs) } /* Remove the loop. */ + if (loop->header) + loop->former_header = loop->header; + else + gcc_assert (loop->former_header != NULL); loop->header = NULL; flow_loop_tree_node_remove (loop); } @@ -272,6 +276,33 @@ fix_loop_structure (bitmap changed_bbs) FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop) if (loop && loop->header == NULL) { + if (dump_file + && ((unsigned) loop->former_header->index + < basic_block_info_for_fn (cfun)->length ())) + { + basic_block former_header + = BASIC_BLOCK_FOR_FN (cfun, loop->former_header->index); + /* If the old header still exists we want to check if the + original loop is re-discovered or the old header is now + part of a newly discovered loop. + In both cases we should have avoided removing the loop. */ + if (former_header == loop->former_header) + { + if (former_header->loop_father->header == former_header) + fprintf (dump_file, "fix_loop_structure: rediscovered " + "removed loop %d as loop %d with old header %d\n", + loop->num, former_header->loop_father->num, + former_header->index); + else if ((unsigned) former_header->loop_father->num + >= old_nloops) + fprintf (dump_file, "fix_loop_structure: header %d of " + "removed loop %d is part of the newly " + "discovered loop %d with header %d\n", + former_header->index, loop->num, + former_header->loop_father->num, + former_header->loop_father->header->index); + } + } (*get_loops (cfun))[i] = NULL; flow_loop_free (loop); } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index f0059be6b5d..4b9c827eea9 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -11707,6 +11707,7 @@ simd_clone_adjust (struct cgraph_node *node) iteration increment and the condition/branch. */ basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src; basic_block incr_bb = create_empty_bb (orig_exit); + add_bb_to_loop (incr_bb, body_bb->loop_father); /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty flag. Set it now to be a FALLTHRU_EDGE. */ gcc_assert (EDGE_COUNT (orig_exit->succs) == 1); @@ -11731,7 +11732,6 @@ simd_clone_adjust (struct cgraph_node *node) loop->safelen = node->simdclone->simdlen; loop->force_vect = true; loop->header = body_bb; - add_bb_to_loop (incr_bb, loop); /* Branch around the body if the mask applies. */ if (node->simdclone->inbranch) @@ -11772,7 +11772,7 @@ simd_clone_adjust (struct cgraph_node *node) gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); e = split_block (incr_bb, gsi_stmt (gsi)); basic_block latch_bb = e->dest; - basic_block new_exit_bb = e->dest; + basic_block new_exit_bb; new_exit_bb = split_block (latch_bb, NULL)->dest; loop->latch = latch_bb; diff --git a/gcc/testsuite/ChangeLog.linaro b/gcc/testsuite/ChangeLog.linaro index 19ab7f1beb2..85e8a720aef 100644 --- a/gcc/testsuite/ChangeLog.linaro +++ b/gcc/testsuite/ChangeLog.linaro @@ -1,5 +1,32 @@ 2015-03-05 Yvan Roux <yvan.roux@linaro.org> + Backport from trunk r218115, r218733, r218746, r220491. + 2015-02-06 Sebastian Pop <s.pop@samsung.com> + Brian Rzycki <b.rzycki@samsung.com> + + PR tree-optimization/64878 + * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c: New. + + 2014-12-15 Richard Biener <rguenther@suse.de> + + PR middle-end/64246 + * gnat.dg/opt46.adb: New testcase. + * gnat.dg/opt46.ads: Likewise. + * gnat.dg/opt46_pkg.adb: Likewise. + * gnat.dg/opt46_pkg.ads: Likewise. + + 2014-12-15 Richard Biener <rguenther@suse.de> + + PR tree-optimization/64284 + * gcc.dg/torture/pr64284.c: New testcase. + + 2014-11-27 Richard Biener <rguenther@suse.de> + + PR tree-optimization/64083 + * gcc.dg/torture/pr64083.c: New testcase. + +2015-03-05 Yvan Roux <yvan.roux@linaro.org> + Backport from trunk r220860. 2015-02-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com> diff --git a/gcc/testsuite/gcc.dg/torture/pr64083.c b/gcc/testsuite/gcc.dg/torture/pr64083.c new file mode 100644 index 00000000000..3c3e5a6087a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr64083.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +int a, b; +void +fn1 () +{ + int c = 0; + while (b) + { + switch (c) + case 1: + fn1 (); + if (a) + c = 1; + b = 0; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr64284.c b/gcc/testsuite/gcc.dg/torture/pr64284.c new file mode 100644 index 00000000000..425438116eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr64284.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +int *a; +int b; +int +fn1() { + enum { QSTRING } c = 0; + while (1) { + switch (*a) { + case '\'': + c = 0; + default: + switch (c) + case 0: + if (b) + return 0; + c = 1; + } + a++; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c new file mode 100644 index 00000000000..9be75aaf21d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-8.c @@ -0,0 +1,440 @@ +/* PR 64878 */ +/* { dg-options "-O2" } */ +/* { dg-do run } */ + +struct A { int a1; }; +struct B { char *b1; int b2; int b3; }; +struct C { char *c1; int c2; struct B *c3; }; +extern struct A *f1 (char *s); +static struct A *f2 (struct C *x); +__attribute__ ((noinline, noclone)) int f3 (struct A *x, struct A *z) { asm volatile ("" : : "g" (x), "g" (z) : "memory"); return 0; } +__attribute__ ((noinline, noclone)) void f4 (struct A *x, char *y, struct A *z) { asm volatile ("" : : "g" (x), "g" (z), "g" (y) : "memory"); } +__attribute__ ((noinline, noclone)) struct B *f5 (void) { static char b[32]; static struct B f3 = { b, 0, 32 }; return &f3; } +__attribute__ ((noinline, noclone)) int f6 (struct B *p, char *w, int z) { asm volatile ("" : : "g" (p), "g" (w), "g" (z) : "memory"); return 0; } +__attribute__ ((noinline, noclone)) void f7 (struct B *p) { asm volatile ("" : : "g" (p) : "memory"); } +__attribute__ ((noinline, noclone)) void f8 (struct B *p) { asm volatile ("" : : "g" (p) : "memory"); } +__attribute__ ((noinline, noclone)) void f9 (struct A *x) { asm volatile ("" : : "g" (x) : "memory"); } +__attribute__ ((noinline, noclone)) struct A *f10 (void) { static struct A j; asm volatile ("" : : : "memory"); return &j; } +__attribute__ ((noinline, noclone)) struct A *f11 (void) { static struct A j; asm volatile ("" : : : "memory"); return &j; } +__attribute__ ((noinline, noclone)) struct A *f12 (int b) { static struct A j; asm volatile ("" : : "g" (b) : "memory"); return &j; } +__attribute__ ((noinline, noclone)) struct A *f13 (int i) { static struct A j; asm volatile ("" : : "g" (i) : "memory"); return &j; } +__attribute__ ((noinline, noclone)) struct A *f14 (double d) { static struct A j; asm volatile ("" : : "g" (&d) : "memory"); return &j; } +__attribute__ ((noinline, noclone)) struct A *f15 (char *s) { static struct A j; asm volatile ("" : : "g" (s) : "memory"); return &j; } +char *t = "0123456789abcdef"; +char *u = "0123456789.+-e"; + +__attribute__ ((noinline, noclone)) struct A * +f1 (char *s) +{ + struct C f; + struct A *o; + f.c1 = s; + f.c2 = 0; + f.c3 = f5 (); + o = f2 (&f); + f8 (f.c3); + return o; +} + +static struct A * +f2 (struct C *x) +{ + int a, b, e = 0; + struct A *f = 0, *o; + char *g = 0; + char h = '\0'; + int i = 0, j = 0; + a = 0; + b = 1; + char c; + do + { + c = x->c1[x->c2]; + switch (a) + { + case 0: + if (c == ' ') + x->c2++; + else if (c == '/') + { + a = 4; + j = x->c2++; + } + else + a = b; + break; + case 1: + switch (c) + { + case '{': + a = 0; + b = 15; + f = f10 (); + x->c2++; + break; + case '[': + a = 0; + b = 13; + f = f11 (); + x->c2++; + break; + case 'N': + case 'n': + a = 3; + j = x->c2++; + break; + case '"': + case '\'': + h = c; + f7 (x->c3); + a = 8; + j = ++x->c2; + break; + case 'T': + case 't': + case 'F': + case 'f': + a = 11; + j = x->c2++; + break; + case '0' ... '9': + case '-': + i = 0; + a = 12; + j = x->c2++; + break; + default: + e = 1; + goto out; + } + break; + case 2: + goto out; + case 3: + if (__builtin_strncmp ("null", x->c1 + j, x->c2 - j)) + { + e = 2; + goto out; + } + if (x->c2 - j == 4) + { + f = 0; + b = 2; + a = 0; + } + else + x->c2++; + break; + case 4: + if (c == '*') + a = 5; + else if (c == '/') + a = 6; + else + { + e = 8; + goto out; + } + x->c2++; + break; + case 5: + if (c == '*') + a = 7; + x->c2++; + break; + case 6: + if (c == '\n') + a = 0; + x->c2++; + break; + case 7: + if (c == '/') + a = 0; + else + a = 5; + x->c2++; + break; + case 8: + if (c == h) + { + f6 (x->c3, x->c1 + j, x->c2 - j); + f = f15 (x->c3->b1); + b = 2; + a = 0; + } + else if (c == '\\') + { + b = 8; + a = 9; + } + x->c2++; + break; + case 9: + switch (c) + { + case '"': + case '\\': + f6 (x->c3, x->c1 + j, x->c2 - j - 1); + j = x->c2++; + a = b; + break; + case 'b': + case 'n': + case 'r': + case 't': + f6 (x->c3, x->c1 + j, x->c2 - j - 1); + if (c == 'b') + f6 (x->c3, "\b", 1); + else if (c == 'n') + f6 (x->c3, "\n", 1); + else if (c == 'r') + f6 (x->c3, "\r", 1); + else if (c == 't') + f6 (x->c3, "\t", 1); + j = ++x->c2; + a = b; + break; + case 'u': + f6 (x->c3, x->c1 + j, x->c2 - j - 1); + j = ++x->c2; + a = 10; + break; + default: + e = 7; + goto out; + } + break; + case 10: + if (__builtin_strchr (t, c)) + { + x->c2++; + if (x->c2 - j == 4) + { + unsigned char w[3]; + unsigned int s = + (((x->c1[j] <= '9') ? x->c1[j] - '0' : (x->c1[j] & 7) + 9) << 12) + + (((x->c1[j + 1] <= '9') ? x->c1[j + 1] - '0' : (x->c1[j + 1] & 7) + 9) << 8) + + (((x->c1[j + 2] <= '9') ? x->c1[j + 2] - '0' : (x->c1[j + 2] & 7) + 9) << 4) + + ((x->c1[j + 3] <= '9') ? x->c1[j + 3] - '0' : (x->c1[j + 3] & 7) + 9); + if (s < 0x80) + { + w[0] = s; + f6 (x->c3, (char *) w, 1); + } + else if (s < 0x800) + { + w[0] = 0xc0 | (s >> 6); + w[1] = 0x80 | (s & 0x3f); + f6 (x->c3, (char *) w, 2); + } + else + { + w[0] = 0x0 | (s >> 12); + w[1] = 0x80 | ((s >> 6) & 0x3f); + w[2] = 0x80 | (s & 0x3f); + f6 (x->c3, (char *) w, 3); + } + j = x->c2; + a = b; + } + } + else + { + e = 7; + goto out; + } + break; + case 11: + if (__builtin_strncmp ("true", x->c1 + j, x->c2 - j) == 0) + { + if (x->c2 - j == 4) + { + f = f12 (1); + b = 2; + a = 0; + } + else + x->c2++; + } + else if (__builtin_strncmp ("false", x->c1 + j, x->c2 - j) == 0) + { + if (x->c2 - j == 5) + { + f = f12 (0); + b = 2; + a = 0; + } + else + x->c2++; + } + else + { + e = 3; + goto out; + } + break; + case 12: + if (!c || !__builtin_strchr (u, c)) + { + if (!i) + f = f13 (0); + else + f = f14 (0.0); + b = 2; + a = 0; + } + else + { + if (c == '.' || c == 'e') + i = 1; + x->c2++; + } + break; + case 13: + if (c == ']') + { + x->c2++; + b = 2; + a = 0; + } + else + { + o = f2 (x); + if (((unsigned long) o > (unsigned long) -4000L)) + { + e = 5; + goto out; + } + f3 (f, o); + b = 14; + a = 0; + } + break; + case 14: + if (c == ']') + { + x->c2++; + b = 2; + a = 0; + } + else if (c == ',') + { + x->c2++; + b = 13; + a = 0; + } + else + { + f9 (f); + e = 5; + goto out; + } + break; + case 15: + a = 16; + j = x->c2; + break; + case 16: + if (c == '}') + { + x->c2++; + b = 2; + a = 0; + } + else if (c == '"' || c == '\'') + { + h = c; + f7 (x->c3); + a = 17; + j = ++x->c2; + } + else + { + e = 6; + goto out; + } + break; + case 17: + if (c == h) + { + f6 (x->c3, x->c1 + j, x->c2 - j); + g = __builtin_strdup (x->c3->b1); + b = 18; + a = 0; + } + else if (c == '\\') + { + b = 17; + a = 9; + } + x->c2++; + break; + case 18: + if (c == ':') + { + x->c2++; + b = 19; + a = 0; + } + else + { + e = -6; + goto out; + } + break; + case 19: + o = f2 (x); + if (((unsigned long) o > (unsigned long) -4000L)) + { + e = 6; + goto out; + } + f4 (f, g, o); + __builtin_free (g); + g = 0; + b = 20; + a = 0; + break; + case 20: + if (c == '}') + { + x->c2++; + b = 2; + a = 0; + } + else if (c == ',') + { + x->c2++; + b = 15; + a = 0; + } + else + { + e = 6; + goto out; + } + break; + } + } + while (c); + if (a != 2 && b != 2) + e = 9; +out: + __builtin_free (g); + if (e == 0) + return f; + f9 (f); + return 0; +} + +int +main () +{ + asm volatile ("" : : : "memory"); + struct A *r = f1 ("{ \"id\": null, \"blahah\": \"foobarbazbar\", \"barbar\": { \"barbarbarba\":" + "\"abcdefgh\", \"ijklmnopqr\": \"stuvwxyzabcdefghijklmnopqrstuv\", \"xyzxyz\":" + " [ \"1\" ] } }"); + if (!r) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gnat.dg/opt46.adb b/gcc/testsuite/gnat.dg/opt46.adb new file mode 100644 index 00000000000..64e0b632e3a --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt46.adb @@ -0,0 +1,45 @@ +-- { dg-do compile } +-- { dg-options "-O" } + +with Ada.Unchecked_Deallocation; + +with Opt46_Pkg; + +package body Opt46 is + + type Pattern is abstract tagged null record; + + type Pattern_Access is access Pattern'Class; + + procedure Free is new Ada.Unchecked_Deallocation + (Pattern'Class, Pattern_Access); + + type Action is abstract tagged null record; + + type Action_Access is access Action'Class; + + procedure Free is new Ada.Unchecked_Deallocation + (Action'Class, Action_Access); + + type Pattern_Action is record + Pattern : Pattern_Access; + Action : Action_Access; + end record; + + package Pattern_Action_Table is new Opt46_Pkg (Pattern_Action, Natural, 1); + + type Session_Data is record + Filters : Pattern_Action_Table.Instance; + end record; + + procedure Close (Session : Session_Type) is + Filters : Pattern_Action_Table.Instance renames Session.Data.Filters; + begin + for F in 1 .. Pattern_Action_Table.Last (Filters) loop + Free (Filters.Table (F).Pattern); + Free (Filters.Table (F).Action); + end loop; + + end Close; + +end Opt46; diff --git a/gcc/testsuite/gnat.dg/opt46.ads b/gcc/testsuite/gnat.dg/opt46.ads new file mode 100644 index 00000000000..5a5175d0936 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt46.ads @@ -0,0 +1,16 @@ +package Opt46 is + + type Session_Type is limited private; + + procedure Close (Session : Session_Type); + +private + + type Session_Data; + type Session_Data_Access is access Session_Data; + + type Session_Type is record + Data : Session_Data_Access; + end record; + +end Opt46; diff --git a/gcc/testsuite/gnat.dg/opt46_pkg.adb b/gcc/testsuite/gnat.dg/opt46_pkg.adb new file mode 100644 index 00000000000..26f67cc90ec --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt46_pkg.adb @@ -0,0 +1,8 @@ +package body Opt46_Pkg is + + function Last (T : Instance) return Table_Index_Type is + begin + return Table_Index_Type (T.P.Last_Val); + end Last; + +end Opt46_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt46_pkg.ads b/gcc/testsuite/gnat.dg/opt46_pkg.ads new file mode 100644 index 00000000000..1309315378f --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt46_pkg.ads @@ -0,0 +1,31 @@ +generic + type Table_Component_Type is private; + type Table_Index_Type is range <>; + + Table_Low_Bound : Table_Index_Type; + +package Opt46_Pkg is + + type Table_Type is + array (Table_Index_Type range <>) of Table_Component_Type; + subtype Big_Table_Type is + Table_Type (Table_Low_Bound .. Table_Index_Type'Last); + + type Table_Ptr is access all Big_Table_Type; + + type Table_Private is private; + + type Instance is record + Table : aliased Table_Ptr := null; + P : Table_Private; + end record; + + function Last (T : Instance) return Table_Index_Type; + +private + + type Table_Private is record + Last_Val : Integer; + end record; + +end Opt46_Pkg; diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 14ed52a007a..dc3b4191bb5 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -4236,10 +4236,9 @@ cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb, if (current_loops && e->dest == e->dest->loop_father->header) { - e->dest->loop_father->header = NULL; - e->dest->loop_father->latch = NULL; + mark_loop_for_removal (e->dest->loop_father); new_bb->loop_father->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES); + loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES); } redirect_eh_edge_1 (e, new_bb, change_region); redirect_edge_succ (e, new_bb); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index f757bdfaa2f..288645b5904 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2336,11 +2336,8 @@ copy_loops (copy_body_data *id, /* Assign the new loop its header and latch and associate those with the new loop. */ - if (src_loop->header != NULL) - { - dest_loop->header = (basic_block)src_loop->header->aux; - dest_loop->header->loop_father = dest_loop; - } + dest_loop->header = (basic_block)src_loop->header->aux; + dest_loop->header->loop_father = dest_loop; if (src_loop->latch != NULL) { dest_loop->latch = (basic_block)src_loop->latch->aux; @@ -5505,6 +5502,11 @@ tree_function_versioning (tree old_decl, tree new_decl, delete_unreachable_blocks_update_callgraph (&id); if (id.dst_node->definition) cgraph_rebuild_references (); + if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) + { + calculate_dominance_info (CDI_DOMINATORS); + fix_loop_structure (NULL); + } update_ssa (TODO_update_ssa); /* After partial cloning we need to rescale frequencies, so they are diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index d3fe4afab71..cad91ef667c 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "params.h" #include "tree-ssa-threadedge.h" +#include "tree-ssa-loop.h" /* To avoid code explosion due to jump threading, we limit the number of statements we are going to copy. This variable @@ -947,7 +948,8 @@ static int max_threaded_paths; static void fsm_find_control_statement_thread_paths (tree expr, pointer_set_t *visited_phis, - vec<basic_block, va_gc> *&path) + vec<basic_block, va_gc> *&path, + bool seen_loop_phi) { tree var = SSA_NAME_VAR (expr); gimple def_stmt = SSA_NAME_DEF_STMT (expr); @@ -970,6 +972,14 @@ fsm_find_control_statement_thread_paths (tree expr, int next_path_length = 0; basic_block last_bb_in_path = path->last (); + if (loop_containing_stmt (def_stmt)->header == gimple_bb (def_stmt)) + { + /* Do not walk through more than one loop PHI node. */ + if (seen_loop_phi) + return; + seen_loop_phi = true; + } + /* Following the chain of SSA_NAME definitions, we jumped from a definition in LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */ @@ -1030,7 +1040,9 @@ fsm_find_control_statement_thread_paths (tree expr, { vec_safe_push (path, bbi); /* Recursively follow SSA_NAMEs looking for a constant definition. */ - fsm_find_control_statement_thread_paths (arg, visited_phis, path); + fsm_find_control_statement_thread_paths (arg, visited_phis, path, + seen_loop_phi); + path->pop (); continue; } @@ -1297,7 +1309,8 @@ thread_through_normal_block (edge e, pointer_set_t *visited_phis = pointer_set_create (); max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS); - fsm_find_control_statement_thread_paths (cond, visited_phis, bb_path); + fsm_find_control_statement_thread_paths (cond, visited_phis, bb_path, + false); pointer_set_destroy (visited_phis); vec_free (bb_path); diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index d1b289ffa68..6ae071ea083 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -700,6 +700,10 @@ ssa_redirect_edges (struct redirection_data **slot, if ((*path)[1]->type != EDGE_COPY_SRC_JOINER_BLOCK) EDGE_SUCC (rd->dup_blocks[0], 0)->count += e->count; + /* If we redirect a loop latch edge cancel its loop. */ + if (e->src == e->src->loop_father->latch) + mark_loop_for_removal (e->src->loop_father); + /* Redirect the incoming edge (possibly to the joiner block) to the appropriate duplicate block. */ e2 = redirect_edge_and_branch (e, rd->dup_blocks[0]); @@ -780,7 +784,6 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners) edge e, e2; edge_iterator ei; ssa_local_info_t local_info; - struct loop *loop = bb->loop_father; /* To avoid scanning a linear array for the element we need we instead use a hash table. For normal code there should be no noticeable @@ -788,32 +791,6 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners) incoming and outgoing edges such linear searches can get expensive. */ redirection_data.create (EDGE_COUNT (bb->succs)); - /* If we thread the latch of the loop to its exit, the loop ceases to - exist. Make sure we do not restrict ourselves in order to preserve - this loop. */ - if (loop->header == bb) - { - e = loop_latch_edge (loop); - vec<jump_thread_edge *> *path = THREAD_PATH (e); - - if (path - && (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && joiners) - || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && !joiners))) - { - for (unsigned int i = 1; i < path->length (); i++) - { - edge e2 = (*path)[i]->e; - - if (loop_exit_edge_p (loop, e2)) - { - loop->header = NULL; - loop->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP); - } - } - } - } - /* Record each unique threaded destination into a hash table for efficient lookups. */ FOR_EACH_EDGE (e, ei, bb->preds) @@ -1257,9 +1234,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers) { /* If the loop ceased to exist, mark it as such, and thread through its original header. */ - loop->header = NULL; - loop->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP); + mark_loop_for_removal (loop); return thread_block (header, false); } @@ -1669,7 +1644,7 @@ duplicate_seme_region (edge entry, edge exit, basic_block *region_copy) { unsigned i; - bool free_region_copy = false, copying_header = false; + bool free_region_copy = false; struct loop *loop = entry->dest->loop_father; edge exit_copy; edge redirected; @@ -1693,10 +1668,7 @@ duplicate_seme_region (edge entry, edge exit, initialize_original_copy_tables (); - if (copying_header) - set_loop_copy (loop, loop_outer (loop)); - else - set_loop_copy (loop, loop); + set_loop_copy (loop, loop); if (!region_copy) { @@ -1758,6 +1730,8 @@ duplicate_seme_region (edge entry, edge exit, } /* Redirect the entry and add the phi node arguments. */ + if (entry->dest == loop->header) + mark_loop_for_removal (loop); redirected = redirect_edge_and_branch (entry, get_bb_copy (entry->dest)); gcc_assert (redirected != NULL); flush_pending_stmts (entry); @@ -1937,16 +1911,8 @@ thread_through_all_blocks (bool may_peel_loop_headers) /* Our path is still valid, thread it. */ if (e->aux) { - struct loop *loop = (*path)[0]->e->dest->loop_father; - if (thread_block ((*path)[0]->e->dest, false)) - { - /* This jump thread likely totally scrambled this loop. - So arrange for it to be fixed up. */ - loop->header = NULL; - loop->latch = NULL; - e->aux = NULL; - } + e->aux = NULL; else { delete_jump_thread_path (path); |