tree-vrp.c (find_conditional_asserts): Update comments.
2006-02-07 Jeff Law <law@redhat.com> * tree-vrp.c (find_conditional_asserts): Update comments. (simplify_stmt_for_jump_threading): New. (identify_jump_threads, finalize_jump_threads): New. (vrp_finalize): Call identify_jump_threads. (execute_vrp): Call finalize_jump_threads. * tree-ssa-dom.c (struct opt_stats_d): Remove num_iterations field. (vrp_element, vrp_data, vrp_element_p): Remove. (vrp_hash_elt, vrp_variables_stack): Remove. (vrp_hash, vrp_eq, record_range): Remove. (simplify_cond_and_lookup_avail_expr): Remove. (extract_range_from_cond): Remove. (thread_across_edge): Relocated into tree-ssa-threadedge.c. (simplify_stmt_for_jump_threading): New. (dom_thread_across_edge): New wrapper. (tree_ssa_dominator_optimize): No longer initialize or finalize any of the VRP datastructures. Remove iteration step and simplify as a result of removal of iteration step. (pass_dominator): Perform a cfg cleanup after DOM. (dom_opt_finalize_block): Use the new common routines for threading jumps. Simplify stack management slightly. No longer need to unwind VRP state. (record_equivalences_from_incoming_edge): No longer record VRP information. (eliminate_redundant_computations): No longer call simplify_cond_and_lookup_avail_expr. * tree-flow.h (potentially_threadable_block): Prototype. (thread_across_edge): Likewise. * Makefile.in (OBJS-common): Add tree-ssa-threadedge.o (tree-ssa-threadedge.o): Add dependencies. * tree-ssa-threadedge.c: New file. * passes.c (init_optimization_passes): Merge PHIs before calling VRP. Run VRP again late in the SSA optimization pipeline. * gcc.dg/tree-ssa/vrp01.c: Update dumpfile names now that we have multiple VRP passes. * gcc.dg/tree-ssa/vrp09.c: Likewise. * gcc.dg/tree-ssa/vrp18.c: Likewise. * gcc.dg/tree-ssa/pr21582.c: Likewise. * gcc.dg/tree-ssa/pr20657.c: Likewise. * gcc.dg/tree-ssa/pr21001.c: Likewise. * gcc.dg/tree-ssa/vrp02.c: Likewise * gcc.dg/tree-ssa/vrp11.c: Likewise * gcc.dg/tree-ssa/pr14341.c: Likewise * gcc.dg/tree-ssa/vrp19.c: Likewise * gcc.dg/tree-ssa/vrp20.c: Likewise * gcc.dg/tree-ssa/vrp03.c: Likewise * gcc.dg/tree-ssa/pr21086.c: Likewise * gcc.dg/tree-ssa/pr21959.c: Likewise * gcc.dg/tree-ssa/vrp21.c: Likewise * gcc.dg/tree-ssa/vrp04.c: Likewise * gcc.dg/tree-ssa/pr25485.c: Likewise * gcc.dg/tree-ssa/pr22026.c: Likewise * gcc.dg/tree-ssa/vrp22.c: Likewise * gcc.dg/tree-ssa/vrp05.c: Likewise * gcc.dg/tree-ssa/20030807-10.c: Likewise * gcc.dg/tree-ssa/pr20701.c: Likewise * gcc.dg/tree-ssa/vrp23.c: Likewise * gcc.dg/tree-ssa/vrp06.c: Likewise * gcc.dg/tree-ssa/pr22117.c: Likewise * gcc.dg/tree-ssa/pr20702.c: Likewise * gcc.dg/tree-ssa/vrp15.c: Likewise * gcc.dg/tree-ssa/pr21090.c: Likewise * gcc.dg/tree-ssa/pr21294.c: Likewise * gcc.dg/tree-ssa/vrp24.c: Likewise * gcc.dg/tree-ssa/vrp07.c: Likewise * gcc.dg/tree-ssa/pr21563.c: Likewise * gcc.dg/tree-ssa/pr25382.c: Likewise * gcc.dg/tree-ssa/vrp16.c: Likewise * gcc.dg/tree-ssa/vrp25.c: Likewise * gcc.dg/tree-ssa/vrp08.c: Likewise * gcc.dg/tree-ssa/20030807-6.c: Likewise * gcc.dg/tree-ssa/vrp17.c: Likewise * gcc.dg/tree-ssa/pr21458.c: Likewise * g++.dg/tree-ssa/pr18178.C: Likewise From-SVN: r110705
This commit is contained in:
parent
e45dcf9c6e
commit
2090d6a0a8
48 changed files with 1026 additions and 1090 deletions
|
@ -1,3 +1,38 @@
|
|||
2006-02-07 Jeff Law <law@redhat.com>
|
||||
|
||||
* tree-vrp.c (find_conditional_asserts): Update comments.
|
||||
(simplify_stmt_for_jump_threading): New.
|
||||
(identify_jump_threads, finalize_jump_threads): New.
|
||||
(vrp_finalize): Call identify_jump_threads.
|
||||
(execute_vrp): Call finalize_jump_threads.
|
||||
* tree-ssa-dom.c (struct opt_stats_d): Remove num_iterations field.
|
||||
(vrp_element, vrp_data, vrp_element_p): Remove.
|
||||
(vrp_hash_elt, vrp_variables_stack): Remove.
|
||||
(vrp_hash, vrp_eq, record_range): Remove.
|
||||
(simplify_cond_and_lookup_avail_expr): Remove.
|
||||
(extract_range_from_cond): Remove.
|
||||
(thread_across_edge): Relocated into tree-ssa-threadedge.c.
|
||||
(simplify_stmt_for_jump_threading): New.
|
||||
(dom_thread_across_edge): New wrapper.
|
||||
(tree_ssa_dominator_optimize): No longer initialize or
|
||||
finalize any of the VRP datastructures. Remove iteration
|
||||
step and simplify as a result of removal of iteration step.
|
||||
(pass_dominator): Perform a cfg cleanup after DOM.
|
||||
(dom_opt_finalize_block): Use the new common routines
|
||||
for threading jumps. Simplify stack management slightly.
|
||||
No longer need to unwind VRP state.
|
||||
(record_equivalences_from_incoming_edge): No longer record
|
||||
VRP information.
|
||||
(eliminate_redundant_computations): No longer call
|
||||
simplify_cond_and_lookup_avail_expr.
|
||||
* tree-flow.h (potentially_threadable_block): Prototype.
|
||||
(thread_across_edge): Likewise.
|
||||
* Makefile.in (OBJS-common): Add tree-ssa-threadedge.o
|
||||
(tree-ssa-threadedge.o): Add dependencies.
|
||||
* tree-ssa-threadedge.c: New file.
|
||||
* passes.c (init_optimization_passes): Merge PHIs before
|
||||
calling VRP. Run VRP again late in the SSA optimization pipeline.
|
||||
|
||||
2006-02-07 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR c++/26140
|
||||
|
|
|
@ -961,7 +961,7 @@ OBJS-common = \
|
|||
tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o \
|
||||
omp-low.o tree-phinodes.o tree-ssanames.o tree-sra.o tree-complex.o \
|
||||
tree-vect-generic.o tree-ssa-loop.o tree-ssa-loop-niter.o \
|
||||
tree-ssa-loop-manip.o tree-ssa-threadupdate.o \
|
||||
tree-ssa-loop-manip.o tree-ssa-threadupdate.o tree-ssa-threadedge.o \
|
||||
tree-vectorizer.o tree-vect-analyze.o tree-vect-transform.o \
|
||||
tree-vect-patterns.o \
|
||||
tree-ssa-loop-ivcanon.o tree-ssa-propagate.o tree-ssa-address.o \
|
||||
|
@ -1860,6 +1860,10 @@ tree-ssa-uncprop.o : tree-ssa-uncprop.c $(TREE_FLOW_H) $(CONFIG_H) \
|
|||
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
|
||||
$(TREE_DUMP_H) $(BASIC_BLOCK_H) domwalk.h real.h tree-pass.h $(FLAGS_H) \
|
||||
langhooks.h tree-ssa-propagate.h
|
||||
tree-ssa-threadedge.o : tree-ssa-threadedge.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
|
||||
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
|
||||
$(BASIC_BLOCK_H) $(FLAGS_H) tree-pass.h $(CFGLOOP_H)
|
||||
tree-ssa-threadupdate.o : tree-ssa-threadupdate.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
|
||||
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Top level of GCC compilers (cc1, cc1plus, etc.)
|
||||
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
|
@ -507,9 +507,9 @@ init_optimization_passes (void)
|
|||
NEXT_PASS (pass_dce);
|
||||
NEXT_PASS (pass_forwprop);
|
||||
NEXT_PASS (pass_copy_prop);
|
||||
NEXT_PASS (pass_merge_phi);
|
||||
NEXT_PASS (pass_vrp);
|
||||
NEXT_PASS (pass_dce);
|
||||
NEXT_PASS (pass_merge_phi);
|
||||
NEXT_PASS (pass_dominator);
|
||||
|
||||
/* The only copy propagation opportunities left after DOM
|
||||
|
@ -560,6 +560,7 @@ init_optimization_passes (void)
|
|||
NEXT_PASS (pass_tree_loop);
|
||||
NEXT_PASS (pass_cse_reciprocals);
|
||||
NEXT_PASS (pass_reassoc);
|
||||
NEXT_PASS (pass_vrp);
|
||||
NEXT_PASS (pass_dominator);
|
||||
|
||||
/* The only copy propagation opportunities left after DOM
|
||||
|
|
|
@ -1,3 +1,47 @@
|
|||
2006-02-07 Jeff Law <law@redhat.com>
|
||||
|
||||
* gcc.dg/tree-ssa/vrp01.c: Update dumpfile names now that we have
|
||||
multiple VRP passes.
|
||||
* gcc.dg/tree-ssa/vrp09.c: Likewise.
|
||||
* gcc.dg/tree-ssa/vrp18.c: Likewise.
|
||||
* gcc.dg/tree-ssa/pr21582.c: Likewise.
|
||||
* gcc.dg/tree-ssa/pr20657.c: Likewise.
|
||||
* gcc.dg/tree-ssa/pr21001.c: Likewise.
|
||||
* gcc.dg/tree-ssa/vrp02.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp11.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr14341.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp19.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp20.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp03.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr21086.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr21959.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp21.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp04.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr25485.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr22026.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp22.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp05.c: Likewise
|
||||
* gcc.dg/tree-ssa/20030807-10.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr20701.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp23.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp06.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr22117.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr20702.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp15.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr21090.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr21294.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp24.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp07.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr21563.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr25382.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp16.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp25.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp08.c: Likewise
|
||||
* gcc.dg/tree-ssa/20030807-6.c: Likewise
|
||||
* gcc.dg/tree-ssa/vrp17.c: Likewise
|
||||
* gcc.dg/tree-ssa/pr21458.c: Likewise
|
||||
* g++.dg/tree-ssa/pr18178.C: Likewise
|
||||
|
||||
2006-02-07 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR c++/26140
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
// Define this to see it work.
|
||||
// #define WORK_WORK_WORK
|
||||
|
@ -43,5 +43,5 @@ void doit (array *a)
|
|||
|
||||
/* VRP should remove all but 1 if() in the loop. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "if " 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "if " 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
|
||||
extern const unsigned char mode_size[];
|
||||
|
@ -18,9 +18,9 @@ subreg_highpart_offset (outermode, innermode)
|
|||
}
|
||||
|
||||
/* There should be one mask with the value 3. */
|
||||
/* { dg-final { scan-tree-dump-times " \& 3" 1 "vrp"} } */
|
||||
/* { dg-final { scan-tree-dump-times " \& 3" 1 "vrp1"} } */
|
||||
|
||||
/* There should be one right shift by 2 places. */
|
||||
/* { dg-final { scan-tree-dump-times " >> 2" 1 "vrp"} } */
|
||||
/* { dg-final { scan-tree-dump-times " >> 2" 1 "vrp1"} } */
|
||||
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
|
||||
void
|
||||
|
@ -39,5 +39,5 @@ foo4 (distance, i, j)
|
|||
}
|
||||
|
||||
/* There should be no ABS_EXPR. */
|
||||
/* { dg-final { scan-tree-dump-times "ABS_EXPR " 0 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "ABS_EXPR " 0 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
void fn_call (int);
|
||||
int h(int, int);
|
||||
|
@ -12,5 +12,5 @@ void t()
|
|||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "fn_call \\(1\\)" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "fn_call \\(1\\)" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
statement, which was needed to eliminate the second "if" statement. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
|
||||
|
||||
int
|
||||
foo (int a)
|
||||
|
@ -14,5 +14,5 @@ foo (int a)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
|
@ -26,5 +26,5 @@ can_combine_p (rtx insn, rtx elt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 0" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
immediate successors of the basic block. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
|
||||
|
||||
extern void bar (int);
|
||||
|
||||
|
@ -25,5 +25,5 @@ foo (int *p, int b)
|
|||
return a;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
range infomation out of the conditional. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
|
||||
|
||||
int
|
||||
foo (int a)
|
||||
|
@ -17,5 +17,5 @@ foo (int a)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
int
|
||||
foo (int *p)
|
||||
|
@ -15,5 +15,5 @@ foo (int *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate " 2 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate " 2 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
int g, h;
|
||||
|
||||
|
@ -19,5 +19,5 @@ foo (int a)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
allows us to eliminate the second "if" statement. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
|
||||
|
||||
struct f {
|
||||
int i;
|
||||
|
@ -19,5 +19,5 @@ foo (struct f *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
extern void g (void);
|
||||
extern void bar (int);
|
||||
|
@ -16,5 +16,5 @@ foo (int a)
|
|||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Make sure VRP folds the second "if" statement. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */
|
||||
|
||||
int
|
||||
foo (int a)
|
||||
|
@ -13,5 +13,5 @@ foo (int a)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do link } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
static inline void do_thing(char *s, int *p, char *q)
|
||||
{
|
||||
|
@ -24,5 +24,5 @@ main()
|
|||
do_other_thing ("xxx", &i, "yyy");
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*" 0 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*" 0 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
unsigned char c[0xFF];
|
||||
void f(void)
|
||||
|
@ -16,5 +16,5 @@ void f(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
same applies to subtraction and unsigned multiplication. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
int
|
||||
plus (int x, int y)
|
||||
|
@ -45,5 +45,5 @@ mult (unsigned x, unsigned y)
|
|||
}
|
||||
|
||||
/* None of the predicates can be folded in these functions. */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 0 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 0 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
known to be zero after entering the first two "if" statements. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
void
|
||||
foo (int *p, int q)
|
||||
|
@ -19,5 +19,5 @@ foo (int *p, int q)
|
|||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate r_.* != 0B to 0" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate r_.* != 0B to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Check that VRP now gets ranges from BIT_AND_EXPRs. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
int
|
||||
foo (int a)
|
||||
|
@ -15,5 +15,5 @@ foo (int a)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* PR tree-optimization/25485
|
||||
VRP did not fold TRUTH_AND_EXPR. Make sure it does now. */
|
||||
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
int
|
||||
foo (int a, int b)
|
||||
|
@ -13,5 +13,5 @@ foo (int a, int b)
|
|||
return 31;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "if" 1 "vrp"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "if" 1 "vrp1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
foo (int *p, int i)
|
||||
{
|
||||
|
@ -24,5 +24,5 @@ foo (int *p, int i)
|
|||
return i;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
struct A
|
||||
{
|
||||
|
@ -20,5 +20,5 @@ foo (struct A *p, struct A *q)
|
|||
return x + p->b;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
struct A
|
||||
{
|
||||
|
@ -30,6 +30,6 @@ foo (struct A *p, struct A *q)
|
|||
return q->a;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate q_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate r_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate q_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate r_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
foo (int a, int b)
|
||||
{
|
||||
|
@ -9,5 +9,5 @@ foo (int a, int b)
|
|||
return a + b;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate a_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate a_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
foo (int k, int j)
|
||||
{
|
||||
|
@ -16,5 +16,5 @@ foo (int k, int j)
|
|||
return j;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
foo (int i, int j, int a)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ foo (int i, int j, int a)
|
|||
return i + a + j;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
foo (int i, int *p)
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ foo (int i, int *p)
|
|||
return i;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 0" 1 "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "PREDICATE: p_\[0-9\] ne_expr 0B" 2 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "PREDICATE: p_\[0-9\] ne_expr 0B" 2 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details" } */
|
||||
|
||||
/* Compile with -fno-tree-fre -O2 to prevent CSEing *p. */
|
||||
foo (int a, int *p)
|
||||
|
@ -18,6 +18,6 @@ foo (int a, int *p)
|
|||
return a;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "PREDICATE: p_. ne_expr 0" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "PREDICATE: p_. ne_expr 0" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
foo (int *p)
|
||||
{
|
||||
|
@ -27,5 +27,5 @@ L78:
|
|||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.. != 0B to 1" 2 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate p_.. != 0B to 1" 2 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
foo (int k, int j, int z)
|
||||
{
|
||||
|
@ -16,5 +16,5 @@ foo (int k, int j, int z)
|
|||
return j;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
|
||||
extern void abort (void) __attribute__ ((__noreturn__));
|
||||
|
@ -29,6 +29,6 @@ blah (tree t)
|
|||
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "tree_code_length.42." 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "tree_code_length.42." 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
|
||||
extern void abort (void) __attribute__ ((__noreturn__));
|
||||
|
@ -18,6 +18,6 @@ nonlocal_mentioned_p (rtx x)
|
|||
abort ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate .*to 0" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate .*to 0" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
extern void abort (void) __attribute__ ((__noreturn__));
|
||||
union tree_node;
|
||||
|
@ -27,6 +27,6 @@ gimplify_for_stmt (tree stmt)
|
|||
abort ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1" } */
|
||||
|
||||
static int blocksize = 4096;
|
||||
|
||||
|
@ -30,5 +30,5 @@ void foo (void)
|
|||
eof_reached = 1;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp" } */
|
||||
/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp1" } */
|
||||
|
||||
#include <limits.h>
|
||||
extern void abort ();
|
||||
|
@ -22,6 +22,6 @@ int g (int b) {
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump "Folding predicate a_. < 0 to 0" "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump "Folding predicate b_. >= 0 to 1" "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump "Folding predicate a_. < 0 to 0" "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump "Folding predicate b_. >= 0 to 1" "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp" } */
|
||||
/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp1" } */
|
||||
|
||||
extern void abort ();
|
||||
extern void exit (int);
|
||||
|
@ -23,6 +23,6 @@ int g (int b) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Folding predicate a_. == 0 to 0" "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump "Folding predicate b_. != 0 to 1" "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump "Folding predicate a_. == 0 to 0" "vrp1" } } */
|
||||
/* { dg-final { scan-tree-dump "Folding predicate b_. != 0 to 1" "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp1" } */
|
||||
|
||||
extern void link_error ();
|
||||
|
||||
|
@ -22,5 +22,5 @@ void test02(unsigned int a, unsigned int b)
|
|||
link_error ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp" } */
|
||||
/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp1" } */
|
||||
|
||||
extern void link_error ();
|
||||
|
||||
|
@ -12,5 +12,5 @@ void test02(unsigned int a, unsigned int b)
|
|||
link_error ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
blah (int code1, int code2)
|
||||
{
|
||||
|
@ -40,6 +40,6 @@ L8:
|
|||
/* The n_sets > 0 test can be simplified into n_sets == 1 since the
|
||||
only way to reach the test is when n_sets <= 1, and the only value
|
||||
which satisfies both conditions is n_sets == 1. */
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
|
||||
struct rtx_def;
|
||||
|
@ -84,6 +84,6 @@ L7:
|
|||
/* The n_sets > 0 test can be simplified into n_sets == 1 since the
|
||||
only way to reach the test is when n_sets <= 1, and the only value
|
||||
which satisfies both conditions is n_sets == 1. */
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp-details" } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
extern void abort ();
|
||||
int tree_code_length[100];
|
||||
|
@ -47,6 +47,6 @@ L9:
|
|||
/* The second test of (code1 != 53) and the test (D18670 <= 2) are
|
||||
both totally subsumed by earlier tests and thus should be folded
|
||||
away using VRP. */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 2 "vrp" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Folding predicate" 2 "vrp1" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vrp1" } } */
|
||||
|
||||
|
|
|
@ -749,6 +749,11 @@ tree expand_simple_operations (tree);
|
|||
void substitute_in_loop_info (struct loop *, tree, tree);
|
||||
edge single_dom_exit (struct loop *);
|
||||
|
||||
/* In tree-ssa-threadedge.c */
|
||||
extern bool potentially_threadable_block (basic_block);
|
||||
extern void thread_across_edge (tree, edge, bool,
|
||||
VEC(tree, heap) **, tree (*) (tree));
|
||||
|
||||
/* In tree-ssa-loop-im.c */
|
||||
/* The possibilities of statement movement. */
|
||||
|
||||
|
|
1047
gcc/tree-ssa-dom.c
1047
gcc/tree-ssa-dom.c
File diff suppressed because it is too large
Load diff
537
gcc/tree-ssa-threadedge.c
Normal file
537
gcc/tree-ssa-threadedge.c
Normal file
|
@ -0,0 +1,537 @@
|
|||
/* SSA Jump Threading
|
||||
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
|
||||
Contributed by Jeff Law <law@redhat.com>
|
||||
|
||||
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 2, 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 COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "flags.h"
|
||||
#include "rtl.h"
|
||||
#include "tm_p.h"
|
||||
#include "ggc.h"
|
||||
#include "basic-block.h"
|
||||
#include "cfgloop.h"
|
||||
#include "output.h"
|
||||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "diagnostic.h"
|
||||
#include "timevar.h"
|
||||
#include "tree-dump.h"
|
||||
#include "tree-flow.h"
|
||||
#include "domwalk.h"
|
||||
#include "real.h"
|
||||
#include "tree-pass.h"
|
||||
#include "tree-ssa-propagate.h"
|
||||
#include "langhooks.h"
|
||||
#include "params.h"
|
||||
|
||||
/* To avoid code explosion due to jump threading, we limit the
|
||||
number of statements we are going to copy. This variable
|
||||
holds the number of statements currently seen that we'll have
|
||||
to copy as part of the jump threading process. */
|
||||
static int stmt_count;
|
||||
|
||||
/* Return TRUE if we may be able to thread an incoming edge into
|
||||
BB to an outgoing edge from BB. Return FALSE otherwise. */
|
||||
|
||||
bool
|
||||
potentially_threadable_block (basic_block bb)
|
||||
{
|
||||
block_stmt_iterator bsi;
|
||||
|
||||
/* If BB has a single successor or a single predecessor, then
|
||||
there is no threading opportunity. */
|
||||
if (single_succ_p (bb) || single_pred_p (bb))
|
||||
return false;
|
||||
|
||||
/* If BB does not end with a conditional, switch or computed goto,
|
||||
then there is no threading opportunity. */
|
||||
bsi = bsi_last (bb);
|
||||
if (bsi_end_p (bsi)
|
||||
|| ! bsi_stmt (bsi)
|
||||
|| (TREE_CODE (bsi_stmt (bsi)) != COND_EXPR
|
||||
&& TREE_CODE (bsi_stmt (bsi)) != GOTO_EXPR
|
||||
&& TREE_CODE (bsi_stmt (bsi)) != SWITCH_EXPR))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return the LHS of any ASSERT_EXPR where OP appears as the first
|
||||
argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
|
||||
BB. If no such ASSERT_EXPR is found, return OP. */
|
||||
|
||||
static tree
|
||||
lhs_of_dominating_assert (tree op, basic_block bb, tree stmt)
|
||||
{
|
||||
imm_use_iterator imm_iter;
|
||||
use_operand_p imm_use;
|
||||
|
||||
FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, op)
|
||||
{
|
||||
tree use_stmt = USE_STMT (imm_use);
|
||||
|
||||
if (use_stmt != stmt
|
||||
&& TREE_CODE (use_stmt) == MODIFY_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (use_stmt, 1)) == ASSERT_EXPR
|
||||
&& TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 0) == op
|
||||
&& dominated_by_p (CDI_DOMINATORS, bb, bb_for_stmt (use_stmt)))
|
||||
op = TREE_OPERAND (use_stmt, 0);
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
/* We record temporary equivalences created by PHI nodes or
|
||||
statements within the target block. Doing so allows us to
|
||||
identify more jump threading opportunities, even in blocks
|
||||
with side effects.
|
||||
|
||||
We keep track of those temporary equivalences in a stack
|
||||
structure so that we can unwind them when we're done processing
|
||||
a particular edge. This routine handles unwinding the data
|
||||
structures. */
|
||||
|
||||
static void
|
||||
remove_temporary_equivalences (VEC(tree, heap) **stack)
|
||||
{
|
||||
while (VEC_length (tree, *stack) > 0)
|
||||
{
|
||||
tree prev_value, dest;
|
||||
|
||||
dest = VEC_pop (tree, *stack);
|
||||
|
||||
/* A NULL value indicates we should stop unwinding, oherwise
|
||||
pop off the next entry as they're recorded in pairs. */
|
||||
if (dest == NULL)
|
||||
break;
|
||||
|
||||
prev_value = VEC_pop (tree, *stack);
|
||||
SSA_NAME_VALUE (dest) = prev_value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record a temporary equivalence, saving enough information so that
|
||||
we can restore the state of recorded equivalences when we're
|
||||
done processing the current edge. */
|
||||
|
||||
static void
|
||||
record_temporary_equivalence (tree x, tree y, VEC(tree, heap) **stack)
|
||||
{
|
||||
tree prev_x = SSA_NAME_VALUE (x);
|
||||
|
||||
if (TREE_CODE (y) == SSA_NAME)
|
||||
{
|
||||
tree tmp = SSA_NAME_VALUE (y);
|
||||
y = tmp ? tmp : y;
|
||||
}
|
||||
|
||||
SSA_NAME_VALUE (x) = y;
|
||||
VEC_reserve (tree, heap, *stack, 2);
|
||||
VEC_quick_push (tree, *stack, prev_x);
|
||||
VEC_quick_push (tree, *stack, x);
|
||||
}
|
||||
|
||||
/* Record temporary equivalences created by PHIs at the target of the
|
||||
edge E. Record unwind information for the equivalences onto STACK.
|
||||
|
||||
If a PHI which prevents threading is encountered, then return FALSE
|
||||
indicating we should not thread this edge, else return TRUE. */
|
||||
|
||||
static bool
|
||||
record_temporary_equivalences_from_phis (edge e, VEC(tree, heap) **stack)
|
||||
{
|
||||
tree phi;
|
||||
|
||||
/* Each PHI creates a temporary equivalence, record them.
|
||||
These are context sensitive equivalences and will be removed
|
||||
later. */
|
||||
for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
|
||||
{
|
||||
tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
|
||||
tree dst = PHI_RESULT (phi);
|
||||
|
||||
/* If the desired argument is not the same as this PHI's result
|
||||
and it is set by a PHI in E->dest, then we can not thread
|
||||
through E->dest. */
|
||||
if (src != dst
|
||||
&& TREE_CODE (src) == SSA_NAME
|
||||
&& TREE_CODE (SSA_NAME_DEF_STMT (src)) == PHI_NODE
|
||||
&& bb_for_stmt (SSA_NAME_DEF_STMT (src)) == e->dest)
|
||||
return false;
|
||||
|
||||
/* We consider any non-virtual PHI as a statement since it
|
||||
count result in a constant assignment or copy operation. */
|
||||
if (is_gimple_reg (dst))
|
||||
stmt_count++;
|
||||
|
||||
record_temporary_equivalence (dst, src, stack);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Try to simplify each statement in E->dest, ultimately leading to
|
||||
a simplification of the COND_EXPR at the end of E->dest.
|
||||
|
||||
Record unwind information for temporary equivalences onto STACK.
|
||||
|
||||
Use SIMPLIFY (a pointer to a callback function) to further simplify
|
||||
statements using pass specific information.
|
||||
|
||||
We might consider marking just those statements which ultimately
|
||||
feed the COND_EXPR. It's not clear if the overhead of bookkeeping
|
||||
would be recovered by trying to simplify fewer statements.
|
||||
|
||||
If we are able to simplify a statement into the form
|
||||
SSA_NAME = (SSA_NAME | gimple invariant), then we can record
|
||||
a context sensitive equivalency which may help us simplify
|
||||
later statements in E->dest. */
|
||||
|
||||
static tree
|
||||
record_temporary_equivalences_from_stmts_at_dest (edge e,
|
||||
VEC(tree, heap) **stack,
|
||||
tree (*simplify) (tree))
|
||||
{
|
||||
block_stmt_iterator bsi;
|
||||
tree stmt = NULL;
|
||||
int max_stmt_count;
|
||||
|
||||
max_stmt_count = PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS);
|
||||
|
||||
/* Walk through each statement in the block recording equivalences
|
||||
we discover. Note any equivalences we discover are context
|
||||
sensitive (ie, are dependent on traversing E) and must be unwound
|
||||
when we're finished processing E. */
|
||||
for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
tree cached_lhs = NULL;
|
||||
|
||||
stmt = bsi_stmt (bsi);
|
||||
|
||||
/* Ignore empty statements and labels. */
|
||||
if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
|
||||
continue;
|
||||
|
||||
/* Safely handle threading across loop backedges. Only allowing
|
||||
a conditional at the target of the backedge is over conservative,
|
||||
but still allows us to capture the majority of the cases where
|
||||
we can thread across a loop backedge. */
|
||||
if ((e->flags & EDGE_DFS_BACK) != 0
|
||||
&& TREE_CODE (stmt) != COND_EXPR
|
||||
&& TREE_CODE (stmt) != SWITCH_EXPR)
|
||||
return NULL;
|
||||
|
||||
/* If the statement has volatile operands, then we assume we
|
||||
can not thread through this block. This is overly
|
||||
conservative in some ways. */
|
||||
if (TREE_CODE (stmt) == ASM_EXPR && ASM_VOLATILE_P (stmt))
|
||||
return NULL;
|
||||
|
||||
/* If duplicating this block is going to cause too much code
|
||||
expansion, then do not thread through this block. */
|
||||
stmt_count++;
|
||||
if (stmt_count > max_stmt_count)
|
||||
return NULL;
|
||||
|
||||
/* If this is not a MODIFY_EXPR which sets an SSA_NAME to a new
|
||||
value, then do not try to simplify this statement as it will
|
||||
not simplify in any way that is helpful for jump threading. */
|
||||
if (TREE_CODE (stmt) != MODIFY_EXPR
|
||||
|| TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
|
||||
continue;
|
||||
|
||||
/* At this point we have a statement which assigns an RHS to an
|
||||
SSA_VAR on the LHS. We want to try and simplify this statement
|
||||
to expose more context sensitive equivalences which in turn may
|
||||
allow us to simplify the condition at the end of the loop.
|
||||
|
||||
Handle simple copy operations as well as implied copies from
|
||||
ASSERT_EXPRs. */
|
||||
if (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME)
|
||||
cached_lhs = TREE_OPERAND (stmt, 1);
|
||||
else if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ASSERT_EXPR)
|
||||
cached_lhs = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
|
||||
else
|
||||
{
|
||||
/* A statement that is not a trivial copy or ASSERT_EXPR.
|
||||
We're going to temporarily copy propagate the operands
|
||||
and see if that allows us to simplify this statement. */
|
||||
tree *copy, pre_fold_expr;
|
||||
ssa_op_iter iter;
|
||||
use_operand_p use_p;
|
||||
unsigned int num, i = 0;
|
||||
|
||||
num = NUM_SSA_OPERANDS (stmt, (SSA_OP_USE | SSA_OP_VUSE));
|
||||
copy = XCNEWVEC (tree, num);
|
||||
|
||||
/* Make a copy of the uses & vuses into USES_COPY, then cprop into
|
||||
the operands. */
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
|
||||
{
|
||||
tree tmp = NULL;
|
||||
tree use = USE_FROM_PTR (use_p);
|
||||
|
||||
copy[i++] = use;
|
||||
if (TREE_CODE (use) == SSA_NAME)
|
||||
tmp = SSA_NAME_VALUE (use);
|
||||
if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
|
||||
SET_USE (use_p, tmp);
|
||||
}
|
||||
|
||||
/* Try to fold/lookup the new expression. Inserting the
|
||||
expression into the hash table is unlikely to help
|
||||
Sadly, we have to handle conditional assignments specially
|
||||
here, because fold expects all the operands of an expression
|
||||
to be folded before the expression itself is folded, but we
|
||||
can't just substitute the folded condition here. */
|
||||
if (TREE_CODE (TREE_OPERAND (stmt, 1)) == COND_EXPR)
|
||||
{
|
||||
tree cond = COND_EXPR_COND (TREE_OPERAND (stmt, 1));
|
||||
cond = fold (cond);
|
||||
if (cond == boolean_true_node)
|
||||
pre_fold_expr = COND_EXPR_THEN (TREE_OPERAND (stmt, 1));
|
||||
else if (cond == boolean_false_node)
|
||||
pre_fold_expr = COND_EXPR_ELSE (TREE_OPERAND (stmt, 1));
|
||||
else
|
||||
pre_fold_expr = TREE_OPERAND (stmt, 1);
|
||||
}
|
||||
else
|
||||
pre_fold_expr = TREE_OPERAND (stmt, 1);
|
||||
|
||||
if (pre_fold_expr)
|
||||
{
|
||||
cached_lhs = fold (pre_fold_expr);
|
||||
if (TREE_CODE (cached_lhs) != SSA_NAME
|
||||
&& !is_gimple_min_invariant (cached_lhs))
|
||||
cached_lhs = (*simplify) (stmt);
|
||||
}
|
||||
|
||||
/* Restore the statement's original uses/defs. */
|
||||
i = 0;
|
||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
|
||||
SET_USE (use_p, copy[i++]);
|
||||
|
||||
free (copy);
|
||||
}
|
||||
|
||||
/* Record the context sensitive equivalence if we were able
|
||||
to simplify this statement. */
|
||||
if (cached_lhs
|
||||
&& (TREE_CODE (cached_lhs) == SSA_NAME
|
||||
|| is_gimple_min_invariant (cached_lhs)))
|
||||
record_temporary_equivalence (TREE_OPERAND (stmt, 0),
|
||||
cached_lhs,
|
||||
stack);
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
||||
/* Simplify the control statement at the end of the block E->dest.
|
||||
|
||||
To avoid allocating memory unnecessarily, a scratch COND_EXPR
|
||||
is available to use/clobber in DUMMY_COND.
|
||||
|
||||
Use SIMPLIFY (a pointer to a callback function) to further simplify
|
||||
a condition using pass specific information.
|
||||
|
||||
Return the simplified condition or NULL if simplification could
|
||||
not be performed. */
|
||||
|
||||
static tree
|
||||
simplify_control_stmt_condition (edge e,
|
||||
tree stmt,
|
||||
tree dummy_cond,
|
||||
tree (*simplify) (tree),
|
||||
bool handle_dominating_asserts)
|
||||
{
|
||||
tree cond, cached_lhs;
|
||||
|
||||
if (TREE_CODE (stmt) == COND_EXPR)
|
||||
cond = COND_EXPR_COND (stmt);
|
||||
else if (TREE_CODE (stmt) == GOTO_EXPR)
|
||||
cond = GOTO_DESTINATION (stmt);
|
||||
else
|
||||
cond = SWITCH_COND (stmt);
|
||||
|
||||
/* For comparisons, we have to update both operands, then try
|
||||
to simplify the comparison. */
|
||||
if (COMPARISON_CLASS_P (cond))
|
||||
{
|
||||
tree op0, op1;
|
||||
enum tree_code cond_code;
|
||||
|
||||
op0 = TREE_OPERAND (cond, 0);
|
||||
op1 = TREE_OPERAND (cond, 1);
|
||||
cond_code = TREE_CODE (cond);
|
||||
|
||||
/* Get the current value of both operands. */
|
||||
if (TREE_CODE (op0) == SSA_NAME)
|
||||
{
|
||||
tree tmp = SSA_NAME_VALUE (op0);
|
||||
if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
|
||||
op0 = tmp;
|
||||
}
|
||||
|
||||
if (TREE_CODE (op1) == SSA_NAME)
|
||||
{
|
||||
tree tmp = SSA_NAME_VALUE (op1);
|
||||
if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
|
||||
op1 = tmp;
|
||||
}
|
||||
|
||||
if (handle_dominating_asserts)
|
||||
{
|
||||
/* Now see if the operand was consumed by an ASSERT_EXPR
|
||||
which dominates E->src. If so, we want to replace the
|
||||
operand with the LHS of the ASSERT_EXPR. */
|
||||
if (TREE_CODE (op0) == SSA_NAME)
|
||||
op0 = lhs_of_dominating_assert (op0, e->src, stmt);
|
||||
|
||||
if (TREE_CODE (op1) == SSA_NAME)
|
||||
op1 = lhs_of_dominating_assert (op1, e->src, stmt);
|
||||
}
|
||||
|
||||
/* We may need to canonicalize the comparison. For
|
||||
example, op0 might be a constant while op1 is an
|
||||
SSA_NAME. Failure to canonicalize will cause us to
|
||||
miss threading opportunities. */
|
||||
if (cond_code != SSA_NAME
|
||||
&& tree_swap_operands_p (op0, op1, false))
|
||||
{
|
||||
tree tmp;
|
||||
cond_code = swap_tree_comparison (TREE_CODE (cond));
|
||||
tmp = op0;
|
||||
op0 = op1;
|
||||
op1 = tmp;
|
||||
}
|
||||
|
||||
/* Stuff the operator and operands into our dummy conditional
|
||||
expression. */
|
||||
TREE_SET_CODE (COND_EXPR_COND (dummy_cond), cond_code);
|
||||
TREE_OPERAND (COND_EXPR_COND (dummy_cond), 0) = op0;
|
||||
TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1) = op1;
|
||||
|
||||
/* We absolutely do not care about any type conversions
|
||||
we only care about a zero/nonzero value. */
|
||||
cached_lhs = fold (COND_EXPR_COND (dummy_cond));
|
||||
while (TREE_CODE (cached_lhs) == NOP_EXPR
|
||||
|| TREE_CODE (cached_lhs) == CONVERT_EXPR
|
||||
|| TREE_CODE (cached_lhs) == NON_LVALUE_EXPR)
|
||||
cached_lhs = TREE_OPERAND (cached_lhs, 0);
|
||||
|
||||
/* If we have not simplified the condition down to an invariant,
|
||||
then use the pass specific callback to simplify the condition. */
|
||||
if (! is_gimple_min_invariant (cached_lhs))
|
||||
cached_lhs = (*simplify) (dummy_cond);
|
||||
}
|
||||
|
||||
/* We can have conditionals which just test the state of a variable
|
||||
rather than use a relational operator. These are simpler to handle. */
|
||||
else if (TREE_CODE (cond) == SSA_NAME)
|
||||
{
|
||||
cached_lhs = cond;
|
||||
|
||||
/* Get the variable's current value from the equivalency chains. */
|
||||
while (cached_lhs
|
||||
&& TREE_CODE (cached_lhs) == SSA_NAME
|
||||
&& SSA_NAME_VALUE (cached_lhs))
|
||||
cached_lhs = SSA_NAME_VALUE (cached_lhs);
|
||||
|
||||
/* If we're dominated by a suitable ASSERT_EXPR, then
|
||||
update CACHED_LHS appropriately. */
|
||||
if (handle_dominating_asserts && TREE_CODE (cached_lhs) == SSA_NAME)
|
||||
cached_lhs = lhs_of_dominating_assert (cached_lhs, e->src, stmt);
|
||||
|
||||
/* If we haven't simplified to an invariant yet, then use the
|
||||
pass specific callback to try and simplify it further. */
|
||||
if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
|
||||
cached_lhs = (*simplify) (stmt);
|
||||
}
|
||||
else
|
||||
cached_lhs = NULL;
|
||||
|
||||
return cached_lhs;
|
||||
}
|
||||
|
||||
/* We are exiting E->src, see if E->dest ends with a conditional
|
||||
jump which has a known value when reached via E.
|
||||
|
||||
Special care is necessary if E is a back edge in the CFG as we
|
||||
may have already recorded equivalences for E->dest into our
|
||||
various tables, including the result of the conditional at
|
||||
the end of E->dest. Threading opportunities are severely
|
||||
limited in that case to avoid short-circuiting the loop
|
||||
incorrectly.
|
||||
|
||||
Note it is quite common for the first block inside a loop to
|
||||
end with a conditional which is either always true or always
|
||||
false when reached via the loop backedge. Thus we do not want
|
||||
to blindly disable threading across a loop backedge. */
|
||||
|
||||
void
|
||||
thread_across_edge (tree dummy_cond,
|
||||
edge e,
|
||||
bool handle_dominating_asserts,
|
||||
VEC(tree, heap) **stack,
|
||||
tree (*simplify) (tree))
|
||||
{
|
||||
tree stmt;
|
||||
|
||||
stmt_count = 0;
|
||||
|
||||
/* PHIs create temporary equivalences. */
|
||||
if (!record_temporary_equivalences_from_phis (e, stack))
|
||||
goto fail;
|
||||
|
||||
/* Now walk each statement recording any context sensitive
|
||||
temporary equivalences we can detect. */
|
||||
stmt = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify);
|
||||
if (!stmt)
|
||||
goto fail;
|
||||
|
||||
/* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
|
||||
will be taken. */
|
||||
if (TREE_CODE (stmt) == COND_EXPR
|
||||
|| TREE_CODE (stmt) == GOTO_EXPR
|
||||
|| TREE_CODE (stmt) == SWITCH_EXPR)
|
||||
{
|
||||
tree cond;
|
||||
|
||||
/* Extract and simplify the condition. */
|
||||
cond = simplify_control_stmt_condition (e, stmt, dummy_cond, simplify, handle_dominating_asserts);
|
||||
|
||||
if (cond && is_gimple_min_invariant (cond))
|
||||
{
|
||||
edge taken_edge = find_taken_edge (e->dest, cond);
|
||||
basic_block dest = (taken_edge ? taken_edge->dest : NULL);
|
||||
|
||||
if (dest == e->dest)
|
||||
goto fail;
|
||||
|
||||
remove_temporary_equivalences (stack);
|
||||
register_jump_thread (e, taken_edge);
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
remove_temporary_equivalences (stack);
|
||||
}
|
179
gcc/tree-vrp.c
179
gcc/tree-vrp.c
|
@ -2755,7 +2755,24 @@ find_conditional_asserts (basic_block bb)
|
|||
/* Remove the COND_EXPR operands from the FOUND_IN_SUBGRAPH bitmap.
|
||||
Otherwise, when we finish traversing each of the sub-graphs, we
|
||||
won't know whether the variables were found in the sub-graphs or
|
||||
if they had been found in a block upstream from BB. */
|
||||
if they had been found in a block upstream from BB.
|
||||
|
||||
This is actually a bad idea is some cases, particularly jump
|
||||
threading. Consider a CFG like the following:
|
||||
|
||||
0
|
||||
/|
|
||||
1 |
|
||||
\|
|
||||
2
|
||||
/ \
|
||||
3 4
|
||||
|
||||
Assume that one or more operands in the conditional at the
|
||||
end of block 0 are used in a conditional in block 2, but not
|
||||
anywhere in block 1. In this case we will not insert any
|
||||
assert statements in block 1, which may cause us to miss
|
||||
opportunities to optimize, particularly for jump threading. */
|
||||
FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
|
||||
RESET_BIT (found_in_subgraph, SSA_NAME_VERSION (op));
|
||||
|
||||
|
@ -4202,6 +4219,157 @@ simplify_stmt_using_ranges (tree stmt)
|
|||
}
|
||||
}
|
||||
|
||||
/* Stack of dest,src equivalency pairs that need to be restored after
|
||||
each attempt to thread a block's incoming edge to an outgoing edge.
|
||||
|
||||
A NULL entry is used to mark the end of pairs which need to be
|
||||
restored. */
|
||||
static VEC(tree,heap) *stack;
|
||||
|
||||
/* A trivial wrapper so that we can present the generic jump
|
||||
threading code with a simple API for simplifying statements. */
|
||||
static tree
|
||||
simplify_stmt_for_jump_threading (tree stmt)
|
||||
{
|
||||
/* We only use VRP information to simplify conditionals. This is
|
||||
overly conservative, but it's unclear if doing more would be
|
||||
worth the compile time cost. */
|
||||
if (TREE_CODE (stmt) != COND_EXPR)
|
||||
return NULL;
|
||||
|
||||
return vrp_evaluate_conditional (COND_EXPR_COND (stmt), true);
|
||||
}
|
||||
|
||||
/* Blocks which have more than one predecessor and more than
|
||||
one successor present jump threading opportunities. ie,
|
||||
when the block is reached from a specific predecessor, we
|
||||
may be able to determine which of the outgoing edges will
|
||||
be traversed. When this optimization applies, we are able
|
||||
to avoid conditionals at runtime and we may expose secondary
|
||||
optimization opportunities.
|
||||
|
||||
This routine is effectively a driver for the generic jump
|
||||
threading code. It basically just presents the generic code
|
||||
with edges that may be suitable for jump threading.
|
||||
|
||||
Unlike DOM, we do not iterate VRP if jump threading was successful.
|
||||
While iterating may expose new opportunities for VRP, it is expected
|
||||
those opportunities would be very limited and the compile time cost
|
||||
to expose those opportunities would be significant.
|
||||
|
||||
As jump threading opportunities are discovered, they are registered
|
||||
for later realization. */
|
||||
|
||||
static void
|
||||
identify_jump_threads (void)
|
||||
{
|
||||
basic_block bb;
|
||||
tree dummy;
|
||||
|
||||
/* Ugh. When substituting values earlier in this pass we can
|
||||
wipe the dominance information. So rebuild the dominator
|
||||
information as we need it within the jump threading code. */
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
|
||||
/* We do not allow VRP information to be used for jump threading
|
||||
across a back edge in the CFG. Otherwise it becomes too
|
||||
difficult to avoid eliminating loop exit tests. Of course
|
||||
EDGE_DFS_BACK is not accurate at this time so we have to
|
||||
recompute it. */
|
||||
mark_dfs_back_edges ();
|
||||
|
||||
/* Allocate our unwinder stack to unwind any temporary equivalences
|
||||
that might be recorded. */
|
||||
stack = VEC_alloc (tree, heap, 20);
|
||||
|
||||
/* To avoid lots of silly node creation, we create a single
|
||||
conditional and just modify it in-place when attempting to
|
||||
thread jumps. */
|
||||
dummy = build2 (EQ_EXPR, boolean_type_node, NULL, NULL);
|
||||
dummy = build3 (COND_EXPR, void_type_node, dummy, NULL, NULL);
|
||||
|
||||
/* Walk through all the blocks finding those which present a
|
||||
potential jump threading opportunity. We could set this up
|
||||
as a dominator walker and record data during the walk, but
|
||||
I doubt it's worth the effort for the classes of jump
|
||||
threading opportunities we are trying to identify at this
|
||||
point in compilation. */
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
tree last, cond;
|
||||
|
||||
/* If the generic jump threading code does not find this block
|
||||
interesting, then there is nothing to do. */
|
||||
if (! potentially_threadable_block (bb))
|
||||
continue;
|
||||
|
||||
/* We only care about blocks ending in a COND_EXPR. While there
|
||||
may be some value in handling SWITCH_EXPR here, I doubt it's
|
||||
terribly important. */
|
||||
last = bsi_stmt (bsi_last (bb));
|
||||
if (TREE_CODE (last) != COND_EXPR)
|
||||
continue;
|
||||
|
||||
/* We're basically looking for any kind of conditional with
|
||||
integral type arguments. */
|
||||
cond = COND_EXPR_COND (last);
|
||||
if ((TREE_CODE (cond) == SSA_NAME
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (cond)))
|
||||
|| (COMPARISON_CLASS_P (cond)
|
||||
&& TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 0)))
|
||||
&& (TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME
|
||||
|| is_gimple_min_invariant (TREE_OPERAND (cond, 1)))
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))))
|
||||
{
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
|
||||
/* We've got a block with multiple predecessors and multiple
|
||||
successors which also ends in a suitable conditional. For
|
||||
each predecessor, see if we can thread it to a specific
|
||||
successor. */
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
{
|
||||
/* Do not thread across back edges or abnormal edges
|
||||
in the CFG. */
|
||||
if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
|
||||
continue;
|
||||
|
||||
thread_across_edge (dummy, e, true,
|
||||
&stack,
|
||||
simplify_stmt_for_jump_threading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We do not actually update the CFG or SSA graphs at this point as
|
||||
ASSERT_EXPRs are still in the IL and cfg cleanup code does not yet
|
||||
handle ASSERT_EXPRs gracefully. */
|
||||
}
|
||||
|
||||
/* We identified all the jump threading opportunities earlier, but could
|
||||
not transform the CFG at that time. This routine transforms the
|
||||
CFG and arranges for the dominator tree to be rebuilt if necessary.
|
||||
|
||||
Note the SSA graph update will occur during the normal TODO
|
||||
processing by the pass manager. */
|
||||
static void
|
||||
finalize_jump_threads (void)
|
||||
{
|
||||
bool cfg_altered = false;
|
||||
cfg_altered = thread_through_all_blocks ();
|
||||
|
||||
/* If we threaded jumps, then we need to recompute the dominance
|
||||
information, to safely do that we must clean up the CFG first. */
|
||||
if (cfg_altered)
|
||||
{
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
cleanup_tree_cfg ();
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
}
|
||||
VEC_free (tree, heap, stack);
|
||||
}
|
||||
|
||||
|
||||
/* Traverse all the blocks folding conditionals with known ranges. */
|
||||
|
@ -4246,6 +4414,10 @@ vrp_finalize (void)
|
|||
|
||||
substitute_and_fold (single_val_range, true);
|
||||
|
||||
/* We must identify jump threading opportunities before we release
|
||||
the datastructures built by VRP. */
|
||||
identify_jump_threads ();
|
||||
|
||||
/* Free allocated memory. */
|
||||
for (i = 0; i < num_ssa_names; i++)
|
||||
if (vr_value[i])
|
||||
|
@ -4323,7 +4495,12 @@ execute_vrp (void)
|
|||
current_loops = NULL;
|
||||
}
|
||||
|
||||
/* ASSERT_EXPRs must be removed before finalizing jump threads
|
||||
as finalizing jump threads calls the CFG cleanup code which
|
||||
does not properly handle ASSERT_EXPRs. */
|
||||
remove_range_assertions ();
|
||||
finalize_jump_threads ();
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
Loading…
Add table
Reference in a new issue