mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-13 23:58:28 +08:00
re PR middle-end/33088 (spurious exceptions with -ffloat-store)
PR middle-end/33088 * gimplify.c (gimplify_modify_expr_complex_part): Add note to comment. * tree-complex.c (init_dont_simulate_again): Return true if there are uninitialized loads generated by gimplify_modify_expr_complex_part. * tree-gimple.c (is_gimple_reg_type): Return false for complex types if not optimizing. * tree-ssa.c (ssa_undefined_value_p): New predicate extracted from... (warn_uninit): ...here. Use ssa_undefined_value_p. * tree-ssa-pre.c (is_undefined_value): Delete. (phi_translate_1): Use ssa_undefined_value_p. (add_to_exp_gen): Likewise. (make_values_for_stmt): Likewise. * tree-flow.h (ssa_undefined_value_p): Declare. From-SVN: r130917
This commit is contained in:
parent
e49f4f07da
commit
7b7e6ecdb0
@ -1,3 +1,19 @@
|
||||
2007-12-13 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
PR middle-end/33088
|
||||
* gimplify.c (gimplify_modify_expr_complex_part): Add note to comment.
|
||||
* tree-complex.c (init_dont_simulate_again): Return true if there are
|
||||
uninitialized loads generated by gimplify_modify_expr_complex_part.
|
||||
* tree-gimple.c (is_gimple_reg_type): Return false for complex types
|
||||
if not optimizing.
|
||||
* tree-ssa.c (ssa_undefined_value_p): New predicate extracted from...
|
||||
(warn_uninit): ...here. Use ssa_undefined_value_p.
|
||||
* tree-ssa-pre.c (is_undefined_value): Delete.
|
||||
(phi_translate_1): Use ssa_undefined_value_p.
|
||||
(add_to_exp_gen): Likewise.
|
||||
(make_values_for_stmt): Likewise.
|
||||
* tree-flow.h (ssa_undefined_value_p): Declare.
|
||||
|
||||
2007-12-13 Andrew Pinski <pinskia@gmail.com>
|
||||
David Daney <ddaney@avtrex.com>
|
||||
|
||||
|
@ -3728,7 +3728,15 @@ tree_to_gimple_tuple (tree *tp)
|
||||
|
||||
/* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
|
||||
a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
|
||||
DECL_GIMPLE_REG_P set. */
|
||||
DECL_GIMPLE_REG_P set.
|
||||
|
||||
IMPORTANT NOTE: This promotion is performed by introducing a load of the
|
||||
other, unmodified part of the complex object just before the total store.
|
||||
As a consequence, if the object is still uninitialized, an undefined value
|
||||
will be loaded into a register, which may result in a spurious exception
|
||||
if the register is floating-point and the value happens to be a signaling
|
||||
NaN for example. Then the fully-fledged complex operations lowering pass
|
||||
followed by a DCE pass are necessary in order to fix things up. */
|
||||
|
||||
static enum gimplify_status
|
||||
gimplify_modify_expr_complex_part (tree *expr_p, tree *pre_p, bool want_value)
|
||||
|
@ -1,3 +1,8 @@
|
||||
2007-12-13 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* gcc.dg/uninit-13.c: UnXFAIL.
|
||||
* gcc.dg/complex-5.c: New testcase.
|
||||
|
||||
2007-12-13 Olga Golovanevsky <olga@il.ibm.com>
|
||||
|
||||
* gcc.dg/struct/struct-reorg.exp: Replace
|
||||
|
55
gcc/testsuite/gcc.dg/complex-5.c
Normal file
55
gcc/testsuite/gcc.dg/complex-5.c
Normal file
@ -0,0 +1,55 @@
|
||||
/* PR middle-end/33088 */
|
||||
/* Origin: Joseph S. Myers <jsm28@gcc.gnu.org> */
|
||||
|
||||
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
|
||||
/* { dg-options "-std=c99 -O -ffloat-store -lm" } */
|
||||
|
||||
#include <fenv.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
volatile int x[1024];
|
||||
|
||||
void __attribute__((noinline))
|
||||
fill_stack (void)
|
||||
{
|
||||
volatile int y[1024];
|
||||
int i;
|
||||
for (i = 0; i < 1024; i++)
|
||||
y[i] = 0x7ff00000;
|
||||
for (i = 0; i < 1024; i++)
|
||||
x[i] = y[i];
|
||||
}
|
||||
|
||||
volatile _Complex double vc;
|
||||
|
||||
void __attribute__((noinline))
|
||||
use_complex (_Complex double c)
|
||||
{
|
||||
vc = c;
|
||||
}
|
||||
|
||||
double t0, t1, t2, t3;
|
||||
|
||||
#define USE_COMPLEX(X, R, C) \
|
||||
do { __real__ X = R; __imag__ X = C; use_complex (X); } while (0)
|
||||
|
||||
void __attribute__((noinline))
|
||||
use_stack (void)
|
||||
{
|
||||
_Complex double a, b, c, d;
|
||||
USE_COMPLEX (a, t0, t1);
|
||||
USE_COMPLEX (b, t1, t2);
|
||||
USE_COMPLEX (c, t2, t3);
|
||||
USE_COMPLEX (d, t3, t0);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
fill_stack ();
|
||||
feclearexcept (FE_INVALID);
|
||||
use_stack ();
|
||||
if (fetestexcept (FE_INVALID))
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
@ -5,6 +5,6 @@ typedef _Complex float C;
|
||||
C foo()
|
||||
{
|
||||
C f;
|
||||
__imag__ f = 0;
|
||||
return f; /* { dg-warning "" "uninit" { xfail *-*-* } } */
|
||||
__imag__ f = 0; /* { dg-warning "is used" "unconditional" } */
|
||||
return f;
|
||||
}
|
||||
|
@ -246,6 +246,17 @@ init_dont_simulate_again (void)
|
||||
saw_a_complex_op = true;
|
||||
break;
|
||||
|
||||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
/* The total store transformation performed during
|
||||
gimplification creates such uninitialized loads
|
||||
and we need to lower the statement to be able
|
||||
to fix things up. */
|
||||
if (TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
|
||||
&& ssa_undefined_value_p (TREE_OPERAND (rhs, 0)))
|
||||
saw_a_complex_op = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -884,6 +884,7 @@ extern void verify_ssa (bool);
|
||||
extern void delete_tree_ssa (void);
|
||||
extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
|
||||
extern bool stmt_references_memory_p (tree);
|
||||
extern bool ssa_undefined_value_p (tree);
|
||||
|
||||
/* In tree-into-ssa.c */
|
||||
void update_ssa (unsigned);
|
||||
|
@ -285,7 +285,13 @@ is_gimple_id (tree t)
|
||||
bool
|
||||
is_gimple_reg_type (tree type)
|
||||
{
|
||||
return !AGGREGATE_TYPE_P (type);
|
||||
/* In addition to aggregate types, we also exclude complex types if not
|
||||
optimizing because they can be subject to partial stores in GNU C by
|
||||
means of the __real__ and __imag__ operators and we cannot promote
|
||||
them to total stores (see gimplify_modify_expr_complex_part). */
|
||||
return !(AGGREGATE_TYPE_P (type)
|
||||
|| (TREE_CODE (type) == COMPLEX_TYPE && !optimize));
|
||||
|
||||
}
|
||||
|
||||
/* Return true if T is a non-aggregate register variable. */
|
||||
@ -328,8 +334,8 @@ is_gimple_reg (tree t)
|
||||
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
|
||||
return false;
|
||||
|
||||
/* Complex values must have been put into ssa form. That is, no
|
||||
assignments to the individual components. */
|
||||
/* Complex and vector values must have been put into SSA-like form.
|
||||
That is, no assignments to the individual components. */
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
|
||||
return DECL_GIMPLE_REG_P (t);
|
||||
|
@ -383,7 +383,6 @@ static void bitmap_set_copy (bitmap_set_t, bitmap_set_t);
|
||||
static bool bitmap_set_contains_value (bitmap_set_t, tree);
|
||||
static void bitmap_insert_into_set (bitmap_set_t, tree);
|
||||
static bitmap_set_t bitmap_set_new (void);
|
||||
static bool is_undefined_value (tree);
|
||||
static tree create_expression_by_pieces (basic_block, tree, tree);
|
||||
static tree find_or_generate_expression (basic_block, tree, tree);
|
||||
|
||||
@ -1328,7 +1327,7 @@ phi_translate_1 (tree expr, bitmap_set_t set1, bitmap_set_t set2,
|
||||
if (is_gimple_min_invariant (def))
|
||||
return def;
|
||||
|
||||
if (is_undefined_value (def))
|
||||
if (TREE_CODE (def) == SSA_NAME && ssa_undefined_value_p (def))
|
||||
return NULL;
|
||||
|
||||
val = get_value_handle (def);
|
||||
@ -2889,18 +2888,6 @@ insert (void)
|
||||
}
|
||||
|
||||
|
||||
/* Return true if VAR is an SSA variable with no defining statement in
|
||||
this procedure, *AND* isn't a live-on-entry parameter. */
|
||||
|
||||
static bool
|
||||
is_undefined_value (tree expr)
|
||||
{
|
||||
return (TREE_CODE (expr) == SSA_NAME
|
||||
&& IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr))
|
||||
/* PARM_DECLs and hard registers are always defined. */
|
||||
&& TREE_CODE (SSA_NAME_VAR (expr)) != PARM_DECL);
|
||||
}
|
||||
|
||||
/* Add OP to EXP_GEN (block), and possibly to the maximal set if it is
|
||||
not defined by a phi node.
|
||||
PHI nodes can't go in the maximal sets because they are not in
|
||||
@ -2912,7 +2899,7 @@ add_to_exp_gen (basic_block block, tree op)
|
||||
{
|
||||
if (!in_fre)
|
||||
{
|
||||
if (TREE_CODE (op) == SSA_NAME && is_undefined_value (op))
|
||||
if (TREE_CODE (op) == SSA_NAME && ssa_undefined_value_p (op))
|
||||
return;
|
||||
bitmap_value_insert_into_set (EXP_GEN (block), op);
|
||||
if (TREE_CODE (op) != SSA_NAME
|
||||
@ -3415,7 +3402,7 @@ make_values_for_stmt (tree stmt, basic_block block)
|
||||
AVAIL_OUT (block));
|
||||
}
|
||||
/* None of the rest of these can be PRE'd. */
|
||||
if (TREE_CODE (rhs) == SSA_NAME && !is_undefined_value (rhs))
|
||||
if (TREE_CODE (rhs) == SSA_NAME && !ssa_undefined_value_p (rhs))
|
||||
add_to_exp_gen (block, rhs);
|
||||
return true;
|
||||
}
|
||||
|
@ -1228,9 +1228,28 @@ walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data,
|
||||
}
|
||||
|
||||
|
||||
/* Return true if T, an SSA_NAME, has an undefined value. */
|
||||
|
||||
bool
|
||||
ssa_undefined_value_p (tree t)
|
||||
{
|
||||
tree var = SSA_NAME_VAR (t);
|
||||
|
||||
/* Parameters get their initial value from the function entry. */
|
||||
if (TREE_CODE (var) == PARM_DECL)
|
||||
return false;
|
||||
|
||||
/* Hard register variables get their initial value from the ether. */
|
||||
if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
|
||||
return false;
|
||||
|
||||
/* The value is undefined iff its definition statement is empty. */
|
||||
return IS_EMPTY_STMT (SSA_NAME_DEF_STMT (t));
|
||||
}
|
||||
|
||||
/* Emit warnings for uninitialized variables. This is done in two passes.
|
||||
|
||||
The first pass notices real uses of SSA names with default definitions.
|
||||
The first pass notices real uses of SSA names with undefined values.
|
||||
Such uses are unconditionally uninitialized, and we can be certain that
|
||||
such a use is a mistake. This pass is run before most optimizations,
|
||||
so that we catch as many as we can.
|
||||
@ -1250,22 +1269,11 @@ static void
|
||||
warn_uninit (tree t, const char *gmsgid, void *data)
|
||||
{
|
||||
tree var = SSA_NAME_VAR (t);
|
||||
tree def = SSA_NAME_DEF_STMT (t);
|
||||
tree context = (tree) data;
|
||||
location_t *locus;
|
||||
expanded_location xloc, floc;
|
||||
|
||||
/* Default uses (indicated by an empty definition statement),
|
||||
are uninitialized. */
|
||||
if (!IS_EMPTY_STMT (def))
|
||||
return;
|
||||
|
||||
/* Except for PARMs of course, which are always initialized. */
|
||||
if (TREE_CODE (var) == PARM_DECL)
|
||||
return;
|
||||
|
||||
/* Hard register variables get their initial value from the ether. */
|
||||
if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
|
||||
if (!ssa_undefined_value_p (t))
|
||||
return;
|
||||
|
||||
/* TREE_NO_WARNING either means we already warned, or the front end
|
||||
|
Loading…
Reference in New Issue
Block a user