> 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;
 	}
 

Reply via email to