Commit c3dd8dd7 by Richard Biener Committed by Richard Biener

re PR tree-optimization/55124 (ICE in find_or_generate_expression, at tree-ssa-pre.c:2803)

2012-12-04  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/55124
	* tree-ssa-pre.c (find_or_generate_expression): Instead of
	ICEing when we are not able to generate an expression defer it
	by signalling failure.  Fix possible wrong-code issue by
	not picking random REFERENCE expressions as fallback.
	(create_component_ref_by_pieces_1): Adjust.  Add failure paths.
	(create_expression_by_pieces): Likewise.
	(insert_into_preds_of_block): When expression generation failed
	for one edge make sure to not insert a PHI node.

	* gcc.dg/torture/pr55124.c: New testcase.

From-SVN: r194125
parent f2b2ead4
2012-12-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/55124
* tree-ssa-pre.c (find_or_generate_expression): Instead of
ICEing when we are not able to generate an expression defer it
by signalling failure. Fix possible wrong-code issue by
not picking random REFERENCE expressions as fallback.
(create_component_ref_by_pieces_1): Adjust. Add failure paths.
(create_expression_by_pieces): Likewise.
(insert_into_preds_of_block): When expression generation failed
for one edge make sure to not insert a PHI node.
2012-12-03 Eric Botcazou <ebotcazou@adacore.com> 2012-12-03 Eric Botcazou <ebotcazou@adacore.com>
* config/ia64/ia64.c (ia64_compute_frame_size): Allocate the scratch * config/ia64/ia64.c (ia64_compute_frame_size): Allocate the scratch
2012-12-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/55124
* gcc.dg/torture/pr55124.c: New testcase.
2012-12-03 Tobias Burnus <burnus@net-b.de> 2012-12-03 Tobias Burnus <burnus@net-b.de>
* gfortran.dg/quad_3.f90: New. * gfortran.dg/quad_3.f90: New.
......
/* { dg-do compile } */
int a, b;
long c;
void f2(void)
{
unsigned long k = 1;
foo(b ? k = 0 : 0);
b = ((c = b) ? (k ? : (c = 0)) : a) * c;
}
void f1(void)
{
f2();
a = b | c;
}
...@@ -2564,13 +2564,21 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2564,13 +2564,21 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
fn = currop->op0; fn = currop->op0;
else else
fn = find_or_generate_expression (block, currop->op0, stmts); fn = find_or_generate_expression (block, currop->op0, stmts);
if (!fn)
return NULL_TREE;
if (currop->op1) if (currop->op1)
sc = find_or_generate_expression (block, currop->op1, stmts); {
sc = find_or_generate_expression (block, currop->op1, stmts);
if (!sc)
return NULL_TREE;
}
args = XNEWVEC (tree, ref->operands.length () - 1); args = XNEWVEC (tree, ref->operands.length () - 1);
while (*operand < ref->operands.length ()) while (*operand < ref->operands.length ())
{ {
args[nargs] = create_component_ref_by_pieces_1 (block, ref, args[nargs] = create_component_ref_by_pieces_1 (block, ref,
operand, stmts); operand, stmts);
if (!args[nargs])
return NULL_TREE;
nargs++; nargs++;
} }
folded = build_call_array (currop->type, folded = build_call_array (currop->type,
...@@ -2587,6 +2595,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2587,6 +2595,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
{ {
tree baseop = create_component_ref_by_pieces_1 (block, ref, operand, tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
stmts); stmts);
if (!baseop)
return NULL_TREE;
tree offset = currop->op0; tree offset = currop->op0;
if (TREE_CODE (baseop) == ADDR_EXPR if (TREE_CODE (baseop) == ADDR_EXPR
&& handled_component_p (TREE_OPERAND (baseop, 0))) && handled_component_p (TREE_OPERAND (baseop, 0)))
...@@ -2610,10 +2620,20 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2610,10 +2620,20 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
vn_reference_op_t nextop = &ref->operands[++*operand]; vn_reference_op_t nextop = &ref->operands[++*operand];
tree baseop = create_component_ref_by_pieces_1 (block, ref, operand, tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
stmts); stmts);
if (!baseop)
return NULL_TREE;
if (currop->op0) if (currop->op0)
genop0 = find_or_generate_expression (block, currop->op0, stmts); {
genop0 = find_or_generate_expression (block, currop->op0, stmts);
if (!genop0)
return NULL_TREE;
}
if (nextop->op0) if (nextop->op0)
genop1 = find_or_generate_expression (block, nextop->op0, stmts); {
genop1 = find_or_generate_expression (block, nextop->op0, stmts);
if (!genop1)
return NULL_TREE;
}
return build5 (TARGET_MEM_REF, currop->type, return build5 (TARGET_MEM_REF, currop->type,
baseop, currop->op2, genop0, currop->op1, genop1); baseop, currop->op2, genop0, currop->op1, genop1);
} }
...@@ -2629,8 +2649,10 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2629,8 +2649,10 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
case IMAGPART_EXPR: case IMAGPART_EXPR:
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
{ {
tree genop0 = create_component_ref_by_pieces_1 (block, ref, tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
operand, stmts); stmts);
if (!genop0)
return NULL_TREE;
return fold_build1 (currop->opcode, currop->type, genop0); return fold_build1 (currop->opcode, currop->type, genop0);
} }
...@@ -2638,7 +2660,11 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2638,7 +2660,11 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
{ {
tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand, tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
stmts); stmts);
if (!genop0)
return NULL_TREE;
tree genop1 = find_or_generate_expression (block, currop->op0, stmts); tree genop1 = find_or_generate_expression (block, currop->op0, stmts);
if (!genop1)
return NULL_TREE;
return fold_build2 (currop->opcode, currop->type, genop0, genop1); return fold_build2 (currop->opcode, currop->type, genop0, genop1);
} }
...@@ -2646,6 +2672,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2646,6 +2672,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
{ {
tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand, tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
stmts); stmts);
if (!genop0)
return NULL_TREE;
tree op1 = currop->op0; tree op1 = currop->op0;
tree op2 = currop->op1; tree op2 = currop->op1;
return fold_build3 (BIT_FIELD_REF, currop->type, genop0, op1, op2); return fold_build3 (BIT_FIELD_REF, currop->type, genop0, op1, op2);
...@@ -2661,8 +2689,13 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2661,8 +2689,13 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
tree genop1 = currop->op0; tree genop1 = currop->op0;
tree genop2 = currop->op1; tree genop2 = currop->op1;
tree genop3 = currop->op2; tree genop3 = currop->op2;
genop0 = create_component_ref_by_pieces_1 (block, ref, operand, stmts); genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
stmts);
if (!genop0)
return NULL_TREE;
genop1 = find_or_generate_expression (block, genop1, stmts); genop1 = find_or_generate_expression (block, genop1, stmts);
if (!genop1)
return NULL_TREE;
if (genop2) if (genop2)
{ {
tree domain_type = TYPE_DOMAIN (TREE_TYPE (genop0)); tree domain_type = TYPE_DOMAIN (TREE_TYPE (genop0));
...@@ -2672,7 +2705,11 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2672,7 +2705,11 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
|| integer_zerop (TYPE_MIN_VALUE (domain_type)))) || integer_zerop (TYPE_MIN_VALUE (domain_type))))
genop2 = NULL_TREE; genop2 = NULL_TREE;
else else
genop2 = find_or_generate_expression (block, genop2, stmts); {
genop2 = find_or_generate_expression (block, genop2, stmts);
if (!genop2)
return NULL_TREE;
}
} }
if (genop3) if (genop3)
{ {
...@@ -2688,6 +2725,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2688,6 +2725,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
genop3 = size_binop (EXACT_DIV_EXPR, genop3, genop3 = size_binop (EXACT_DIV_EXPR, genop3,
size_int (TYPE_ALIGN_UNIT (elmt_type))); size_int (TYPE_ALIGN_UNIT (elmt_type)));
genop3 = find_or_generate_expression (block, genop3, stmts); genop3 = find_or_generate_expression (block, genop3, stmts);
if (!genop3)
return NULL_TREE;
} }
} }
return build4 (currop->opcode, currop->type, genop0, genop1, return build4 (currop->opcode, currop->type, genop0, genop1,
...@@ -2699,10 +2738,16 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, ...@@ -2699,10 +2738,16 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
tree op1; tree op1;
tree genop2 = currop->op1; tree genop2 = currop->op1;
op0 = create_component_ref_by_pieces_1 (block, ref, operand, stmts); op0 = create_component_ref_by_pieces_1 (block, ref, operand, stmts);
if (!op0)
return NULL_TREE;
/* op1 should be a FIELD_DECL, which are represented by themselves. */ /* op1 should be a FIELD_DECL, which are represented by themselves. */
op1 = currop->op0; op1 = currop->op0;
if (genop2) if (genop2)
genop2 = find_or_generate_expression (block, genop2, stmts); {
genop2 = find_or_generate_expression (block, genop2, stmts);
if (!genop2)
return NULL_TREE;
}
return fold_build3 (COMPONENT_REF, TREE_TYPE (op1), op0, op1, genop2); return fold_build3 (COMPONENT_REF, TREE_TYPE (op1), op0, op1, genop2);
} }
...@@ -2749,18 +2794,11 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref, ...@@ -2749,18 +2794,11 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
return create_component_ref_by_pieces_1 (block, ref, &op, stmts); return create_component_ref_by_pieces_1 (block, ref, &op, stmts);
} }
/* Find a leader for an expression, or generate one using /* Find a simple leader for an expression, or generate one using
create_expression_by_pieces if it's ANTIC but create_expression_by_pieces from a NARY expression for the value.
complex.
BLOCK is the basic_block we are looking for leaders in. BLOCK is the basic_block we are looking for leaders in.
OP is the tree expression to find a leader for or generate. OP is the tree expression to find a leader for or generate.
STMTS is the statement list to put the inserted expressions on. Returns the leader or NULL_TREE on failure. */
Returns the SSA_NAME of the LHS of the generated expression or the
leader.
DOMSTMT if non-NULL is a statement that should be dominated by
all uses in the generated expression. If DOMSTMT is non-NULL this
routine can fail and return NULL_TREE. Otherwise it will assert
on failure. */
static tree static tree
find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts) find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts)
...@@ -2774,21 +2812,30 @@ find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts) ...@@ -2774,21 +2812,30 @@ find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts)
return PRE_EXPR_NAME (leader); return PRE_EXPR_NAME (leader);
else if (leader->kind == CONSTANT) else if (leader->kind == CONSTANT)
return PRE_EXPR_CONSTANT (leader); return PRE_EXPR_CONSTANT (leader);
/* Defer. */
return NULL_TREE;
} }
/* It must be a complex expression, so generate it recursively. */ /* It must be a complex expression, so generate it recursively. Note
that this is only necessary to handle gcc.dg/tree-ssa/ssa-pre28.c
where the insert algorithm fails to insert a required expression. */
bitmap exprset = value_expressions[lookfor]; bitmap exprset = value_expressions[lookfor];
bitmap_iterator bi; bitmap_iterator bi;
unsigned int i; unsigned int i;
EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi) EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi)
{ {
pre_expr temp = expression_for_id (i); pre_expr temp = expression_for_id (i);
if (temp->kind != NAME) /* We cannot insert random REFERENCE expressions at arbitrary
places. We can insert NARYs which eventually re-materializes
its operand values. */
if (temp->kind == NARY)
return create_expression_by_pieces (block, temp, stmts, return create_expression_by_pieces (block, temp, stmts,
get_expr_type (expr)); get_expr_type (expr));
} }
gcc_unreachable (); /* Defer. */
return NULL_TREE;
} }
#define NECESSARY GF_PLF_1 #define NECESSARY GF_PLF_1
...@@ -2801,15 +2848,13 @@ find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts) ...@@ -2801,15 +2848,13 @@ find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts)
This function will die if we hit some value that shouldn't be This function will die if we hit some value that shouldn't be
ANTIC but is (IE there is no leader for it, or its components). ANTIC but is (IE there is no leader for it, or its components).
The function returns NULL_TREE in case a different antic expression
has to be inserted first.
This function may also generate expressions that are themselves This function may also generate expressions that are themselves
partially or fully redundant. Those that are will be either made partially or fully redundant. Those that are will be either made
fully redundant during the next iteration of insert (for partially fully redundant during the next iteration of insert (for partially
redundant ones), or eliminated by eliminate (for fully redundant redundant ones), or eliminated by eliminate (for fully redundant
ones). ones). */
If DOMSTMT is non-NULL then we make sure that all uses in the
expressions dominate that statement. In this case the function
can return NULL_TREE to signal failure. */
static tree static tree
create_expression_by_pieces (basic_block block, pre_expr expr, create_expression_by_pieces (basic_block block, pre_expr expr,
...@@ -2838,6 +2883,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr, ...@@ -2838,6 +2883,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
{ {
vn_reference_t ref = PRE_EXPR_REFERENCE (expr); vn_reference_t ref = PRE_EXPR_REFERENCE (expr);
folded = create_component_ref_by_pieces (block, ref, stmts); folded = create_component_ref_by_pieces (block, ref, stmts);
if (!folded)
return NULL_TREE;
} }
break; break;
case NARY: case NARY:
...@@ -2848,6 +2895,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr, ...@@ -2848,6 +2895,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
for (i = 0; i < nary->length; ++i) for (i = 0; i < nary->length; ++i)
{ {
genop[i] = find_or_generate_expression (block, nary->op[i], stmts); genop[i] = find_or_generate_expression (block, nary->op[i], stmts);
if (!genop[i])
return NULL_TREE;
/* Ensure genop[] is properly typed for POINTER_PLUS_EXPR. It /* Ensure genop[] is properly typed for POINTER_PLUS_EXPR. It
may have conversions stripped. */ may have conversions stripped. */
if (nary->opcode == POINTER_PLUS_EXPR) if (nary->opcode == POINTER_PLUS_EXPR)
...@@ -3085,6 +3134,13 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum, ...@@ -3085,6 +3134,13 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
&stmts, type); &stmts, type);
gcc_assert (!(pred->flags & EDGE_ABNORMAL)); gcc_assert (!(pred->flags & EDGE_ABNORMAL));
gsi_insert_seq_on_edge (pred, stmts); gsi_insert_seq_on_edge (pred, stmts);
if (!builtexpr)
{
/* We cannot insert a PHI node if we failed to insert
on one edge. */
nophi = true;
continue;
}
avail[pred->dest_idx] = get_or_alloc_expr_for_name (builtexpr); avail[pred->dest_idx] = get_or_alloc_expr_for_name (builtexpr);
insertions = true; insertions = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment