re PR tree-optimization/68619 (error: loop with header 6 not in loop tree)

2015-12-10  Jeff Law  <law@redhat.com>

	PR tree-optimization/68619
	* tree-ssa-dom.c (dom_opt_dom_walker::before_dom_children): Propgate
	return value from optimize_stmt.
	(dom_opt_dom_walker): Add new argument to dom_walker constructor.
	(pass_dominator:execute): If a block has an unreachable edge,
	remove all jump threads through any successor of the affected block.
	(record_equivalences_from_phis): Ignore alternative if the edge
	does not have EDGE_EXECUTABLE set.
	(single_incoming_edge_ignoring_loop_edges): Similarly.
	(optimize_stmt): If a gimple_code has a compile-time constant
	condition, return the edge taken for that constant value.  Also
	change the condition to true/false as necessary.
	* domwalk.h (dom_walker::dom_walker): Add new argument
	skip_unreachable_blocks.  Don't provide empty constructor body.
	(dom_walker::before_dom_children): Change return type.
	(dom_walker::bb_reachable): Declare new private method.
	(dom_walker::propagate_unreachable_to_edges): Likewise.
	(dom_walker::m_unreachable_dom): Declare new private data member.
	(dom_walker::m_skip_unreachable_blocks): Likewise.
	* domwalk.c: Include dumpfile.h.
	(dom_walker::dom_walker): New constructor.  Initialize private data
	members.  If needed, set EDGE_EXECUTABLE for all edges in the CFG,
	extracted from tree-ssa-sccvn.c.
	(dom_walker::bb_reachable): New method extracted from tree-ssa-sccvn.c
	(dom_walker::propagate_unreachable_to_edges): Likewise.
	(dom_walker::walk): Only call before_dom_children on reachable
	blocks.  If before_dom_children returns an edge, then clear
	EDGE_EXECUTABLE for all other outgoing edges from the same block.
	For unreachable blocks, call propagate_unreachable_to_edges.
	Similarly, only call after_dom_children on reachable blocks.  For
	unreachable blocks, conditionally clear m_unreachable_dom.
	* tree-ssa-sccvn.c (sccvn_dom_walker::unreachable_dom): Remove
	private data member.
	(sccvn_dom_walker::after_dom_children): Use methods from dom_walker
	class.
	(run_scc_vn): Likewise.
	(sccvn_dom_walker::before_dom_children): Likewise.  Return the taken
	outgoing edge if a COND, SWITCH, or GOTO are optimized.
	* compare-elim.c (find_comparison_dom_walker::before_dom_children):
	Change return type to an edge.  Always return NULL.
	* fwprop.c (single_def_use_dom_walker::before_dom_children): Likewise.
	* gimple-ssa-strength-reduction.c
	(find_candidates_dom_walker::before_dom_children): Likewise.
	* ipa-prop.c (analysis_dom_walker::before_dom_children): Likewise.
	(ipcp_modif_dom_walker::before_dom_children): Likewise.
	* tree-into-ssa.c (rewrite_dom_walker::before_dom_children): Likewise.
	(rewrite_update_dom_walker::before_dom_children): Likewise.
	(mark_def_dom_children::before_dom_children): Likewise.
	* tree-ssa-dse.c (dse_dom_walker::before_dom_children): Likewise.
	* tree-ssa-loop-im.c
	(invariantness_dom_walker::before_dom_children): Likewise.
	(move_computations_dom_walker::before_dom_walker): Likewise.
	* tree-ssa-phiopt.c
	(nontrapping_dom_walker::before_dom_children): Likewise.
	* tree-ssa-pre.c
	(eliminate_dom_walker::before_dom_children): Likewise.
	* tree-ssa-propagate.c
	(substitute_and_fold_dom_walker::before_dom_children): Likewise.
	* tree-ssa-strlen.c
	(strlen_dom_walker::before_dom_children): Likewise.
	* tree-ssa-uncprop.c
	(uncprop_dom_walker::before_dom_children): Likewise.

	PR tree-optimization/68619
	* gcc.dg/tree-ssa/pr68619-1.c: New test.
	* gcc.dg/tree-ssa/pr68619-2.c: New test.
	* gcc.dg/tree-ssa/pr68619-3.c: New test.
	* gcc.dg/tree-ssa/pr68619-4.c: New test.
	* gcc.dg/tree-ssa/pr68619-5.c: New test.

From-SVN: r231527
This commit is contained in:
Jeff Law 2015-12-10 09:34:43 -07:00 committed by Jeff Law
parent 9dd920ab70
commit 3daacdcd5f
23 changed files with 740 additions and 136 deletions

View File

@ -1,3 +1,68 @@
2015-12-10 Jeff Law <law@redhat.com>
PR tree-optimization/68619
* tree-ssa-dom.c (dom_opt_dom_walker::before_dom_children): Propgate
return value from optimize_stmt.
(dom_opt_dom_walker): Add new argument to dom_walker constructor.
(pass_dominator:execute): If a block has an unreachable edge,
remove all jump threads through any successor of the affected block.
(record_equivalences_from_phis): Ignore alternative if the edge
does not have EDGE_EXECUTABLE set.
(single_incoming_edge_ignoring_loop_edges): Similarly.
(optimize_stmt): If a gimple_code has a compile-time constant
condition, return the edge taken for that constant value. Also
change the condition to true/false as necessary.
* domwalk.h (dom_walker::dom_walker): Add new argument
skip_unreachable_blocks. Don't provide empty constructor body.
(dom_walker::before_dom_children): Change return type.
(dom_walker::bb_reachable): Declare new private method.
(dom_walker::propagate_unreachable_to_edges): Likewise.
(dom_walker::m_unreachable_dom): Declare new private data member.
(dom_walker::m_skip_unreachable_blocks): Likewise.
* domwalk.c: Include dumpfile.h.
(dom_walker::dom_walker): New constructor. Initialize private data
members. If needed, set EDGE_EXECUTABLE for all edges in the CFG,
extracted from tree-ssa-sccvn.c.
(dom_walker::bb_reachable): New method extracted from tree-ssa-sccvn.c
(dom_walker::propagate_unreachable_to_edges): Likewise.
(dom_walker::walk): Only call before_dom_children on reachable
blocks. If before_dom_children returns an edge, then clear
EDGE_EXECUTABLE for all other outgoing edges from the same block.
For unreachable blocks, call propagate_unreachable_to_edges.
Similarly, only call after_dom_children on reachable blocks. For
unreachable blocks, conditionally clear m_unreachable_dom.
* tree-ssa-sccvn.c (sccvn_dom_walker::unreachable_dom): Remove
private data member.
(sccvn_dom_walker::after_dom_children): Use methods from dom_walker
class.
(run_scc_vn): Likewise.
(sccvn_dom_walker::before_dom_children): Likewise. Return the taken
outgoing edge if a COND, SWITCH, or GOTO are optimized.
* compare-elim.c (find_comparison_dom_walker::before_dom_children):
Change return type to an edge. Always return NULL.
* fwprop.c (single_def_use_dom_walker::before_dom_children): Likewise.
* gimple-ssa-strength-reduction.c
(find_candidates_dom_walker::before_dom_children): Likewise.
* ipa-prop.c (analysis_dom_walker::before_dom_children): Likewise.
(ipcp_modif_dom_walker::before_dom_children): Likewise.
* tree-into-ssa.c (rewrite_dom_walker::before_dom_children): Likewise.
(rewrite_update_dom_walker::before_dom_children): Likewise.
(mark_def_dom_children::before_dom_children): Likewise.
* tree-ssa-dse.c (dse_dom_walker::before_dom_children): Likewise.
* tree-ssa-loop-im.c
(invariantness_dom_walker::before_dom_children): Likewise.
(move_computations_dom_walker::before_dom_walker): Likewise.
* tree-ssa-phiopt.c
(nontrapping_dom_walker::before_dom_children): Likewise.
* tree-ssa-pre.c
(eliminate_dom_walker::before_dom_children): Likewise.
* tree-ssa-propagate.c
(substitute_and_fold_dom_walker::before_dom_children): Likewise.
* tree-ssa-strlen.c
(strlen_dom_walker::before_dom_children): Likewise.
* tree-ssa-uncprop.c
(uncprop_dom_walker::before_dom_children): Likewise.
2015-12-10 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/68376

View File

@ -248,7 +248,7 @@ public:
find_comparison_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
};
/* Return true if conforming COMPARE with EH_NOTE is redundant with comparison
@ -294,7 +294,7 @@ can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
compare in the BB is live at the end of the block, install the compare
in BB->AUX. Called via dom_walker.walk (). */
void
edge
find_comparison_dom_walker::before_dom_children (basic_block bb)
{
struct comparison *last_cmp;
@ -426,6 +426,8 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
remove EH edges. */
if (need_purge)
purge_dead_edges (bb);
return NULL;
}
/* Find all comparisons in the function. */

View File

@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "backend.h"
#include "cfganal.h"
#include "domwalk.h"
#include "dumpfile.h"
/* This file implements a generic walker for dominator trees.
@ -142,6 +143,91 @@ cmp_bb_postorder (const void *a, const void *b)
return 1;
}
/* Constructor for a dom walker.
If SKIP_UNREACHBLE_BLOCKS is true, then we need to set
EDGE_EXECUTABLE on every edge in the CFG. */
dom_walker::dom_walker (cdi_direction direction,
bool skip_unreachable_blocks)
: m_dom_direction (direction),
m_skip_unreachable_blocks (skip_unreachable_blocks),
m_unreachable_dom (NULL)
{
/* If we are not skipping unreachable blocks, then there is nothing
to do. */
if (!m_skip_unreachable_blocks)
return;
basic_block bb;
FOR_ALL_BB_FN (bb, cfun)
{
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->succs)
e->flags |= EDGE_EXECUTABLE;
}
}
/* Return TRUE if BB is reachable, false otherwise. */
bool
dom_walker::bb_reachable (struct function *fun, basic_block bb)
{
/* If we're not skipping unreachable blocks, then assume everything
is reachable. */
if (!m_skip_unreachable_blocks)
return true;
/* If any of the predecessor edges that do not come from blocks dominated
by us are still marked as possibly executable consider this block
reachable. */
bool reachable = false;
if (!m_unreachable_dom)
{
reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (fun);
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->preds)
if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
reachable |= (e->flags & EDGE_EXECUTABLE);
}
return reachable;
}
/* BB has been determined to be unreachable. Propagate that property
to incoming and outgoing edges of BB as appropriate. */
void
dom_walker::propagate_unreachable_to_edges (basic_block bb,
FILE *dump_file,
int dump_flags)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Marking all outgoing edges of unreachable "
"BB %d as not executable\n", bb->index);
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->succs)
e->flags &= ~EDGE_EXECUTABLE;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Marking backedge from BB %d into "
"unreachable BB %d as not executable\n",
e->src->index, bb->index);
e->flags &= ~EDGE_EXECUTABLE;
}
}
if (!m_unreachable_dom)
m_unreachable_dom = bb;
}
/* Recursively walk the dominator tree.
BB is the basic block we are currently visiting. */
@ -171,9 +257,23 @@ dom_walker::walk (basic_block bb)
|| bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
|| bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
{
/* Callback for subclasses to do custom things before we have walked
the dominator children, but before we walk statements. */
before_dom_children (bb);
if (this->bb_reachable (cfun, bb))
{
edge taken_edge = before_dom_children (bb);
if (taken_edge)
{
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->succs)
if (e != taken_edge)
e->flags &= ~EDGE_EXECUTABLE;
}
}
else
propagate_unreachable_to_edges (bb, dump_file, dump_flags);
/* Mark the current BB to be popped out of the recursion stack
once children are processed. */
@ -203,7 +303,10 @@ dom_walker::walk (basic_block bb)
/* Callback allowing subclasses to do custom things after we have
walked dominator children, but before we walk statements. */
after_dom_children (bb);
if (bb_reachable (cfun, bb))
after_dom_children (bb);
else if (m_unreachable_dom == bb)
m_unreachable_dom = NULL;
}
if (sp)
bb = worklist[--sp];

View File

@ -30,13 +30,26 @@ along with GCC; see the file COPYING3. If not see
class dom_walker
{
public:
dom_walker (cdi_direction direction) : m_dom_direction (direction) {}
/* Use SKIP_UNREACHBLE_BLOCKS = true when your client can discover
that some edges are not executable.
If a client can discover that a COND, SWITCH or GOTO has a static
target in the before_dom_children callback, the taken edge should
be returned. The generic walker will clear EDGE_EXECUTABLE on all
edges it can determine are not executable. */
dom_walker (cdi_direction direction, bool skip_unreachable_blocks = false);
/* Walk the dominator tree. */
void walk (basic_block);
/* Function to call before the recursive walk of the dominator children. */
virtual void before_dom_children (basic_block) {}
/* Function to call before the recursive walk of the dominator children.
Return value is the always taken edge if the block has multiple outgoing
edges, NULL otherwise. When skipping unreachable blocks, the walker
uses the taken edge information to clear EDGE_EXECUTABLE on the other
edges, exposing unreachable blocks. A NULL return value means all
outgoing edges should still be considered executable. */
virtual edge before_dom_children (basic_block) { return NULL; }
/* Function to call after the recursive walk of the dominator children. */
virtual void after_dom_children (basic_block) {}
@ -47,6 +60,18 @@ private:
if it is set to CDI_POST_DOMINATORS, then we walk the post
dominator tree. */
const ENUM_BITFIELD (cdi_direction) m_dom_direction : 2;
bool m_skip_unreachable_blocks;
basic_block m_unreachable_dom;
/* Query whether or not the given block is reachable or not. */
bool bb_reachable (struct function *, basic_block);
/* Given an unreachable block, propagate that property to outgoing
and possibly incoming edges for the block. Typically called after
determining a block is unreachable in the before_dom_children
callback. */
void propagate_unreachable_to_edges (basic_block, FILE *, int);
};
#endif

View File

@ -208,11 +208,11 @@ class single_def_use_dom_walker : public dom_walker
public:
single_def_use_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
void
edge
single_def_use_dom_walker::before_dom_children (basic_block bb)
{
int bb_index = bb->index;
@ -245,6 +245,8 @@ single_def_use_dom_walker::before_dom_children (basic_block bb)
process_uses (df_get_artificial_uses (bb_index), 0);
process_defs (df_get_artificial_defs (bb_index), 0);
return NULL;
}
/* Pop the definitions created in this basic block when leaving its

View File

@ -1649,12 +1649,12 @@ class find_candidates_dom_walker : public dom_walker
public:
find_candidates_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
};
/* Find strength-reduction candidates in block BB. */
void
edge
find_candidates_dom_walker::before_dom_children (basic_block bb)
{
bool speed = optimize_bb_for_speed_p (bb);
@ -1737,6 +1737,7 @@ find_candidates_dom_walker::before_dom_children (basic_block bb)
}
}
}
return NULL;
}
/* Dump a candidate for debug. */

View File

@ -2245,17 +2245,18 @@ public:
analysis_dom_walker (struct ipa_func_body_info *fbi)
: dom_walker (CDI_DOMINATORS), m_fbi (fbi) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
private:
struct ipa_func_body_info *m_fbi;
};
void
edge
analysis_dom_walker::before_dom_children (basic_block bb)
{
ipa_analyze_params_uses_in_bb (m_fbi, bb);
ipa_compute_jump_functions_for_bb (m_fbi, bb);
return NULL;
}
/* Release body info FBI. */
@ -5098,7 +5099,7 @@ public:
: dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs),
m_aggval (av), m_something_changed (sc), m_cfg_changed (cc) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
private:
struct ipa_func_body_info *m_fbi;
@ -5107,7 +5108,7 @@ private:
bool *m_something_changed, *m_cfg_changed;
};
void
edge
ipcp_modif_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -5198,7 +5199,7 @@ ipcp_modif_dom_walker::before_dom_children (basic_block bb)
&& gimple_purge_dead_eh_edges (gimple_bb (stmt)))
*m_cfg_changed = true;
}
return NULL;
}
/* Update alignment of formal parameters as described in

View File

@ -1,3 +1,12 @@
2015-12-10 Jeff Law <law@redhat.com>
PR tree-optimization/68619
* gcc.dg/tree-ssa/pr68619-1.c: New test.
* gcc.dg/tree-ssa/pr68619-2.c: New test.
* gcc.dg/tree-ssa/pr68619-3.c: New test.
* gcc.dg/tree-ssa/pr68619-4.c: New test.
* gcc.dg/tree-ssa/pr68619-5.c: New test.
2015-12-10 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/68376

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-O2 -w" } */
extern void fn2(int);
int a, b, c;
void fn1() {
int d;
for (; b; b++) {
a = 7;
for (; a;) {
jump:
fn2(d ?: c);
d = 0;
}
d = c;
if (c)
goto jump;
}
goto jump;
}

View File

@ -0,0 +1,92 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-dom2-details -w" } */
typedef union tree_node *tree;
struct gcc_options
{
int x_flag_finite_math_only;
};
extern struct gcc_options global_options;
enum mode_class
{ MODE_RANDOM, MODE_CC, MODE_INT, MODE_PARTIAL_INT, MODE_FRACT, MODE_UFRACT,
MODE_ACCUM, MODE_UACCUM, MODE_FLOAT, MODE_DECIMAL_FLOAT, MODE_COMPLEX_INT,
MODE_COMPLEX_FLOAT, MODE_VECTOR_INT, MODE_VECTOR_FRACT,
MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM,
MODE_VECTOR_FLOAT, MAX_MODE_CLASS
};
extern const unsigned char mode_class[27];
extern const unsigned char mode_inner[27];
struct real_value
{
};
struct real_format
{
unsigned char has_inf;
};
extern const struct real_format *real_format_for_mode[5 -
2 + 1 + 15 - 10 + 1];
struct tree_type
{
};
union tree_node
{
int code;
int mode;
struct tree_type type;
};
tree
omp_reduction_init (tree clause, tree type)
{
if ((((type)->code) == 64))
{
struct real_value max;
if (((((mode_class[((((type))->code) ==
32 ?
vector_type_mode (type)
: (type)->mode)]) ==
MODE_VECTOR_FLOAT)
&&
((real_format_for_mode
[((mode_class[((mode_class[((((type))->code) ==
32 ?
vector_type_mode (type)
: (type)->mode)]) ==
12) ? (((((type))->code)
==
32 ?
vector_type_mode
(type)
: (type)->mode))
: (mode_inner[((((type))->code) ==
32 ?
vector_type_mode (type)
: (type)->mode)])]) ==
12)
? (((((mode_class[((((type))->code) ==
32 ? vector_type_mode (type)
: (type)->mode)]) ==
12) ? (((((type))->code) ==
32 ?
vector_type_mode (type)
: (type)->mode)) : (mode_inner
[((((type))->code) ==
32 ?
vector_type_mode (type)
: (type)->mode)])) - 10) +
(5 - 2 +
1))
: ((((mode_class
[((((type))->code) ==
32 ? vector_type_mode (type) : (type)->mode)]) ==
12) ? (((((type))->code) ==
32 ? vector_type_mode (type) : (type)->
mode)) : (mode_inner[((((type))->code) ==
32 ? vector_type_mode (type)
: (type)->mode)])) -
2)]))->has_inf) && !global_options.x_flag_finite_math_only))
real_inf (&max);
}
}
/* { dg-final { scan-tree-dump "Marking all outgoing edges of unreachable" "dom2"} } */

View File

@ -0,0 +1,26 @@
/* { dg-do compile } */
/* { dg-options "-O2 -w" } */
typedef unsigned int hashval_t;
enum ETYPE
{
ETYPE_ARRAY, ETYPE_STRUCT, ETYPE_UNION,
};
struct entry
{
enum ETYPE etype:8;
unsigned short len;
const char *attrib;
};
e_hash (const void *a)
{
const struct entry *e = a;
hashval_t ret = 0;
int i;
if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION)
abort ();
for (i = 0; i <= e[0].len; ++i)
{
ret = iterative_hash (&e[i], __builtin_offsetof (struct entry, attrib), ret);
}
return ret;
}

View File

@ -0,0 +1,94 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized -w" } */
typedef struct rtx_def *rtx;
enum rtx_code
{
UNKNOWN, VALUE, DEBUG_EXPR, EXPR_LIST, INSN_LIST, SEQUENCE, ADDRESS,
DEBUG_INSN, INSN, JUMP_INSN, CALL_INSN, BARRIER, CODE_LABEL, NOTE,
COND_EXEC, PARALLEL, ASM_INPUT, ASM_OPERANDS, UNSPEC, UNSPEC_VOLATILE,
ADDR_VEC, ADDR_DIFF_VEC, PREFETCH, SET, USE, CLOBBER, CALL, RETURN,
EH_RETURN, TRAP_IF, CONST_INT, CONST_FIXED, CONST_DOUBLE, CONST_VECTOR,
CONST_STRING, CONST, PC, REG, SCRATCH, SUBREG, STRICT_LOW_PART, CONCAT,
CONCATN, MEM, LABEL_REF, SYMBOL_REF, CC0, IF_THEN_ELSE, COMPARE, PLUS,
MINUS, NEG, MULT, SS_MULT, US_MULT, DIV, SS_DIV, US_DIV, MOD, UDIV, UMOD,
AND, IOR, XOR, NOT, ASHIFT, ROTATE, ASHIFTRT, LSHIFTRT, ROTATERT, SMIN,
SMAX, UMIN, UMAX, PRE_DEC, PRE_INC, POST_DEC, POST_INC, PRE_MODIFY,
POST_MODIFY, NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU, UNORDERED,
ORDERED, UNEQ, UNGE, UNGT, UNLE, UNLT, LTGT, SIGN_EXTEND, ZERO_EXTEND,
TRUNCATE, FLOAT_EXTEND, FLOAT_TRUNCATE, FLOAT, FIX, UNSIGNED_FLOAT,
UNSIGNED_FIX, FRACT_CONVERT, UNSIGNED_FRACT_CONVERT, SAT_FRACT,
UNSIGNED_SAT_FRACT, ABS, SQRT, BSWAP, FFS, CLZ, CTZ, POPCOUNT, PARITY,
SIGN_EXTRACT, ZERO_EXTRACT, HIGH, LO_SUM, VEC_MERGE, VEC_SELECT,
VEC_CONCAT, VEC_DUPLICATE, SS_PLUS, US_PLUS, SS_MINUS, SS_NEG, US_NEG,
SS_ABS, SS_ASHIFT, US_ASHIFT, US_MINUS, SS_TRUNCATE, US_TRUNCATE, FMA,
VAR_LOCATION, DEBUG_IMPLICIT_PTR, ENTRY_VALUE, LAST_AND_UNUSED_RTX_CODE
};
enum rtx_class
{
RTX_COMPARE, RTX_COMM_COMPARE, RTX_BIN_ARITH, RTX_COMM_ARITH, RTX_UNARY,
RTX_EXTRA, RTX_MATCH, RTX_INSN, RTX_OBJ, RTX_CONST_OBJ, RTX_TERNARY,
RTX_BITFIELD_OPS, RTX_AUTOINC
};
extern const unsigned char rtx_length[((int) LAST_AND_UNUSED_RTX_CODE)];
extern const enum rtx_class rtx_class[((int) LAST_AND_UNUSED_RTX_CODE)];
union rtunion_def
{
rtx rt_rtx;
};
typedef union rtunion_def rtunion;
struct rtx_def
{
enum rtx_code code:16;
union u
{
rtunion fld[1];
}
u;
};
struct cse_reg_info
{
unsigned int timestamp;
int reg_qty;
int reg_tick;
int reg_in_table;
unsigned int subreg_ticked;
};
static struct cse_reg_info *cse_reg_info_table;
static unsigned int cse_reg_info_timestamp;
static __inline__ struct cse_reg_info *
get_cse_reg_info (unsigned int regno)
{
struct cse_reg_info *p = &cse_reg_info_table[regno];
if (p->timestamp != cse_reg_info_timestamp)
cse_reg_info_table[regno].timestamp = cse_reg_info_timestamp;
}
int
mention_regs (rtx x)
{
enum rtx_code code;
int i, j;
const char *fmt;
int changed = 0;
code = ((x)->code);
if (code == SUBREG
&& ((((((x)->u.fld[0]).rt_rtx))->code) == REG))
{
(get_cse_reg_info (i)->reg_in_table) = (get_cse_reg_info (i)->reg_tick);
(get_cse_reg_info (i)->subreg_ticked) =
(rhs_regno ((((x)->u.fld[0]).rt_rtx)));
}
if ((((rtx_class[(int) (((x)->code))]) & (~1)) == (RTX_COMPARE & (~1))))
{
if (((((((x)->u.fld[0]).rt_rtx))->code) == REG))
foop ();
}
for (i = (rtx_length[(int) (code)]) - 1; i >= 0; i--)
arf ();
}
/* Make sure the constant 39 gets propagated into the PHI at the join point. */
/* { dg-final { scan-tree-dump "PHI <.*, 39" "optimized"} } */

View File

@ -0,0 +1,172 @@
/* { dg-do compile } */
/* { dg-options "-O2 -w" } */
typedef union tree_node *tree;
typedef union gimple_statement_d *gimple;
enum machine_mode
{ VOIDmode, BLKmode, CCmode, CCGCmode, CCGOCmode, CCNOmode, CCAmode, CCCmode,
CCOmode, CCSmode, CCZmode, CCFPmode, CCFPUmode, BImode, QImode, HImode,
SImode, DImode, TImode, OImode, QQmode, HQmode, SQmode, DQmode, TQmode,
UQQmode, UHQmode, USQmode, UDQmode, UTQmode, HAmode, SAmode, DAmode,
TAmode, UHAmode, USAmode, UDAmode, UTAmode, SFmode, DFmode, XFmode,
TFmode, SDmode, DDmode, TDmode, CQImode, CHImode, CSImode, CDImode,
CTImode, COImode, SCmode, DCmode, XCmode, TCmode, V2QImode, V4QImode,
V2HImode, V1SImode, V8QImode, V4HImode, V2SImode, V1DImode, V16QImode,
V8HImode, V4SImode, V2DImode, V1TImode, V32QImode, V16HImode, V8SImode,
V4DImode, V2TImode, V64QImode, V32HImode, V16SImode, V8DImode, V4TImode,
V2SFmode, V4SFmode, V2DFmode, V8SFmode, V4DFmode, V2TFmode, V16SFmode,
V8DFmode, V4TFmode, MAX_MACHINE_MODE, MIN_MODE_RANDOM =
VOIDmode, MAX_MODE_RANDOM = BLKmode, MIN_MODE_CC = CCmode, MAX_MODE_CC =
CCFPUmode, MIN_MODE_INT = QImode, MAX_MODE_INT =
OImode, MIN_MODE_PARTIAL_INT = VOIDmode, MAX_MODE_PARTIAL_INT =
VOIDmode, MIN_MODE_FRACT = QQmode, MAX_MODE_FRACT =
TQmode, MIN_MODE_UFRACT = UQQmode, MAX_MODE_UFRACT =
UTQmode, MIN_MODE_ACCUM = HAmode, MAX_MODE_ACCUM =
TAmode, MIN_MODE_UACCUM = UHAmode, MAX_MODE_UACCUM =
UTAmode, MIN_MODE_FLOAT = SFmode, MAX_MODE_FLOAT =
TFmode, MIN_MODE_DECIMAL_FLOAT = SDmode, MAX_MODE_DECIMAL_FLOAT =
TDmode, MIN_MODE_COMPLEX_INT = CQImode, MAX_MODE_COMPLEX_INT =
COImode, MIN_MODE_COMPLEX_FLOAT = SCmode, MAX_MODE_COMPLEX_FLOAT =
TCmode, MIN_MODE_VECTOR_INT = V2QImode, MAX_MODE_VECTOR_INT =
V4TImode, MIN_MODE_VECTOR_FRACT = VOIDmode, MAX_MODE_VECTOR_FRACT =
VOIDmode, MIN_MODE_VECTOR_UFRACT = VOIDmode, MAX_MODE_VECTOR_UFRACT =
VOIDmode, MIN_MODE_VECTOR_ACCUM = VOIDmode, MAX_MODE_VECTOR_ACCUM =
VOIDmode, MIN_MODE_VECTOR_UACCUM = VOIDmode, MAX_MODE_VECTOR_UACCUM =
VOIDmode, MIN_MODE_VECTOR_FLOAT = V2SFmode, MAX_MODE_VECTOR_FLOAT =
V4TFmode, NUM_MACHINE_MODES = MAX_MACHINE_MODE };
enum mode_class
{ MODE_RANDOM, MODE_CC, MODE_INT, MODE_PARTIAL_INT, MODE_FRACT, MODE_UFRACT,
MODE_ACCUM, MODE_UACCUM, MODE_FLOAT, MODE_DECIMAL_FLOAT, MODE_COMPLEX_INT,
MODE_COMPLEX_FLOAT, MODE_VECTOR_INT, MODE_VECTOR_FRACT,
MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM,
MODE_VECTOR_FLOAT, MAX_MODE_CLASS };
extern const unsigned char mode_class[NUM_MACHINE_MODES];
extern const unsigned char mode_inner[NUM_MACHINE_MODES];
struct real_format
{
unsigned char has_nans;
};
extern const struct real_format *real_format_for_mode[MAX_MODE_FLOAT -
MIN_MODE_FLOAT + 1 +
MAX_MODE_DECIMAL_FLOAT -
MIN_MODE_DECIMAL_FLOAT +
1];
enum tree_code
{ ERROR_MARK, IDENTIFIER_NODE, TREE_LIST, TREE_VEC, BLOCK, OFFSET_TYPE,
ENUMERAL_TYPE, BOOLEAN_TYPE, INTEGER_TYPE, REAL_TYPE, POINTER_TYPE,
REFERENCE_TYPE, NULLPTR_TYPE, FIXED_POINT_TYPE, COMPLEX_TYPE, VECTOR_TYPE,
ARRAY_TYPE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, VOID_TYPE,
FUNCTION_TYPE, METHOD_TYPE, LANG_TYPE, INTEGER_CST, REAL_CST, FIXED_CST,
COMPLEX_CST, VECTOR_CST, STRING_CST, FUNCTION_DECL, LABEL_DECL,
FIELD_DECL, VAR_DECL, CONST_DECL, PARM_DECL, TYPE_DECL, RESULT_DECL,
DEBUG_EXPR_DECL, NAMESPACE_DECL, IMPORTED_DECL, TRANSLATION_UNIT_DECL,
COMPONENT_REF, BIT_FIELD_REF, REALPART_EXPR, IMAGPART_EXPR, ARRAY_REF,
ARRAY_RANGE_REF, INDIRECT_REF, OBJ_TYPE_REF, CONSTRUCTOR, COMPOUND_EXPR,
MODIFY_EXPR, INIT_EXPR, TARGET_EXPR, COND_EXPR, VEC_COND_EXPR, BIND_EXPR,
CALL_EXPR, WITH_CLEANUP_EXPR, CLEANUP_POINT_EXPR, PLACEHOLDER_EXPR,
PLUS_EXPR, MINUS_EXPR, MULT_EXPR, POINTER_PLUS_EXPR, TRUNC_DIV_EXPR,
CEIL_DIV_EXPR, FLOOR_DIV_EXPR, ROUND_DIV_EXPR, TRUNC_MOD_EXPR,
CEIL_MOD_EXPR, FLOOR_MOD_EXPR, ROUND_MOD_EXPR, RDIV_EXPR, EXACT_DIV_EXPR,
FIX_TRUNC_EXPR, FLOAT_EXPR, NEGATE_EXPR, MIN_EXPR, MAX_EXPR, ABS_EXPR,
LSHIFT_EXPR, RSHIFT_EXPR, LROTATE_EXPR, RROTATE_EXPR, BIT_IOR_EXPR,
BIT_XOR_EXPR, BIT_AND_EXPR, BIT_NOT_EXPR, TRUTH_ANDIF_EXPR,
TRUTH_ORIF_EXPR, TRUTH_AND_EXPR, TRUTH_OR_EXPR, TRUTH_XOR_EXPR,
TRUTH_NOT_EXPR, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR, NE_EXPR,
UNORDERED_EXPR, ORDERED_EXPR, UNLT_EXPR, UNLE_EXPR, UNGT_EXPR, UNGE_EXPR,
UNEQ_EXPR, LTGT_EXPR, RANGE_EXPR, PAREN_EXPR, CONVERT_EXPR,
ADDR_SPACE_CONVERT_EXPR, FIXED_CONVERT_EXPR, NOP_EXPR, NON_LVALUE_EXPR,
VIEW_CONVERT_EXPR, COMPOUND_LITERAL_EXPR, SAVE_EXPR, ADDR_EXPR,
FDESC_EXPR, COMPLEX_EXPR, CONJ_EXPR, PREDECREMENT_EXPR, PREINCREMENT_EXPR,
POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, VA_ARG_EXPR, TRY_CATCH_EXPR,
TRY_FINALLY_EXPR, DECL_EXPR, LABEL_EXPR, GOTO_EXPR, RETURN_EXPR,
EXIT_EXPR, LOOP_EXPR, SWITCH_EXPR, CASE_LABEL_EXPR, ASM_EXPR, SSA_NAME,
CATCH_EXPR, EH_FILTER_EXPR, SCEV_KNOWN, SCEV_NOT_KNOWN, POLYNOMIAL_CHREC,
STATEMENT_LIST, ASSERT_EXPR, TREE_BINFO, WITH_SIZE_EXPR,
REALIGN_LOAD_EXPR, TARGET_MEM_REF, MEM_REF, OMP_PARALLEL, OMP_TASK,
OMP_FOR, OMP_SECTIONS, OMP_SINGLE, OMP_SECTION, OMP_MASTER, OMP_ORDERED,
OMP_CRITICAL, OMP_ATOMIC, OMP_CLAUSE, REDUC_MAX_EXPR, REDUC_MIN_EXPR,
REDUC_PLUS_EXPR, DOT_PROD_EXPR, WIDEN_SUM_EXPR, WIDEN_MULT_EXPR,
WIDEN_MULT_PLUS_EXPR, WIDEN_MULT_MINUS_EXPR, FMA_EXPR, VEC_LSHIFT_EXPR,
VEC_RSHIFT_EXPR, VEC_WIDEN_MULT_HI_EXPR, VEC_WIDEN_MULT_LO_EXPR,
VEC_UNPACK_HI_EXPR, VEC_UNPACK_LO_EXPR, VEC_UNPACK_FLOAT_HI_EXPR,
VEC_UNPACK_FLOAT_LO_EXPR, VEC_PACK_TRUNC_EXPR, VEC_PACK_SAT_EXPR,
VEC_PACK_FIX_TRUNC_EXPR, VEC_EXTRACT_EVEN_EXPR, VEC_EXTRACT_ODD_EXPR,
VEC_INTERLEAVE_HIGH_EXPR, VEC_INTERLEAVE_LOW_EXPR, PREDICT_EXPR,
OPTIMIZATION_NODE, TARGET_OPTION_NODE, LAST_AND_UNUSED_TREE_CODE,
C_MAYBE_CONST_EXPR, EXCESS_PRECISION_EXPR, UNCONSTRAINED_ARRAY_TYPE,
UNCONSTRAINED_ARRAY_REF, NULL_EXPR, PLUS_NOMOD_EXPR, MINUS_NOMOD_EXPR,
ATTR_ADDR_EXPR, STMT_STMT, LOOP_STMT, EXIT_STMT, OFFSET_REF, PTRMEM_CST,
NEW_EXPR, VEC_NEW_EXPR, DELETE_EXPR, VEC_DELETE_EXPR, SCOPE_REF,
MEMBER_REF, TYPE_EXPR, AGGR_INIT_EXPR, VEC_INIT_EXPR, THROW_EXPR,
EMPTY_CLASS_EXPR, BASELINK, TEMPLATE_DECL, TEMPLATE_PARM_INDEX,
TEMPLATE_TEMPLATE_PARM, TEMPLATE_TYPE_PARM, TYPENAME_TYPE, TYPEOF_TYPE,
BOUND_TEMPLATE_TEMPLATE_PARM, UNBOUND_CLASS_TEMPLATE, USING_DECL,
USING_STMT, DEFAULT_ARG, TEMPLATE_ID_EXPR, OVERLOAD, PSEUDO_DTOR_EXPR,
MODOP_EXPR, CAST_EXPR, REINTERPRET_CAST_EXPR, CONST_CAST_EXPR,
STATIC_CAST_EXPR, DYNAMIC_CAST_EXPR, DOTSTAR_EXPR, TYPEID_EXPR,
NOEXCEPT_EXPR, NON_DEPENDENT_EXPR, CTOR_INITIALIZER, TRY_BLOCK,
EH_SPEC_BLOCK, HANDLER, MUST_NOT_THROW_EXPR, CLEANUP_STMT, IF_STMT,
FOR_STMT, RANGE_FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT, CONTINUE_STMT,
SWITCH_STMT, EXPR_STMT, TAG_DEFN, OFFSETOF_EXPR, SIZEOF_EXPR, ARROW_EXPR,
ALIGNOF_EXPR, AT_ENCODE_EXPR, STMT_EXPR, UNARY_PLUS_EXPR, STATIC_ASSERT,
TYPE_ARGUMENT_PACK, NONTYPE_ARGUMENT_PACK, TYPE_PACK_EXPANSION,
EXPR_PACK_EXPANSION, ARGUMENT_PACK_SELECT, TRAIT_EXPR, LAMBDA_EXPR,
DECLTYPE_TYPE, TEMPLATE_INFO, URSHIFT_EXPR, COMPARE_EXPR, COMPARE_L_EXPR,
COMPARE_G_EXPR, CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE,
CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
PROTOCOL_INTERFACE_TYPE, KEYWORD_DECL, INSTANCE_METHOD_DECL,
CLASS_METHOD_DECL, PROPERTY_DECL, MESSAGE_SEND_EXPR, CLASS_REFERENCE_EXPR,
PROPERTY_REF, MAX_TREE_CODES };
struct tree_base
{
enum tree_code code:16;
};
struct tree_typed
{
tree type;
};
struct tree_type
{
enum machine_mode mode:8;
};
union tree_node
{
struct tree_base base;
struct tree_typed typed;
struct tree_type type;
};
enum tree_code
parse_predicate (tree cond, tree * op0, tree * op1)
{
gimple s;
tree op;
tree type = (*(&op->typed.type));
enum tree_code code;
return invert_tree_comparison (code,
((((mode_class
[((((type))->base.code) ==
VECTOR_TYPE ? vector_type_mode (type)
: (type)->type.mode)]) ==
MODE_VECTOR_FLOAT)
&&
((real_format_for_mode
[(((enum mode_class)
mode_class[(((enum mode_class)
mode_class[((((type))->
base.
code) ==
VECTOR_TYPE ?
vector_type_mode
(type)
: (type)->
type.
mode)]) ==
MODE_DECIMAL_FLOAT)
? (((((type))->base.
code) ==
VECTOR_TYPE ?
vector_type_mode (type)
: (type)->type.
mode)) : ((enum
machine_mode)
mode_inner[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)])]) == MODE_DECIMAL_FLOAT) ? ((((((enum mode_class) mode_class[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)]) == MODE_DECIMAL_FLOAT) ? (((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)) : ((enum machine_mode) mode_inner[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)])) - MIN_MODE_DECIMAL_FLOAT) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : (((((enum mode_class) mode_class[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)]) == MODE_DECIMAL_FLOAT) ? (((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)) : ((enum machine_mode) mode_inner[((((type))->base.code) == VECTOR_TYPE ? vector_type_mode (type) : (type)->type.mode)])) - MIN_MODE_FLOAT)]))->has_nans) ));
}

View File

@ -1391,7 +1391,7 @@ class rewrite_dom_walker : public dom_walker
public:
rewrite_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
@ -1400,7 +1400,7 @@ public:
(BLOCK_DEFS). Register new definitions for every PHI node in the
block. */
void
edge
rewrite_dom_walker::before_dom_children (basic_block bb)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@ -1432,6 +1432,8 @@ rewrite_dom_walker::before_dom_children (basic_block bb)
reaching definition for the variable and the edge through which that
definition is reaching the PHI node. */
rewrite_add_phi_arguments (bb);
return NULL;
}
@ -2055,7 +2057,7 @@ class rewrite_update_dom_walker : public dom_walker
public:
rewrite_update_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
@ -2064,7 +2066,7 @@ public:
for new SSA names produced in this block (BLOCK_DEFS). Register
new definitions for every PHI node in the block. */
void
edge
rewrite_update_dom_walker::before_dom_children (basic_block bb)
{
bool is_abnormal_phi;
@ -2077,7 +2079,7 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
block_defs_stack.safe_push (NULL_TREE);
if (!bitmap_bit_p (blocks_to_update, bb->index))
return;
return NULL;
/* Mark the LHS if any of the arguments flows through an abnormal
edge. */
@ -2133,6 +2135,8 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
/* Step 3. Update PHI nodes. */
rewrite_update_phi_arguments (bb);
return NULL;
}
/* Called after visiting block BB. Unwind BLOCK_DEFS_STACK to restore
@ -2210,7 +2214,7 @@ public:
mark_def_dom_walker (cdi_direction direction);
~mark_def_dom_walker ();
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
private:
/* Notice that this bitmap is indexed using variable UIDs, so it must be
@ -2232,7 +2236,7 @@ mark_def_dom_walker::~mark_def_dom_walker ()
/* Block processing routine for mark_def_sites. Clear the KILLS bitmap
at the start of each block, and call mark_def_sites for each statement. */
void
edge
mark_def_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -2240,6 +2244,7 @@ mark_def_dom_walker::before_dom_children (basic_block bb)
bitmap_clear (m_kills);
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
mark_def_sites (bb, gsi_stmt (gsi), m_kills);
return NULL;
}
/* Initialize internal data needed during renaming. */

View File

@ -99,7 +99,7 @@ struct opt_stats_d
static struct opt_stats_d opt_stats;
/* Local functions. */
static void optimize_stmt (basic_block, gimple_stmt_iterator,
static edge optimize_stmt (basic_block, gimple_stmt_iterator,
class const_and_copies *,
class avail_exprs_stack *);
static tree lookup_avail_expr (gimple *, bool, class avail_exprs_stack *);
@ -493,12 +493,12 @@ public:
dom_opt_dom_walker (cdi_direction direction,
class const_and_copies *const_and_copies,
class avail_exprs_stack *avail_exprs_stack)
: dom_walker (direction),
: dom_walker (direction, true),
m_const_and_copies (const_and_copies),
m_avail_exprs_stack (avail_exprs_stack),
m_dummy_cond (NULL) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
@ -611,6 +611,36 @@ pass_dominator::execute (function *fun)
avail_exprs_stack);
walker.walk (fun->cfg->x_entry_block_ptr);
/* Look for blocks where we cleared EDGE_EXECUTABLE on an outgoing
edge. When found, remove jump threads which contain any outgoing
edge from the affected block. */
if (cfg_altered)
{
FOR_EACH_BB_FN (bb, fun)
{
edge_iterator ei;
edge e;
/* First see if there are any edges without EDGE_EXECUTABLE
set. */
bool found = false;
FOR_EACH_EDGE (e, ei, bb->succs)
{
if ((e->flags & EDGE_EXECUTABLE) == 0)
{
found = true;
break;
}
}
/* If there were any such edges found, then remove jump threads
containing any edge leaving BB. */
if (found)
FOR_EACH_EDGE (e, ei, bb->succs)
remove_jump_threads_including (e);
}
}
{
gimple_stmt_iterator gsi;
basic_block bb;
@ -951,6 +981,11 @@ record_equivalences_from_phis (basic_block bb)
if (lhs == t)
continue;
/* If the associated edge is not marked as executable, then it
can be ignored. */
if ((gimple_phi_arg_edge (phi, i)->flags & EDGE_EXECUTABLE) == 0)
continue;
t = dom_valueize (t);
/* If we have not processed an alternative yet, then set
@ -997,6 +1032,10 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
continue;
/* We can safely ignore edges that are not executable. */
if ((e->flags & EDGE_EXECUTABLE) == 0)
continue;
/* If we have already seen a non-loop edge, then we must have
multiple incoming non-loop edges and thus we return NULL. */
if (retval)
@ -1294,7 +1333,7 @@ cprop_into_successor_phis (basic_block bb,
}
}
void
edge
dom_opt_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -1322,12 +1361,15 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
m_avail_exprs_stack);
m_avail_exprs_stack->pop_to_marker ();
edge taken_edge = NULL;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
optimize_stmt (bb, gsi, m_const_and_copies, m_avail_exprs_stack);
taken_edge
= optimize_stmt (bb, gsi, m_const_and_copies, m_avail_exprs_stack);
/* Now prepare to process dominated blocks. */
record_edge_info (bb);
cprop_into_successor_phis (bb, m_const_and_copies);
return taken_edge;
}
/* We have finished processing the dominator children of BB, perform
@ -1694,7 +1736,7 @@ cprop_into_stmt (gimple *stmt)
assignment is found, we map the value on the RHS of the assignment to
the variable in the LHS in the CONST_AND_COPIES table. */
static void
static edge
optimize_stmt (basic_block bb, gimple_stmt_iterator si,
class const_and_copies *const_and_copies,
class avail_exprs_stack *avail_exprs_stack)
@ -1703,6 +1745,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
bool may_optimize_p;
bool modified_p = false;
bool was_noreturn;
edge retval = NULL;
old_stmt = stmt = gsi_stmt (si);
was_noreturn = is_gimple_call (stmt) && gimple_call_noreturn_p (stmt);
@ -1823,7 +1866,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
fprintf (dump_file, " Flagged to clear EH edges.\n");
}
release_defs (stmt);
return;
return retval;
}
}
}
@ -1849,25 +1892,19 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
if (val && TREE_CODE (val) == INTEGER_CST)
{
edge taken_edge = find_taken_edge (bb, val);
if (taken_edge)
retval = find_taken_edge (bb, val);
if (retval)
{
/* We need to remove any queued jump threads that
reference outgoing edges from this block. */
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->succs)
remove_jump_threads_including (e);
/* Now clean up the control statement at the end of
BB and remove unexecutable edges. */
remove_ctrl_stmt_and_useless_edges (bb, taken_edge->dest);
/* Fixup the flags on the single remaining edge. */
taken_edge->flags
&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
taken_edge->flags |= EDGE_FALLTHRU;
/* Fix the condition to be either true or false. */
if (gimple_code (stmt) == GIMPLE_COND)
{
if (integer_zerop (val))
gimple_cond_make_false (as_a <gcond *> (stmt));
else if (integer_onep (val))
gimple_cond_make_true (as_a <gcond *> (stmt));
else
gcc_unreachable ();
}
/* Further simplifications may be possible. */
cfg_altered = true;
@ -1887,6 +1924,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
&& is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
need_noreturn_fixup.safe_push (stmt);
}
return retval;
}
/* Helper for walk_non_aliased_vuses. Determine if we arrived at

View File

@ -316,10 +316,10 @@ class dse_dom_walker : public dom_walker
public:
dse_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
};
void
edge
dse_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -332,6 +332,7 @@ dse_dom_walker::before_dom_children (basic_block bb)
else
gsi_prev (&gsi);
}
return NULL;
}
namespace {

View File

@ -958,14 +958,14 @@ public:
invariantness_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
};
/* Determine the outermost loops in that statements in basic block BB are
invariant, and record them to the LIM_DATA associated with the statements.
Callback for dom_walker. */
void
edge
invariantness_dom_walker::before_dom_children (basic_block bb)
{
enum move_pos pos;
@ -976,7 +976,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb)
struct lim_aux_data *lim_data;
if (!loop_outer (bb->loop_father))
return;
return NULL;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Basic block %d (loop %d -- depth %d):\n\n",
@ -1094,6 +1094,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb)
if (lim_data->cost >= LIM_EXPENSIVE)
set_profitable_level (stmt);
}
return NULL;
}
class move_computations_dom_walker : public dom_walker
@ -1102,7 +1103,7 @@ public:
move_computations_dom_walker (cdi_direction direction)
: dom_walker (direction), todo_ (0) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
unsigned int todo_;
};
@ -1111,7 +1112,7 @@ public:
data stored in LIM_DATA structures associated with each statement. Callback
for walk_dominator_tree. */
void
edge
move_computations_dom_walker::before_dom_children (basic_block bb)
{
struct loop *level;
@ -1119,7 +1120,7 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
struct lim_aux_data *lim_data;
if (!loop_outer (bb->loop_father))
return;
return NULL;
for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); )
{
@ -1265,6 +1266,7 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
else
gsi_insert_on_edge (e, stmt);
}
return NULL;
}
/* Hoist the statements out of the loops prescribed by data stored in

View File

@ -1477,7 +1477,7 @@ public:
nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
: dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
@ -1496,7 +1496,7 @@ private:
};
/* Called by walk_dominator_tree, when entering the block BB. */
void
edge
nontrapping_dom_walker::before_dom_children (basic_block bb)
{
edge e;
@ -1529,6 +1529,7 @@ nontrapping_dom_walker::before_dom_children (basic_block bb)
add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), false);
}
}
return NULL;
}
/* Called by walk_dominator_tree, when basic block BB is exited. */

View File

@ -3906,7 +3906,7 @@ public:
eliminate_dom_walker (cdi_direction direction, bool do_pre_)
: dom_walker (direction), do_pre (do_pre_) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
bool do_pre;
@ -3914,7 +3914,7 @@ public:
/* Perform elimination for the basic-block B during the domwalk. */
void
edge
eliminate_dom_walker::before_dom_children (basic_block b)
{
/* Mark new bb. */
@ -4423,6 +4423,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
}
}
}
return NULL;
}
/* Make no longer available leaders no longer available. */

View File

@ -1123,7 +1123,7 @@ public:
BITMAP_FREE (need_eh_cleanup);
}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block) {}
ssa_prop_get_value_fn get_value_fn;
@ -1135,7 +1135,7 @@ public:
bitmap need_eh_cleanup;
};
void
edge
substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
{
/* Propagate known values into PHI nodes. */
@ -1293,6 +1293,7 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
fprintf (dump_file, "Not folded\n");
}
}
return NULL;
}

View File

@ -4208,11 +4208,10 @@ class sccvn_dom_walker : public dom_walker
{
public:
sccvn_dom_walker ()
: dom_walker (CDI_DOMINATORS), fail (false), unreachable_dom (NULL),
cond_stack (vNULL) {}
: dom_walker (CDI_DOMINATORS, true), fail (false), cond_stack (vNULL) {}
~sccvn_dom_walker ();
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
void record_cond (basic_block,
@ -4221,7 +4220,6 @@ public:
enum tree_code code, tree lhs, tree rhs, bool value);
bool fail;
basic_block unreachable_dom;
vec<std::pair <basic_block, std::pair <vn_nary_op_t, vn_nary_op_t> > >
cond_stack;
};
@ -4302,9 +4300,6 @@ sccvn_dom_walker::record_conds (basic_block bb,
void
sccvn_dom_walker::after_dom_children (basic_block bb)
{
if (unreachable_dom == bb)
unreachable_dom = NULL;
while (!cond_stack.is_empty ()
&& cond_stack.last ().first == bb)
{
@ -4319,56 +4314,14 @@ sccvn_dom_walker::after_dom_children (basic_block bb)
/* Value number all statements in BB. */
void
edge
sccvn_dom_walker::before_dom_children (basic_block bb)
{
edge e;
edge_iterator ei;
if (fail)
return;
/* If any of the predecessor edges that do not come from blocks dominated
by us are still marked as possibly executable consider this block
reachable. */
bool reachable = false;
if (!unreachable_dom)
{
reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun);
FOR_EACH_EDGE (e, ei, bb->preds)
if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
reachable |= (e->flags & EDGE_EXECUTABLE);
}
/* If the block is not reachable all outgoing edges are not
executable. Neither are incoming edges with src dominated by us. */
if (!reachable)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Marking all outgoing edges of unreachable "
"BB %d as not executable\n", bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
e->flags &= ~EDGE_EXECUTABLE;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Marking backedge from BB %d into "
"unreachable BB %d as not executable\n",
e->src->index, bb->index);
e->flags &= ~EDGE_EXECUTABLE;
}
}
/* Record the most dominating unreachable block. */
if (!unreachable_dom)
unreachable_dom = bb;
return;
}
return NULL;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Visiting BB %d\n", bb->index);
@ -4429,7 +4382,7 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
&& !DFS (res))
{
fail = true;
return;
return NULL;
}
}
for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
@ -4442,20 +4395,20 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
&& !DFS (op))
{
fail = true;
return;
return NULL;
}
}
/* Finally look at the last stmt. */
gimple *stmt = last_stmt (bb);
if (!stmt)
return;
return NULL;
enum gimple_code code = gimple_code (stmt);
if (code != GIMPLE_COND
&& code != GIMPLE_SWITCH
&& code != GIMPLE_GOTO)
return;
return NULL;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@ -4498,19 +4451,17 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
gcc_unreachable ();
}
if (!val)
return;
return NULL;
edge taken = find_taken_edge (bb, vn_valueize (val));
if (!taken)
return;
return NULL;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Marking all edges out of BB %d but (%d -> %d) as "
"not executable\n", bb->index, bb->index, taken->dest->index);
FOR_EACH_EDGE (e, ei, bb->succs)
if (e != taken)
e->flags &= ~EDGE_EXECUTABLE;
return taken;
}
/* Do SCCVN. Returns true if it finished, false if we bailed out
@ -4520,7 +4471,6 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
bool
run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
{
basic_block bb;
size_t i;
default_vn_walk_kind = default_vn_walk_kind_;
@ -4550,15 +4500,6 @@ run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
}
}
/* Mark all edges as possibly executable. */
FOR_ALL_BB_FN (bb, cfun)
{
edge_iterator ei;
edge e;
FOR_EACH_EDGE (e, ei, bb->succs)
e->flags |= EDGE_EXECUTABLE;
}
/* Walk all blocks in dominator order, value-numbering stmts
SSA defs and decide whether outgoing edges are not executable. */
sccvn_dom_walker walker;

View File

@ -2196,14 +2196,14 @@ class strlen_dom_walker : public dom_walker
public:
strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
/* Callback for walk_dominator_tree. Attempt to optimize various
string ops by remembering string lenths pointed by pointer SSA_NAMEs. */
void
edge
strlen_dom_walker::before_dom_children (basic_block bb)
{
basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
@ -2283,6 +2283,7 @@ strlen_dom_walker::before_dom_children (basic_block bb)
bb->aux = stridx_to_strinfo;
if (vec_safe_length (stridx_to_strinfo) && !strinfo_shared ())
(*stridx_to_strinfo)[0] = (strinfo *) bb;
return NULL;
}
/* Callback for walk_dominator_tree. Free strinfo vector if it is

View File

@ -303,7 +303,7 @@ class uncprop_dom_walker : public dom_walker
public:
uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
@ -433,7 +433,7 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
return retval;
}
void
edge
uncprop_dom_walker::before_dom_children (basic_block bb)
{
basic_block parent;
@ -462,6 +462,7 @@ uncprop_dom_walker::before_dom_children (basic_block bb)
m_equiv_stack.safe_push (NULL_TREE);
uncprop_into_successor_phis (bb);
return NULL;
}
namespace {