https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2024-07-26 Ever confirmed|0 |1 --- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> --- For this testcase the issue is that we value-number _1 = *x_32(D); .. _41 = MEM <unsigned int> [(char * {ref-all})x_32(D)]; the same: Value numbering stmt = _1 = *x_32(D); Setting value number of _1 to _1 (changed) ... Value numbering stmt = _41 = MEM <unsigned int> [(char * {ref-all})x_32(D)]; Inserting name _50 for expression VIEW_CONVERT_EXPR<unsigned int>(_1) Setting value number of _41 to _50 (changed) We already have mitigation of some of this for code hoisting but did not yet disable all FP<->int punning since this was explicitly introduced for optimization and there's currently no way to query the target whether a FP load is not bit-representation preserving. I'm not sure if we can look at the hardreg for the FP mode in question and decide based on its mode for example. The following fixes this. But I really think we need a target hook to avoid pessimizing all targets. diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 0139f1b4e30..62f3de11b56 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -5825,6 +5825,13 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt) result = NULL_TREE; else if (CONSTANT_CLASS_P (result)) result = const_unop (VIEW_CONVERT_EXPR, TREE_TYPE (op), result); + /* Do not treat a float-mode load as preserving the bit + representation. See PR114659, on for x87 FP modes there + is no load instruction that does not at least turn sNaNs + into qNaNs. But allow the case of a constant FP value we an + fold above. */ + else if (SCALAR_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (result)))) + result = NULL_TREE; else { /* We will be setting the value number of lhs to the value number For example gcc.dg/tree-ssa/ssa-fre-7.c explicitly tests for this transform, so the patch regresses quite a few testcases.