[PATCH] Fix PR56295

Richard Biener rguenther@suse.de
Tue Feb 12 13:57:00 GMT 2013


This fixes the code difference -O3 vs. -O3 -flto reported in PR56295.
For the -flto run we are confused by the extra MEM_REF we wrap every
global decl with in the IL (that is to support seamless and alias-correct
replacement of global decls with their prevailing decl).  The following
un-wraps the decl again if the extra MEM_REF has no semantic meaning
(we also do that in fold_stmt, I chose to duplicate the code in a
slightly stricter form here - eventually we should simply fold all
stmts, we have got extra information like global initializers available
at LTRANS time after all).

LTO bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2013-02-12  Richard Biener  <rguenther@suse.de>

	PR lto/56295
	* gimple-streamer-in.c (input_gimple_stmt): Strip MEM_REFs off
	decls again if possible.

Index: gcc/gimple-streamer-in.c
===================================================================
*** gcc/gimple-streamer-in.c	(revision 195973)
--- gcc/gimple-streamer-in.c	(working copy)
*************** input_gimple_stmt (struct lto_input_bloc
*** 143,164 ****
      case GIMPLE_DEBUG:
        for (i = 0; i < num_ops; i++)
  	{
! 	  tree op = stream_read_tree (ib, data_in);
  	  gimple_set_op (stmt, i, op);
  	  if (!op)
  	    continue;
  
! 	  if (TREE_CODE (op) == ADDR_EXPR)
! 	    op = TREE_OPERAND (op, 0);
! 	  while (handled_component_p (op))
  	    {
! 	      if (TREE_CODE (op) == COMPONENT_REF)
  		{
  		  /* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled
  		     by decl merging.  */
  		  tree field, type, tem;
  		  tree closest_match = NULL_TREE;
! 		  field = TREE_OPERAND (op, 1);
  		  type = DECL_CONTEXT (field);
  		  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
  		    {
--- 143,165 ----
      case GIMPLE_DEBUG:
        for (i = 0; i < num_ops; i++)
  	{
! 	  tree *opp, op = stream_read_tree (ib, data_in);
  	  gimple_set_op (stmt, i, op);
  	  if (!op)
  	    continue;
  
! 	  opp = gimple_op_ptr (stmt, i);
! 	  if (TREE_CODE (*opp) == ADDR_EXPR)
! 	    opp = &TREE_OPERAND (*opp, 0);
! 	  while (handled_component_p (*opp))
  	    {
! 	      if (TREE_CODE (*opp) == COMPONENT_REF)
  		{
  		  /* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled
  		     by decl merging.  */
  		  tree field, type, tem;
  		  tree closest_match = NULL_TREE;
! 		  field = TREE_OPERAND (*opp, 1);
  		  type = DECL_CONTEXT (field);
  		  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
  		    {
*************** input_gimple_stmt (struct lto_input_bloc
*** 186,197 ****
  		      if (warning_at (gimple_location (stmt), 0,
  				      "use of type %<%E%> with two mismatching "
  				      "declarations at field %<%E%>",
! 				      type, TREE_OPERAND (op, 1)))
  			{
  			  if (TYPE_FIELDS (type))
  			    inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)),
  				    "original type declared here");
! 			  inform (DECL_SOURCE_LOCATION (TREE_OPERAND (op, 1)),
  				  "field in mismatching type declared here");
  			  if (TYPE_NAME (TREE_TYPE (field))
  			      && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
--- 187,198 ----
  		      if (warning_at (gimple_location (stmt), 0,
  				      "use of type %<%E%> with two mismatching "
  				      "declarations at field %<%E%>",
! 				      type, TREE_OPERAND (*opp, 1)))
  			{
  			  if (TYPE_FIELDS (type))
  			    inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)),
  				    "original type declared here");
! 			  inform (DECL_SOURCE_LOCATION (TREE_OPERAND (*opp, 1)),
  				  "field in mismatching type declared here");
  			  if (TYPE_NAME (TREE_TYPE (field))
  			      && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
*************** input_gimple_stmt (struct lto_input_bloc
*** 208,235 ****
  				    "type of mismatching field declared here");
  			}
  		      /* And finally fixup the types.  */
! 		      TREE_OPERAND (op, 0)
  			= build1 (VIEW_CONVERT_EXPR, type,
! 				  TREE_OPERAND (op, 0));
  		    }
  		  else
! 		    TREE_OPERAND (op, 1) = tem;
  		}
! 	      else if ((TREE_CODE (op) == ARRAY_REF
! 			|| TREE_CODE (op) == ARRAY_RANGE_REF)
! 		       && (TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0)))
  			   != ARRAY_TYPE))
  		{
  		  /* And ARRAY_REFs to objects that had mismatched types
  		     during symbol merging to avoid ICEs.  */
! 		  TREE_OPERAND (op, 0)
  		    = build1 (VIEW_CONVERT_EXPR,
! 			      build_array_type (TREE_TYPE (op), NULL_TREE),
! 			      TREE_OPERAND (op, 0));
  		}
  
! 	      op = TREE_OPERAND (op, 0);
  	    }
  	}
        if (is_gimple_call (stmt))
  	{
--- 209,252 ----
  				    "type of mismatching field declared here");
  			}
  		      /* And finally fixup the types.  */
! 		      TREE_OPERAND (*opp, 0)
  			= build1 (VIEW_CONVERT_EXPR, type,
! 				  TREE_OPERAND (*opp, 0));
  		    }
  		  else
! 		    TREE_OPERAND (*opp, 1) = tem;
  		}
! 	      else if ((TREE_CODE (*opp) == ARRAY_REF
! 			|| TREE_CODE (*opp) == ARRAY_RANGE_REF)
! 		       && (TREE_CODE (TREE_TYPE (TREE_OPERAND (*opp, 0)))
  			   != ARRAY_TYPE))
  		{
  		  /* And ARRAY_REFs to objects that had mismatched types
  		     during symbol merging to avoid ICEs.  */
! 		  TREE_OPERAND (*opp, 0)
  		    = build1 (VIEW_CONVERT_EXPR,
! 			      build_array_type (TREE_TYPE (*opp), NULL_TREE),
! 			      TREE_OPERAND (*opp, 0));
  		}
  
! 	      opp = &TREE_OPERAND (*opp, 0);
  	    }
+ 	  /* At LTO output time we wrap all global decls in MEM_REFs to
+ 	     allow seamless replacement with prevailing decls.  Undo this
+ 	     here if the prevailing decl allows for this.
+ 	     ???  Maybe we should simply fold all stmts.  */
+ 	  if (TREE_CODE (*opp) == MEM_REF
+ 	      && TREE_CODE (TREE_OPERAND (*opp, 0)) == ADDR_EXPR
+ 	      && integer_zerop (TREE_OPERAND (*opp, 1))
+ 	      && (TREE_THIS_VOLATILE (*opp)
+ 		  == TREE_THIS_VOLATILE
+ 		       (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0)))
+ 	      && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*opp, 1)))
+ 	      && (TREE_TYPE (*opp)
+ 		  == TREE_TYPE (TREE_TYPE (TREE_OPERAND (*opp, 1))))
+ 	      && (TREE_TYPE (*opp)
+ 		  == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0))))
+ 	    *opp = TREE_OPERAND (TREE_OPERAND (*opp, 0), 0);
  	}
        if (is_gimple_call (stmt))
  	{



More information about the Gcc-patches mailing list