Commit 8eaa0f34 by Zdenek Dvorak Committed by Zdenek Dvorak

tree-ssa-phiopt.c (minmax_replacement, [...]): New functions.

	* tree-ssa-phiopt.c (minmax_replacement, blocks_in_phiopt_order):
	New functions.
	(tree_ssa_phiopt): Use blocks_in_phiopt_order and minmax_replacement.
	Remove unused removed_phis variable.
	(conditional_replacement): Use build1/build2.
	(abs_replacement): Use last_and_only_stmt and build1/build2.

	* gcc.dg/tree-ssa/phi-opt-5.c: New test.

From-SVN: r96439
parent dcd6de6d
2005-03-14 Zdenek Dvorak <dvorakz@suse.cz> 2005-03-14 Zdenek Dvorak <dvorakz@suse.cz>
* tree-ssa-phiopt.c (minmax_replacement, blocks_in_phiopt_order):
New functions.
(tree_ssa_phiopt): Use blocks_in_phiopt_order and minmax_replacement.
Remove unused removed_phis variable.
(conditional_replacement): Use build1/build2.
(abs_replacement): Use last_and_only_stmt and build1/build2.
2005-03-14 Zdenek Dvorak <dvorakz@suse.cz>
* builtin-attrs.def (ATTR_NOVOPS, ATTR_NOVOPS_LIST, * builtin-attrs.def (ATTR_NOVOPS, ATTR_NOVOPS_LIST,
ATTR_PURE_NOTHROW_NOVOPS_LIST): New. ATTR_PURE_NOTHROW_NOVOPS_LIST): New.
* builtins.def (ATTR_MATHFN_FPROUNDING): Use NOVOPS. * builtins.def (ATTR_MATHFN_FPROUNDING): Use NOVOPS.
......
2005-03-14 Zdenek Dvorak <dvorakz@suse.cz> 2005-03-14 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/phi-opt-5.c: New test.
2005-03-14 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/20050314-1.c: New test. * gcc.dg/tree-ssa/20050314-1.c: New test.
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
......
/* { dg-do compile } */
/* { dg-options "-O1 -ffinite-math-only -fdump-tree-phiopt1" } */
float repl1 (float varx)
{
if (varx < 0.0)
return 0.0;
else if (varx > 1.0)
return 1.0;
else
return varx;
}
/* Should be turned to
varx_4 = MIN_EXPR <1.0e+0, varx_2>;
varx_5 = MAX_EXPR <varx_4, 0.0>; */
/* { dg-final { scan-tree-dump "varx.*MIN_EXPR.*1\\.0" "phiopt1"} } */
/* { dg-final { scan-tree-dump "varx.*MAX_EXPR.*0\\.0" "phiopt1"} } */
float repl2 (float vary)
{
if (vary > 1.0)
return 1.0;
else if (vary < 0.0)
return 0.0;
else
return vary;
}
/* Should be turned to
vary_4 = MAX_EXPR <0.0, vary_2>;
vary_5 = MIN_EXPR <vary_4, 1.0e+0>; */
/* { dg-final { scan-tree-dump "vary.*MAX_EXPR.*0\\.0" "phiopt1"} } */
/* { dg-final { scan-tree-dump "vary.*MIN_EXPR.*1\\.0" "phiopt1"} } */
float repl3 (float varz, float vara, float varb)
{
if (varz > vara)
return vara;
else if (varz < varb)
return varb;
else
return varz;
}
/* Should be turned to
if (varz_2 > vara_3) goto <L4>; else goto <L1>;
<L1>:;
vara_6 = MAX_EXPR <varb_5, varz_2>; */
/* { dg-final { scan-tree-dump "if .*varz" "phiopt1"} } */
/* { dg-final { scan-tree-dump "vara.*MAX_EXPR" "phiopt1"} } */
...@@ -41,10 +41,13 @@ static bool conditional_replacement (basic_block, basic_block, basic_block, ...@@ -41,10 +41,13 @@ static bool conditional_replacement (basic_block, basic_block, basic_block,
edge, edge, tree, tree, tree); edge, edge, tree, tree, tree);
static bool value_replacement (basic_block, basic_block, basic_block, static bool value_replacement (basic_block, basic_block, basic_block,
edge, edge, tree, tree, tree); edge, edge, tree, tree, tree);
static bool minmax_replacement (basic_block, basic_block, basic_block,
edge, edge, tree, tree, tree);
static bool abs_replacement (basic_block, basic_block, basic_block, static bool abs_replacement (basic_block, basic_block, basic_block,
edge, edge, tree, tree, tree); edge, edge, tree, tree, tree);
static void replace_phi_edge_with_variable (basic_block, basic_block, edge, static void replace_phi_edge_with_variable (basic_block, basic_block, edge,
tree, tree); tree, tree);
static basic_block *blocks_in_phiopt_order (void);
/* This pass eliminates PHI nodes which can be trivially implemented as /* This pass eliminates PHI nodes which can be trivially implemented as
an assignment from a conditional expression. i.e. if we have something an assignment from a conditional expression. i.e. if we have something
...@@ -102,6 +105,21 @@ static void replace_phi_edge_with_variable (basic_block, basic_block, edge, ...@@ -102,6 +105,21 @@ static void replace_phi_edge_with_variable (basic_block, basic_block, edge,
bb2: bb2:
x = ABS_EXPR< a >; x = ABS_EXPR< a >;
Similarly,
bb0:
if (a <= b) goto bb2; else goto bb1;
bb1:
goto bb2;
bb2:
x = PHI (b (bb1), a (bb0));
Becomes
x = MIN_EXPR (a, b)
And the same transformation for MAX_EXPR.
bb1 will become unreachable and bb0 and bb2 will almost always be merged bb1 will become unreachable and bb0 and bb2 will almost always be merged
into a single block. Similar transformations are done by the ifcvt into a single block. Similar transformations are done by the ifcvt
RTL optimizer. */ RTL optimizer. */
...@@ -110,15 +128,28 @@ static void ...@@ -110,15 +128,28 @@ static void
tree_ssa_phiopt (void) tree_ssa_phiopt (void)
{ {
basic_block bb; basic_block bb;
basic_block *bb_order;
unsigned n, i;
/* Search every basic block for COND_EXPR we may be able to optimize.
We walk the blocks in order that guarantees that a block with
a single predecessor is processed before the predecessor.
This ensures that we collapse inner ifs before visiting the
outer ones, and also that we do not try to visit a removed
block. */
bb_order = blocks_in_phiopt_order ();
n = n_basic_blocks;
/* Search every basic block for COND_EXPR we may be able to optimize for (i = 0; i < n; i++)
in reverse order so we can find more. */
FOR_EACH_BB_REVERSE (bb)
{ {
tree cond_expr; tree cond_expr;
tree phi; tree phi;
basic_block bb1, bb2; basic_block bb1, bb2;
edge e1, e2; edge e1, e2;
tree arg0, arg1;
bb = bb_order[i];
cond_expr = last_stmt (bb); cond_expr = last_stmt (bb);
/* Check to see if the last statement is a COND_EXPR. */ /* Check to see if the last statement is a COND_EXPR. */
...@@ -174,25 +205,80 @@ tree_ssa_phiopt (void) ...@@ -174,25 +205,80 @@ tree_ssa_phiopt (void)
/* Check to make sure that there is only one PHI node. /* Check to make sure that there is only one PHI node.
TODO: we could do it with more than one iff the other PHI nodes TODO: we could do it with more than one iff the other PHI nodes
have the same elements for these two edges. */ have the same elements for these two edges. */
if (phi && PHI_CHAIN (phi) == NULL) if (!phi || PHI_CHAIN (phi) != NULL)
{ continue;
tree arg0 = NULL, arg1 = NULL;
arg0 = PHI_ARG_DEF_TREE (phi, e1->dest_idx); arg0 = PHI_ARG_DEF_TREE (phi, e1->dest_idx);
arg1 = PHI_ARG_DEF_TREE (phi, e2->dest_idx); arg1 = PHI_ARG_DEF_TREE (phi, e2->dest_idx);
/* We know something is wrong if we cannot find the edges in the PHI /* We know something is wrong if we cannot find the edges in the PHI
node. */ node. */
gcc_assert (arg0 != NULL && arg1 != NULL); gcc_assert (arg0 != NULL && arg1 != NULL);
/* Do the replacement of conditional if it can be done. */ /* Do the replacement of conditional if it can be done. */
if (conditional_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1) if (conditional_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1))
|| value_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1) ;
|| abs_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1)) else if (value_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1))
{ ;
} else if (abs_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1))
;
else
minmax_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1);
}
free (bb_order);
}
/* Returns the list of basic blocks in the function in an order that guarantees
that if a block X has just a single predecessor Y, then Y is after X in the
ordering. */
static basic_block *
blocks_in_phiopt_order (void)
{
basic_block x, y;
basic_block *order = xmalloc (sizeof (basic_block) * n_basic_blocks);
unsigned n = n_basic_blocks, np, i;
sbitmap visited = sbitmap_alloc (last_basic_block + 2);
#define MARK_VISITED(BB) (SET_BIT (visited, (BB)->index + 2))
#define VISITED_P(BB) (TEST_BIT (visited, (BB)->index + 2))
sbitmap_zero (visited);
MARK_VISITED (ENTRY_BLOCK_PTR);
FOR_EACH_BB (x)
{
if (VISITED_P (x))
continue;
/* Walk the predecessors of x as long as they have precisely one
predecessor and add them to the list, so that they get stored
after x. */
for (y = x, np = 1;
single_pred_p (y) && !VISITED_P (single_pred (y));
y = single_pred (y))
np++;
for (y = x, i = n - np;
single_pred_p (y) && !VISITED_P (single_pred (y));
y = single_pred (y), i++)
{
order[i] = y;
MARK_VISITED (y);
} }
order[i] = y;
MARK_VISITED (y);
gcc_assert (i == n - 1);
n -= np;
} }
sbitmap_free (visited);
gcc_assert (n == 0);
return order;
#undef MARK_VISITED
#undef VISITED_P
} }
/* Return TRUE if block BB has no executable statements, otherwise return /* Return TRUE if block BB has no executable statements, otherwise return
...@@ -324,11 +410,11 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -324,11 +410,11 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
if (!COMPARISON_CLASS_P (old_result)) if (!COMPARISON_CLASS_P (old_result))
return false; return false;
new1 = build (TREE_CODE (old_result), TREE_TYPE (old_result), new1 = build2 (TREE_CODE (old_result), TREE_TYPE (old_result),
TREE_OPERAND (old_result, 0), TREE_OPERAND (old_result, 0),
TREE_OPERAND (old_result, 1)); TREE_OPERAND (old_result, 1));
new1 = build (MODIFY_EXPR, TREE_TYPE (old_result), new_var, new1); new1 = build2 (MODIFY_EXPR, TREE_TYPE (old_result), new_var, new1);
bsi_insert_after (&bsi, new1, BSI_NEW_STMT); bsi_insert_after (&bsi, new1, BSI_NEW_STMT);
} }
...@@ -357,7 +443,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -357,7 +443,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
|| (e1 == true_edge && integer_onep (arg1)) || (e1 == true_edge && integer_onep (arg1))
|| (e1 == false_edge && integer_zerop (arg1))) || (e1 == false_edge && integer_zerop (arg1)))
{ {
new = build (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond); new = build2 (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond);
} }
else else
{ {
...@@ -379,7 +465,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -379,7 +465,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
{ {
tree temp = TREE_OPERAND (cond, 0); tree temp = TREE_OPERAND (cond, 0);
tree new_var_1 = make_rename_temp (TREE_TYPE (temp), NULL); tree new_var_1 = make_rename_temp (TREE_TYPE (temp), NULL);
new = build (MODIFY_EXPR, TREE_TYPE (new_var_1), new_var_1, temp); new = build2 (MODIFY_EXPR, TREE_TYPE (new_var_1), new_var_1, temp);
bsi_insert_after (&bsi, new, BSI_NEW_STMT); bsi_insert_after (&bsi, new, BSI_NEW_STMT);
cond = fold_convert (TREE_TYPE (result), new_var_1); cond = fold_convert (TREE_TYPE (result), new_var_1);
} }
...@@ -391,7 +477,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -391,7 +477,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
return false; return false;
} }
new = build (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond); new = build2 (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond);
} }
bsi_insert_after (&bsi, new, BSI_NEW_STMT); bsi_insert_after (&bsi, new, BSI_NEW_STMT);
...@@ -482,6 +568,257 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -482,6 +568,257 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
return false; return false;
} }
/* The function minmax_replacement does the main work of doing the minmax
replacement. Return true if the replacement is done. Otherwise return
false.
BB is the basic block where the replacement is going to be done on. ARG0
is argument 0 from the PHI. Likewise for ARG1. */
static bool
minmax_replacement (basic_block cond_bb, basic_block middle_bb,
basic_block phi_bb, edge e0, edge e1, tree phi,
tree arg0, tree arg1)
{
tree result, type;
tree cond, new;
edge true_edge, false_edge;
enum tree_code cmp, minmax, ass_code;
tree smaller, larger, arg_true, arg_false;
block_stmt_iterator bsi, bsi_from;
type = TREE_TYPE (PHI_RESULT (phi));
/* The optimization may be unsafe due to NaNs. */
if (HONOR_NANS (TYPE_MODE (type)))
return false;
cond = COND_EXPR_COND (last_stmt (cond_bb));
cmp = TREE_CODE (cond);
result = PHI_RESULT (phi);
/* This transformation is only valid for order comparisons. Record which
operand is smaller/larger if the result of the comparison is true. */
if (cmp == LT_EXPR || cmp == LE_EXPR)
{
smaller = TREE_OPERAND (cond, 0);
larger = TREE_OPERAND (cond, 1);
}
else if (cmp == GT_EXPR || cmp == GE_EXPR)
{
smaller = TREE_OPERAND (cond, 1);
larger = TREE_OPERAND (cond, 0);
}
else
return false;
/* We need to know which is the true edge and which is the false
edge so that we know if have abs or negative abs. */
extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
/* Forward the edges over the middle basic block. */
if (true_edge->dest == middle_bb)
true_edge = EDGE_SUCC (true_edge->dest, 0);
if (false_edge->dest == middle_bb)
false_edge = EDGE_SUCC (false_edge->dest, 0);
if (true_edge == e0)
{
gcc_assert (false_edge == e1);
arg_true = arg0;
arg_false = arg1;
}
else
{
gcc_assert (false_edge == e0);
gcc_assert (true_edge == e1);
arg_true = arg1;
arg_false = arg0;
}
if (empty_block_p (middle_bb))
{
if (operand_equal_for_phi_arg_p (arg_true, smaller)
&& operand_equal_for_phi_arg_p (arg_false, larger))
{
/* Case
if (smaller < larger)
rslt = smaller;
else
rslt = larger; */
minmax = MIN_EXPR;
}
else if (operand_equal_for_phi_arg_p (arg_false, smaller)
&& operand_equal_for_phi_arg_p (arg_true, larger))
minmax = MAX_EXPR;
else
return false;
}
else
{
/* Recognize the following case, assuming d <= u:
if (a <= u)
b = MAX (a, d);
x = PHI <b, u>
This is equivalent to
b = MAX (a, d);
x = MIN (b, u); */
tree assign = last_and_only_stmt (middle_bb);
tree lhs, rhs, op0, op1, bound;
if (!assign
|| TREE_CODE (assign) != MODIFY_EXPR)
return false;
lhs = TREE_OPERAND (assign, 0);
rhs = TREE_OPERAND (assign, 1);
ass_code = TREE_CODE (rhs);
if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
return false;
op0 = TREE_OPERAND (rhs, 0);
op1 = TREE_OPERAND (rhs, 1);
if (true_edge->src == middle_bb)
{
/* We got here if the condition is true, i.e., SMALLER < LARGER. */
if (!operand_equal_for_phi_arg_p (lhs, arg_true))
return false;
if (operand_equal_for_phi_arg_p (arg_false, larger))
{
/* Case
if (smaller < larger)
{
r' = MAX_EXPR (smaller, bound)
}
r = PHI <r', larger> --> to be turned to MIN_EXPR. */
if (ass_code != MAX_EXPR)
return false;
minmax = MIN_EXPR;
if (operand_equal_for_phi_arg_p (op0, smaller))
bound = op1;
else if (operand_equal_for_phi_arg_p (op1, smaller))
bound = op0;
else
return false;
/* We need BOUND <= LARGER. */
if (!integer_nonzerop (fold (build2 (LE_EXPR, boolean_type_node,
bound, larger))))
return false;
}
else if (operand_equal_for_phi_arg_p (arg_false, smaller))
{
/* Case
if (smaller < larger)
{
r' = MIN_EXPR (larger, bound)
}
r = PHI <r', smaller> --> to be turned to MAX_EXPR. */
if (ass_code != MIN_EXPR)
return false;
minmax = MAX_EXPR;
if (operand_equal_for_phi_arg_p (op0, larger))
bound = op1;
else if (operand_equal_for_phi_arg_p (op1, larger))
bound = op0;
else
return false;
/* We need BOUND >= SMALLER. */
if (!integer_nonzerop (fold (build2 (GE_EXPR, boolean_type_node,
bound, smaller))))
return false;
}
else
return false;
}
else
{
/* We got here if the condition is false, i.e., SMALLER > LARGER. */
if (!operand_equal_for_phi_arg_p (lhs, arg_false))
return false;
if (operand_equal_for_phi_arg_p (arg_true, larger))
{
/* Case
if (smaller > larger)
{
r' = MIN_EXPR (smaller, bound)
}
r = PHI <r', larger> --> to be turned to MAX_EXPR. */
if (ass_code != MIN_EXPR)
return false;
minmax = MAX_EXPR;
if (operand_equal_for_phi_arg_p (op0, smaller))
bound = op1;
else if (operand_equal_for_phi_arg_p (op1, smaller))
bound = op0;
else
return false;
/* We need BOUND >= LARGER. */
if (!integer_nonzerop (fold (build2 (GE_EXPR, boolean_type_node,
bound, larger))))
return false;
}
else if (operand_equal_for_phi_arg_p (arg_true, smaller))
{
/* Case
if (smaller > larger)
{
r' = MAX_EXPR (larger, bound)
}
r = PHI <r', smaller> --> to be turned to MIN_EXPR. */
if (ass_code != MAX_EXPR)
return false;
minmax = MIN_EXPR;
if (operand_equal_for_phi_arg_p (op0, larger))
bound = op1;
else if (operand_equal_for_phi_arg_p (op1, larger))
bound = op0;
else
return false;
/* We need BOUND <= SMALLER. */
if (!integer_nonzerop (fold (build2 (LE_EXPR, boolean_type_node,
bound, smaller))))
return false;
}
else
return false;
}
/* Move the statement from the middle block. */
bsi = bsi_last (cond_bb);
bsi_from = bsi_last (middle_bb);
bsi_move_before (&bsi_from, &bsi);
}
/* Emit the statement to compute min/max. */
result = duplicate_ssa_name (PHI_RESULT (phi), NULL);
new = build2 (MODIFY_EXPR, type, result,
build2 (minmax, type, arg0, arg1));
SSA_NAME_DEF_STMT (result) = new;
bsi = bsi_last (cond_bb);
bsi_insert_before (&bsi, new, BSI_NEW_STMT);
replace_phi_edge_with_variable (cond_bb, phi_bb, e1, phi, result);
return true;
}
/* The function absolute_replacement does the main work of doing the absolute /* The function absolute_replacement does the main work of doing the absolute
replacement. Return true if the replacement is done. Otherwise return replacement. Return true if the replacement is done. Otherwise return
false. false.
...@@ -497,9 +834,9 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -497,9 +834,9 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
tree new, cond; tree new, cond;
block_stmt_iterator bsi; block_stmt_iterator bsi;
edge true_edge, false_edge; edge true_edge, false_edge;
tree assign = NULL; tree assign;
edge e; edge e;
tree rhs = NULL, lhs = NULL; tree rhs, lhs;
bool negate; bool negate;
enum tree_code cond_code; enum tree_code cond_code;
...@@ -510,57 +847,31 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -510,57 +847,31 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
/* OTHER_BLOCK must have only one executable statement which must have the /* OTHER_BLOCK must have only one executable statement which must have the
form arg0 = -arg1 or arg1 = -arg0. */ form arg0 = -arg1 or arg1 = -arg0. */
bsi = bsi_start (middle_bb);
while (!bsi_end_p (bsi))
{
tree stmt = bsi_stmt (bsi);
/* Empty statements and labels are uninteresting. */
if (TREE_CODE (stmt) == LABEL_EXPR
|| IS_EMPTY_STMT (stmt))
{
bsi_next (&bsi);
continue;
}
/* If we found the assignment, but it was not the only executable
statement in OTHER_BLOCK, then we can not optimize. */
if (assign)
return false;
/* If we got here, then we have found the first executable statement
in OTHER_BLOCK. If it is anything other than arg = -arg1 or
arg1 = -arg0, then we can not optimize. */
if (TREE_CODE (stmt) == MODIFY_EXPR)
{
lhs = TREE_OPERAND (stmt, 0);
rhs = TREE_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == NEGATE_EXPR)
{
rhs = TREE_OPERAND (rhs, 0);
/* The assignment has to be arg0 = -arg1 or arg1 = -arg0. */
if ((lhs == arg0 && rhs == arg1)
|| (lhs == arg1 && rhs == arg0))
{
assign = stmt;
bsi_next (&bsi);
}
else
return false;
}
else
return false;
}
else
return false;
}
assign = last_and_only_stmt (middle_bb);
/* If we did not find the proper negation assignment, then we can not /* If we did not find the proper negation assignment, then we can not
optimize. */ optimize. */
if (assign == NULL) if (assign == NULL)
return false; return false;
/* If we got here, then we have found the only executable statement
in OTHER_BLOCK. If it is anything other than arg = -arg1 or
arg1 = -arg0, then we can not optimize. */
if (TREE_CODE (assign) != MODIFY_EXPR)
return false;
lhs = TREE_OPERAND (assign, 0);
rhs = TREE_OPERAND (assign, 1);
if (TREE_CODE (rhs) != NEGATE_EXPR)
return false;
rhs = TREE_OPERAND (rhs, 0);
/* The assignment has to be arg0 = -arg1 or arg1 = -arg0. */
if (!(lhs == arg0 && rhs == arg1)
&& !(lhs == arg1 && rhs == arg0))
return false;
cond = COND_EXPR_COND (last_stmt (cond_bb)); cond = COND_EXPR_COND (last_stmt (cond_bb));
result = PHI_RESULT (phi); result = PHI_RESULT (phi);
...@@ -607,8 +918,8 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -607,8 +918,8 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
lhs = result; lhs = result;
/* Build the modify expression with abs expression. */ /* Build the modify expression with abs expression. */
new = build (MODIFY_EXPR, TREE_TYPE (lhs), new = build2 (MODIFY_EXPR, TREE_TYPE (lhs),
lhs, build1 (ABS_EXPR, TREE_TYPE (lhs), rhs)); lhs, build1 (ABS_EXPR, TREE_TYPE (lhs), rhs));
bsi = bsi_last (cond_bb); bsi = bsi_last (cond_bb);
bsi_insert_before (&bsi, new, BSI_NEW_STMT); bsi_insert_before (&bsi, new, BSI_NEW_STMT);
...@@ -618,8 +929,8 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -618,8 +929,8 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
/* Get the right BSI. We want to insert after the recently /* Get the right BSI. We want to insert after the recently
added ABS_EXPR statement (which we know is the first statement added ABS_EXPR statement (which we know is the first statement
in the block. */ in the block. */
new = build (MODIFY_EXPR, TREE_TYPE (result), new = build2 (MODIFY_EXPR, TREE_TYPE (result),
result, build1 (NEGATE_EXPR, TREE_TYPE (lhs), lhs)); result, build1 (NEGATE_EXPR, TREE_TYPE (lhs), lhs));
bsi_insert_after (&bsi, new, BSI_NEW_STMT); bsi_insert_after (&bsi, new, BSI_NEW_STMT);
} }
......
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