re PR tree-optimization/31966 (Miscompiles valid code with -ftree-vectorize)

PR tree-optimization/31966
	PR tree-optimization/32533
	* tree-if-conv.c (add_to_dst_predicate_list): Use "edge", not
	"basic_block" description as its third argument.  Update function
	calls to get destination bb from "edge" argument.  Save "cond" into
	aux field of the edge.  Update prototype for changed arguments.
	(find_phi_replacement_condition): Operate on incoming edges, not
	on predecessor blocks.  If there is a condition saved in the
	incoming edge aux field, AND it with incoming bb predicate.
	Return source bb of the first edge.
	(clean_predicate_lists): Clean aux field of outgoing node edges.
	(tree_if_conversion): Do not initialize cond variable. Move
	variable declaration into the loop.
	(replace_phi_with_cond_gimple_modify_stmt): Remove unneded
	initializations of new_stmt, arg0 and arg1 variables.

testsuite/ChangeLog:

	PR tree-optimization/31966
	PR tree-optimization/32533
	* gcc.dg/tree-ssa/pr31966.c: New runtime test.
	* gfortran.dg/pr32533.f90: Ditto.

From-SVN: r126206
This commit is contained in:
Uros Bizjak 2007-07-02 16:26:11 +02:00 committed by Uros Bizjak
parent bc90eb85d9
commit 8ad0217501
5 changed files with 166 additions and 45 deletions

View File

@ -1,3 +1,21 @@
2007-07-02 Uros Bizjak <ubizjak@gmail.com>
PR tree-optimization/31966
PR tree-optimization/32533
* tree-if-conv.c (add_to_dst_predicate_list): Use "edge", not
"basic_block" description as its third argument. Update function
calls to get destination bb from "edge" argument. Save "cond" into
aux field of the edge. Update prototype for changed arguments.
(find_phi_replacement_condition): Operate on incoming edges, not
on predecessor blocks. If there is a condition saved in the
incoming edge aux field, AND it with incoming bb predicate.
Return source bb of the first edge.
(clean_predicate_lists): Clean aux field of outgoing node edges.
(tree_if_conversion): Do not initialize cond variable. Move
variable declaration into the loop.
(replace_phi_with_cond_gimple_modify_stmt): Remove unneded
initializations of new_stmt, arg0 and arg1 variables.
2007-07-02 Jakub Jelinek <jakub@redhat.com>
* tree-nrv.c (dest_safe_for_nrv_p): Grok any handled_component_p,

View File

@ -1,3 +1,10 @@
2007-07-02 Uros Bizjak <ubizjak@gmail.com>
PR tree-optimization/31966
PR tree-optimization/32533
* gcc.dg/tree-ssa/pr31966.c: New runtime test.
* gfortran.dg/pr32533.f90: Ditto.
2007-07-02 Jakub Jelinek <jakub@redhat.com>
* g++.dg/opt/nrv12.C: New test.

View File

@ -0,0 +1,50 @@
/* Contributed by Jack Lloyd <lloyd@randombit.net> */
/* { dg-options "-O2 -ftree-vectorize" } */
/* { dg-options "-O2 -ftree-vectorize -march=nocona" { target { i?86-*-* x86_64-*-* } } } */
typedef unsigned long long word;
const unsigned int MP_WORD_BITS = 64;
const word MP_WORD_MASK = ~((word)0);
const word MP_WORD_TOP_BIT = (word)1 << (8*sizeof(word) - 1);
extern void abort (void);
word do_div(word n1, word n0, word d)
{
word high = n1 % d, quotient = 0;
unsigned int j;
for(j = 0; j != MP_WORD_BITS; ++j)
{
word high_top_bit = (high & MP_WORD_TOP_BIT);
high <<= 1;
high |= (n0 >> (MP_WORD_BITS-1-j)) & 1;
quotient <<= 1;
if(high_top_bit || high >= d)
{
high -= d;
quotient |= 1;
}
}
return quotient;
}
int main()
{
word result;
result = do_div(0x0000000000200000ll,
0x0000000000000000ll,
0x86E53497CE000000ll);
if (result != 0x3CBA83)
abort ();
return 0;
}

View File

@ -0,0 +1,18 @@
! { dg-do run }
! { dg-options "-O2 -ftree-vectorize -ffast-math" }
!
! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
!
SUBROUTINE T(nsubcell,sab_max,subcells)
INTEGER, PARAMETER :: dp=KIND(0.0D0)
REAL(dp) :: sab_max(3), subcells,nsubcell(3)
nsubcell(:) = MIN(MAX(1,NINT(0.5_dp*subcells/sab_max(:))),20)
END SUBROUTINE T
INTEGER, PARAMETER :: dp=KIND(0.0D0)
REAL(dp) :: sab_max(3), subcells,nsubcell(3)
subcells=2.0_dp
sab_max=0.590060749244805_dp
CALL T(nsubcell,sab_max,subcells)
IF (ANY(nsubcell.NE.2.0_dp)) CALL ABORT()
END

View File

@ -114,7 +114,8 @@ static bool if_convertible_stmt_p (struct loop *, basic_block, tree);
static bool if_convertible_bb_p (struct loop *, basic_block, basic_block);
static bool if_convertible_loop_p (struct loop *, bool);
static void add_to_predicate_list (basic_block, tree);
static tree add_to_dst_predicate_list (struct loop * loop, basic_block, tree, tree,
static tree add_to_dst_predicate_list (struct loop * loop, edge,
tree, tree,
block_stmt_iterator *);
static void clean_predicate_lists (struct loop *loop);
static basic_block find_phi_replacement_condition (struct loop *loop,
@ -144,7 +145,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer)
{
basic_block bb;
block_stmt_iterator itr;
tree cond;
unsigned int i;
ifc_bbs = NULL;
@ -164,11 +164,11 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer)
return false;
}
cond = NULL_TREE;
/* Do actual work now. */
for (i = 0; i < loop->num_nodes; i++)
{
tree cond;
bb = ifc_bbs [i];
/* Update condition using predicate list. */
@ -192,7 +192,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer)
basic_block bb_n = single_succ (bb);
if (cond != NULL_TREE)
add_to_predicate_list (bb_n, cond);
cond = NULL_TREE;
}
}
@ -276,12 +275,12 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
/* Add new condition into destination's predicate list. */
/* If 'c' is true then TRUE_EDGE is taken. */
add_to_dst_predicate_list (loop, true_edge->dest, cond,
add_to_dst_predicate_list (loop, true_edge, cond,
unshare_expr (c), bsi);
/* If 'c' is false then FALSE_EDGE is taken. */
c2 = invert_truthvalue (unshare_expr (c));
add_to_dst_predicate_list (loop, false_edge->dest, cond, c2, bsi);
add_to_dst_predicate_list (loop, false_edge, cond, c2, bsi);
/* Now this conditional statement is redundant. Remove it.
But, do not remove exit condition! Update exit condition
@ -578,7 +577,15 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
/* ??? Check data dependency for vectorizer. */
/* What about phi nodes ? */
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
phi = phi_nodes (bb);
/* Clear aux field of incoming edges to a bb with a phi node. */
if (phi)
FOR_EACH_EDGE (e, ei, bb->preds)
e->aux = NULL;
/* Check statements. */
for (; phi; phi = PHI_CHAIN (phi))
if (!if_convertible_phi_p (loop, bb, phi))
return false;
@ -615,13 +622,13 @@ add_to_predicate_list (basic_block bb, tree new_cond)
existing condition. */
static tree
add_to_dst_predicate_list (struct loop * loop, basic_block bb,
add_to_dst_predicate_list (struct loop * loop, edge e,
tree prev_cond, tree cond,
block_stmt_iterator *bsi)
{
tree new_cond = NULL_TREE;
if (!flow_bb_inside_loop_p (loop, bb))
if (!flow_bb_inside_loop_p (loop, e->dest))
return NULL_TREE;
if (prev_cond == boolean_true_node || !prev_cond)
@ -642,6 +649,11 @@ add_to_dst_predicate_list (struct loop * loop, basic_block bb,
if (tmp_stmts2)
bsi_insert_before (bsi, tmp_stmts2, BSI_SAME_STMT);
/* Add the condition to aux field of the edge. In case edge
destination is a PHI node, this condition will be ANDed with
block predicate to construct complete condition. */
e->aux = cond;
/* new_cond == prev_cond AND cond */
tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
unshare_expr (prev_cond), cond);
@ -649,22 +661,30 @@ add_to_dst_predicate_list (struct loop * loop, basic_block bb,
bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT);
new_cond = GIMPLE_STMT_OPERAND (tmp_stmt, 0);
}
add_to_predicate_list (bb, new_cond);
add_to_predicate_list (e->dest, new_cond);
return new_cond;
}
/* During if-conversion aux field from basic block is used to hold predicate
list. Clean each basic block's predicate list for the given LOOP. */
/* During if-conversion aux field from basic block structure is used to hold
predicate list. Clean each basic block's predicate list for the given LOOP.
Also clean aux field of succesor edges, used to hold true and false
condition from conditional expression. */
static void
clean_predicate_lists (struct loop *loop)
{
basic_block *bb;
unsigned int i;
edge e;
edge_iterator ei;
bb = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++)
bb[i]->aux = NULL;
{
bb[i]->aux = NULL;
FOR_EACH_EDGE (e, ei, bb[i]->succs)
e->aux = NULL;
}
free (bb);
}
@ -677,13 +697,12 @@ find_phi_replacement_condition (struct loop *loop,
basic_block bb, tree *cond,
block_stmt_iterator *bsi)
{
basic_block first_bb = NULL;
basic_block second_bb = NULL;
edge first_edge, second_edge;
tree tmp_cond, new_stmts;
gcc_assert (EDGE_COUNT (bb->preds) == 2);
first_bb = (EDGE_PRED (bb, 0))->src;
second_bb = (EDGE_PRED (bb, 1))->src;
first_edge = EDGE_PRED (bb, 0);
second_edge = EDGE_PRED (bb, 1);
/* Use condition based on following criteria:
1)
@ -704,42 +723,55 @@ find_phi_replacement_condition (struct loop *loop,
S3: x = (c == d) ? b : a;
S3 is preferred over S1 and S2*, Make 'b' first_bb and use
its condition.
its condition.
4) If pred B is dominated by pred A then use pred B's condition.
See PR23115. */
/* Select condition that is not TRUTH_NOT_EXPR. */
tmp_cond = first_bb->aux;
tmp_cond = (first_edge->src)->aux;
if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
{
basic_block tmp_bb;
tmp_bb = first_bb;
first_bb = second_bb;
second_bb = tmp_bb;
edge tmp_edge;
tmp_edge = first_edge;
first_edge = second_edge;
second_edge = tmp_edge;
}
/* Check if FIRST_BB is loop header or not and make sure that
FIRST_BB does not dominate SECOND_BB. */
if (first_bb == loop->header
|| dominated_by_p (CDI_DOMINATORS, second_bb, first_bb))
if (first_edge->src == loop->header
|| dominated_by_p (CDI_DOMINATORS,
second_edge->src, first_edge->src))
{
tmp_cond = second_bb->aux;
if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
{
/* Select non loop header condition but do not switch basic blocks. */
*cond = invert_truthvalue (unshare_expr (tmp_cond));
}
*cond = (second_edge->src)->aux;
/* If there is a condition on an incoming edge,
AND it with the incoming bb predicate. */
if (second_edge->aux)
*cond = build2 (TRUTH_AND_EXPR, boolean_type_node,
*cond, first_edge->aux);
if (TREE_CODE (*cond) == TRUTH_NOT_EXPR)
/* We can be smart here and choose inverted
condition without switching bbs. */
*cond = invert_truthvalue (*cond);
else
{
/* Select non loop header condition. */
first_bb = second_bb;
*cond = first_bb->aux;
}
/* Select non loop header bb. */
first_edge = second_edge;
}
else
/* FIRST_BB is not loop header */
*cond = first_bb->aux;
{
/* FIRST_BB is not loop header */
*cond = (first_edge->src)->aux;
/* If there is a condition on an incoming edge,
AND it with the incoming bb predicate. */
if (first_edge->aux)
*cond = build2 (TRUTH_AND_EXPR, boolean_type_node,
*cond, first_edge->aux);
}
/* Create temp. for the condition. Vectorizer prefers to have gimple
value as condition. Various targets use different means to communicate
@ -759,7 +791,7 @@ find_phi_replacement_condition (struct loop *loop,
gcc_assert (*cond);
return first_bb;
return first_edge->src;
}
@ -791,10 +823,6 @@ replace_phi_with_cond_gimple_modify_stmt (tree phi, tree cond,
/* Find basic block and initialize iterator. */
bb = bb_for_stmt (phi);
new_stmt = NULL_TREE;
arg_0 = NULL_TREE;
arg_1 = NULL_TREE;
/* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */
if (EDGE_PRED (bb, 1)->src == true_bb)
{