> ISTR SUBREG_PROMOTED_* gets set by RTL expansion, the problematic
> one should be the one in expr.c setting it on all SSA_NAMEs, maybe it is
> enough to avoid setting it for SSA_NAME_IS_DEFAULT_DEF ones?
No, it's not enough in this case, you need to work a little harder and look at
the arguments of a PHI node because the SSA_NAME_IS_DEFAULT_DEF name is never
materialized in the RTL; so the attached patch works in this case.
* expr.c (expand_expr_real_1) <expand_decl_rtl>: For a SSA_NAME, do
not set SUBREG_PROMOTED_VAR_P on the sub-register if it may contain
uninitialized bits.
--
Eric Botcazou
Index: expr.c
===================================================================
--- expr.c (revision 253114)
+++ expr.c (working copy)
@@ -9908,6 +9908,7 @@ expand_expr_real_1 (tree exp, rtx target
&& dmode != BLKmode
&& GET_MODE (decl_rtl) != dmode)
{
+ bool maybe_uninitialized = false;
machine_mode pmode;
/* Get the signedness to be used for this variable. Ensure we get
@@ -9918,15 +9919,42 @@ expand_expr_real_1 (tree exp, rtx target
&& gimple_code (g) == GIMPLE_CALL
&& !gimple_call_internal_p (g))
pmode = promote_function_mode (type, mode, &unsignedp,
- gimple_call_fntype (g),
- 2);
+ gimple_call_fntype (g), 2);
else
- pmode = promote_ssa_mode (ssa_name, &unsignedp);
+ {
+ use_operand_p arg_p;
+ ssa_op_iter i;
+
+ /* Try to detect if the register contains uninitialized bits. */
+ if (SSA_NAME_IS_DEFAULT_DEF (ssa_name))
+ maybe_uninitialized = true;
+ else if (gimple_code (g) == GIMPLE_PHI)
+ FOR_EACH_PHI_ARG (arg_p, as_a<gphi *> (g), i, SSA_OP_USE)
+ {
+ tree arg = USE_FROM_PTR (arg_p);
+ if (TREE_CODE (arg) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (arg))
+ {
+ maybe_uninitialized = true;
+ break;
+ }
+ }
+
+ pmode = promote_ssa_mode (ssa_name, &unsignedp);
+ }
+
gcc_assert (GET_MODE (decl_rtl) == pmode);
temp = gen_lowpart_SUBREG (mode, decl_rtl);
- SUBREG_PROMOTED_VAR_P (temp) = 1;
- SUBREG_PROMOTED_SET (temp, unsignedp);
+
+ /* We cannot assume anything about a previous extension if the
+ register may contain uninitialized bits. */
+ if (!maybe_uninitialized)
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, unsignedp);
+ }
+
return temp;
}