Commit 5120e0d8 by Richard Biener Committed by Richard Biener

tree-affine.c (expr_to_aff_combination): New function split out from...

2019-05-16  Richard Biener  <rguenther@suse.de>

	* tree-affine.c (expr_to_aff_combination): New function split
	out from...
	(tree_to_aff_combination): ... here.
	(aff_combination_expand): Avoid building a GENERIC tree.

From-SVN: r271294
parent f7430263
2019-05-16 Richard Biener <rguenther@suse.de>
* tree-affine.c (expr_to_aff_combination): New function split
out from...
(tree_to_aff_combination): ... here.
(aff_combination_expand): Avoid building a GENERIC tree.
2019-05-16 Max Filippov <jcmvbkbc@gmail.com> 2019-05-16 Max Filippov <jcmvbkbc@gmail.com>
* cgraphunit.c (cgraph_node::expand_thunk): Remove * cgraphunit.c (cgraph_node::expand_thunk): Remove
......
...@@ -259,104 +259,66 @@ aff_combination_convert (aff_tree *comb, tree type) ...@@ -259,104 +259,66 @@ aff_combination_convert (aff_tree *comb, tree type)
} }
} }
/* Splits EXPR into an affine combination of parts. */ /* Tries to handle OP0 CODE OP1 as affine combination of parts. Returns
true when that was successful and returns the combination in COMB. */
void static bool
tree_to_aff_combination (tree expr, tree type, aff_tree *comb) expr_to_aff_combination (aff_tree *comb, tree_code code, tree type,
tree op0, tree op1 = NULL_TREE)
{ {
aff_tree tmp; aff_tree tmp;
enum tree_code code;
tree cst, core, toffset;
poly_int64 bitpos, bitsize, bytepos; poly_int64 bitpos, bitsize, bytepos;
machine_mode mode;
int unsignedp, reversep, volatilep;
STRIP_NOPS (expr);
code = TREE_CODE (expr);
switch (code) switch (code)
{ {
case POINTER_PLUS_EXPR: case POINTER_PLUS_EXPR:
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb); tree_to_aff_combination (op0, type, comb);
tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp); tree_to_aff_combination (op1, sizetype, &tmp);
aff_combination_add (comb, &tmp); aff_combination_add (comb, &tmp);
return; return true;
case PLUS_EXPR: case PLUS_EXPR:
case MINUS_EXPR: case MINUS_EXPR:
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb); tree_to_aff_combination (op0, type, comb);
tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp); tree_to_aff_combination (op1, type, &tmp);
if (code == MINUS_EXPR) if (code == MINUS_EXPR)
aff_combination_scale (&tmp, -1); aff_combination_scale (&tmp, -1);
aff_combination_add (comb, &tmp); aff_combination_add (comb, &tmp);
return; return true;
case MULT_EXPR: case MULT_EXPR:
cst = TREE_OPERAND (expr, 1); if (TREE_CODE (op1) != INTEGER_CST)
if (TREE_CODE (cst) != INTEGER_CST)
break; break;
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb); tree_to_aff_combination (op0, type, comb);
aff_combination_scale (comb, wi::to_widest (cst)); aff_combination_scale (comb, wi::to_widest (op1));
return; return true;
case NEGATE_EXPR: case NEGATE_EXPR:
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb); tree_to_aff_combination (op0, type, comb);
aff_combination_scale (comb, -1); aff_combination_scale (comb, -1);
return; return true;
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
/* ~x = -x - 1 */ /* ~x = -x - 1 */
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb); tree_to_aff_combination (op0, type, comb);
aff_combination_scale (comb, -1); aff_combination_scale (comb, -1);
aff_combination_add_cst (comb, -1); aff_combination_add_cst (comb, -1);
return; return true;
case ADDR_EXPR:
/* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
{
expr = TREE_OPERAND (expr, 0);
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
aff_combination_add (comb, &tmp);
return;
}
core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
&toffset, &mode, &unsignedp, &reversep,
&volatilep);
if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos))
break;
aff_combination_const (comb, type, bytepos);
if (TREE_CODE (core) == MEM_REF)
{
tree mem_offset = TREE_OPERAND (core, 1);
aff_combination_add_cst (comb, wi::to_poly_widest (mem_offset));
core = TREE_OPERAND (core, 0);
}
else
core = build_fold_addr_expr (core);
if (TREE_CODE (core) == ADDR_EXPR)
aff_combination_add_elt (comb, core, 1);
else
{
tree_to_aff_combination (core, type, &tmp);
aff_combination_add (comb, &tmp);
}
if (toffset)
{
tree_to_aff_combination (toffset, type, &tmp);
aff_combination_add (comb, &tmp);
}
return;
CASE_CONVERT: CASE_CONVERT:
{ {
tree otype = TREE_TYPE (expr); tree otype = type;
tree inner = TREE_OPERAND (expr, 0); tree inner = op0;
tree itype = TREE_TYPE (inner); tree itype = TREE_TYPE (inner);
enum tree_code icode = TREE_CODE (inner); enum tree_code icode = TREE_CODE (inner);
/* STRIP_NOPS */
if (tree_nop_conversion_p (otype, itype))
{
tree_to_aff_combination (op0, type, comb);
return true;
}
/* In principle this is a valid folding, but it isn't necessarily /* In principle this is a valid folding, but it isn't necessarily
an optimization, so do it here and not in fold_unary. */ an optimization, so do it here and not in fold_unary. */
if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR) if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR)
...@@ -376,9 +338,7 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) ...@@ -376,9 +338,7 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
{ {
op0 = fold_convert (otype, op0); op0 = fold_convert (otype, op0);
op1 = fold_convert (otype, op1); op1 = fold_convert (otype, op1);
expr = fold_build2 (icode, otype, op0, op1); return expr_to_aff_combination (comb, icode, otype, op0, op1);
tree_to_aff_combination (expr, type, comb);
return;
} }
wide_int minv, maxv; wide_int minv, maxv;
/* If inner type has wrapping overflow behavior, fold conversion /* If inner type has wrapping overflow behavior, fold conversion
...@@ -399,15 +359,102 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) ...@@ -399,15 +359,102 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
{ {
op0 = fold_convert (otype, op0); op0 = fold_convert (otype, op0);
op1 = fold_convert (otype, op1); op1 = fold_convert (otype, op1);
expr = fold_build2 (MINUS_EXPR, otype, op0, op1); return expr_to_aff_combination (comb, MINUS_EXPR, otype,
tree_to_aff_combination (expr, type, comb); op0, op1);
return;
} }
} }
} }
} }
break; break;
default:;
}
return false;
}
/* Splits EXPR into an affine combination of parts. */
void
tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
{
aff_tree tmp;
enum tree_code code;
tree core, toffset;
poly_int64 bitpos, bitsize, bytepos;
machine_mode mode;
int unsignedp, reversep, volatilep;
STRIP_NOPS (expr);
code = TREE_CODE (expr);
switch (code)
{
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, 0),
TREE_OPERAND (expr, 1)))
return;
break;
case NEGATE_EXPR:
case BIT_NOT_EXPR:
if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, 0)))
return;
break;
CASE_CONVERT:
/* ??? TREE_TYPE (expr) should be equal to type here, but IVOPTS
calls this with not showing an outer widening cast. */
if (expr_to_aff_combination (comb, code,
TREE_TYPE (expr), TREE_OPERAND (expr, 0)))
{
aff_combination_convert (comb, type);
return;
}
break;
case ADDR_EXPR:
/* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
{
expr = TREE_OPERAND (expr, 0);
tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
aff_combination_add (comb, &tmp);
return;
}
core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
&toffset, &mode, &unsignedp, &reversep,
&volatilep);
if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos))
break;
aff_combination_const (comb, type, bytepos);
if (TREE_CODE (core) == MEM_REF)
{
tree mem_offset = TREE_OPERAND (core, 1);
aff_combination_add_cst (comb, wi::to_poly_widest (mem_offset));
core = TREE_OPERAND (core, 0);
}
else
core = build_fold_addr_expr (core);
if (TREE_CODE (core) == ADDR_EXPR)
aff_combination_add_elt (comb, core, 1);
else
{
tree_to_aff_combination (core, type, &tmp);
aff_combination_add (comb, &tmp);
}
if (toffset)
{
tree_to_aff_combination (toffset, type, &tmp);
aff_combination_add (comb, &tmp);
}
return;
default: default:
{ {
if (poly_int_tree_p (expr)) if (poly_int_tree_p (expr))
...@@ -665,7 +712,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED, ...@@ -665,7 +712,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
{ {
unsigned i; unsigned i;
aff_tree to_add, current, curre; aff_tree to_add, current, curre;
tree e, rhs; tree e;
gimple *def; gimple *def;
widest_int scale; widest_int scale;
struct name_expansion *exp; struct name_expansion *exp;
...@@ -715,20 +762,38 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED, ...@@ -715,20 +762,38 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
case PLUS_EXPR: case PLUS_EXPR:
case MINUS_EXPR: case MINUS_EXPR:
case MULT_EXPR: case MULT_EXPR:
if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
gimple_assign_rhs1 (def),
gimple_assign_rhs2 (def)))
continue;
break;
case NEGATE_EXPR: case NEGATE_EXPR:
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
gimple_assign_rhs1 (def)))
continue;
break;
CASE_CONVERT: CASE_CONVERT:
rhs = gimple_assign_rhs_to_tree (def); if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
gimple_assign_rhs1 (def)))
/* This makes us always expand conversions which we did
in the past and makes gcc.dg/tree-ssa/ivopts-lt-2.c
PASS, eliminating one induction variable in IVOPTs.
??? But it is really excessive and we should try
harder to do without it. */
aff_combination_elt (&current, TREE_TYPE (name),
fold_convert (TREE_TYPE (name),
gimple_assign_rhs1 (def)));
break; break;
case ADDR_EXPR: case ADDR_EXPR:
case INTEGER_CST: case INTEGER_CST:
case POLY_INT_CST: case POLY_INT_CST:
rhs = gimple_assign_rhs1 (def); tree_to_aff_combination (gimple_assign_rhs1 (def),
TREE_TYPE (name), &current);
break; break;
default: default:
continue; continue;
} }
tree_to_aff_combination (rhs, TREE_TYPE (name), &current);
exp = XNEW (struct name_expansion); exp = XNEW (struct name_expansion);
exp->in_progress = 1; exp->in_progress = 1;
if (!*cache) if (!*cache)
......
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