tree-optimization/88240 - stopgap for floating point code-hoisting issues

This adds a stopgap measure to avoid performing code-hoisting
on mixed type loads when the load we'd insert in the hoisting
position would be a floating point one.  This is because certain
targets (hello x87) cannot perform floating point loads without
possibly altering the bit representation and thus cannot be used
in place of integral loads.

2020-08-04  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/88240
	* tree-ssa-sccvn.h (vn_reference_s::punned): New flag.
	* tree-ssa-sccvn.c (vn_reference_insert): Initialize punned.
	(vn_reference_insert_pieces): Likewise.
	(visit_reference_op_call): Likewise.
	(visit_reference_op_load): Track whether a ref was punned.
	* tree-ssa-pre.c (do_hoist_insertion): Refuse to perform hoist
	insertion on punned floating point loads.

	* gcc.target/i386/pr88240.c: New testcase.
This commit is contained in:
Richard Biener 2020-08-04 14:10:45 +02:00
parent 7bd72dd5a3
commit 1af5cdd779
4 changed files with 49 additions and 1 deletions

View File

@ -0,0 +1,26 @@
/* { dg-do run } */
/* { dg-options "-O2 -mno-sse" } */
int flag;
union { double f; unsigned long long i; } u;
void __attribute__((noinline))
init ()
{
flag = 1;
u.i = 18442936822990639076ULL;
}
unsigned long long __attribute__((noinline))
test ()
{
if (flag)
return u.i;
else
return u.f;
}
int main()
{
init ();
if (test () != 18442936822990639076ULL)
__builtin_abort ();
return 0;
}

View File

@ -3571,6 +3571,16 @@ do_hoist_insertion (basic_block block)
continue;
}
/* If we end up with a punned expression representation and this
happens to be a float typed one give up - we can't know for
sure whether all paths perform the floating-point load we are
about to insert and on some targets this can cause correctness
issues. See PR88240. */
if (expr->kind == REFERENCE
&& PRE_EXPR_REFERENCE (expr)->punned
&& FLOAT_TYPE_P (get_expr_type (expr)))
continue;
/* OK, we should hoist this value. Perform the transformation. */
pre_stats.hoist_insert++;
if (dump_file && (dump_flags & TDF_DETAILS))

View File

@ -3601,6 +3601,7 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
vr1->vuse = vuse_ssa_val (vuse);
vr1->operands = valueize_shared_reference_ops_from_ref (op, &tem).copy ();
vr1->type = TREE_TYPE (op);
vr1->punned = 0;
ao_ref op_ref;
ao_ref_init (&op_ref, op);
vr1->set = ao_ref_alias_set (&op_ref);
@ -3660,6 +3661,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set,
vr1->vuse = vuse_ssa_val (vuse);
vr1->operands = valueize_refs (operands);
vr1->type = type;
vr1->punned = 0;
vr1->set = set;
vr1->base_set = base_set;
vr1->hashcode = vn_reference_compute_hash (vr1);
@ -4892,6 +4894,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
them here. */
vr2->operands = vr1.operands.copy ();
vr2->type = vr1.type;
vr2->punned = vr1.punned;
vr2->set = vr1.set;
vr2->base_set = vr1.base_set;
vr2->hashcode = vr1.hashcode;
@ -4918,10 +4921,11 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
bool changed = false;
tree last_vuse;
tree result;
vn_reference_t res;
last_vuse = gimple_vuse (stmt);
result = vn_reference_lookup (op, gimple_vuse (stmt),
default_vn_walk_kind, NULL, true, &last_vuse);
default_vn_walk_kind, &res, true, &last_vuse);
/* We handle type-punning through unions by value-numbering based
on offset and size of the access. Be prepared to handle a
@ -4943,6 +4947,13 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
gimple_match_op res_op (gimple_match_cond::UNCOND,
VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
result = vn_nary_build_or_lookup (&res_op);
if (result
&& TREE_CODE (result) == SSA_NAME
&& VN_INFO (result)->needs_insertion)
/* Track whether this is the canonical expression for different
typed loads. We use that as a stopgap measure for code
hoisting when dealing with floating point loads. */
res->punned = true;
}
/* When building the conversion fails avoid inserting the reference

View File

@ -145,6 +145,7 @@ typedef struct vn_reference_s
alias_set_type set;
alias_set_type base_set;
tree type;
unsigned punned : 1;
vec<vn_reference_op_s> operands;
tree result;
tree result_vdef;