[PATCH] Avoid invalid constant pool address dwarf2out optimization

Jakub Jelinek jakub@redhat.com
Wed Jan 27 14:20:00 GMT 2010


Hi!

As discussed in PR42861, I've discovered that mem_loc_descriptor
CONSTANT_POOL_ADDRESS_P symbol handling is wrong.  The problem is
that replacing a symbol_ref/u with a symbol_ref from the constant pool (if
there is any) is incorrect, those two aren't equivalent.  What actually
is equivalent is (mem/u (symbol_ref/u)) and the (symbol_ref) that is
contained in the constant pool, without throwing away the MEM we
are one indirection wrong.  As a MEM is generally more usable in location
debug info than something else (if we need to dereference, we can
DW_OP_deref any time, but the other way (DW_OP_stack_value) is only
Dwarf4 and only available for toplevel locations, not embedded deeper in the
expression, the patch below just kills that "optimization" altogether
(const_ok_for_output will handle properly marked vs. unmarked constant pool
symbols) and only if for a MEM mem_loc_descriptor fails to describe
its address uses avoid_constant_pool_reference/another mem_loc_descriptor
call to see if it can be expressed as a constant instead.

Bootstrapped/regtested on {i686,x86_64,powerpc,powerpc64,s390,s390x}-linux.
Ok for trunk?

2010-01-27  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2out.c (mem_loc_descriptor): Remove special casing of
	CONSTANT_POOL_ADDRESS_P SYMBOL_REFs.  If for MEM recursive call
	on MEM's address failed, try avoid_constant_pool_reference and
	recurse if it returned something different.
	(loc_descriptor): If for MEM mem_loc_descriptor failed on the
	address, try avoid_constant_pool_reference and recurse if it
	returned something different.
	(dw_loc_list_1): If for MEM mem_loc_descriptor failed on the
	address and avoid_constant_pool_reference returned something
	different, don't set have_address.

--- gcc/dwarf2out.c.jj	2010-01-20 13:17:57.000000000 +0100
+++ gcc/dwarf2out.c	2010-01-26 15:03:37.000000000 +0100
@@ -11069,6 +11069,12 @@ mem_loc_descriptor (rtx rtl, enum machin
 	mem_loc_result = tls_mem_loc_descriptor (rtl);
       if (mem_loc_result != 0)
 	add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
+      else
+	{
+	  rtx new_rtl = avoid_constant_pool_reference (rtl);
+	  if (new_rtl != rtl)
+	    return mem_loc_descriptor (new_rtl, mode, initialized);
+	}
       break;
 
     case LO_SUM:
@@ -11082,34 +11088,6 @@ mem_loc_descriptor (rtx rtl, enum machin
 	 pool.  */
     case CONST:
     case SYMBOL_REF:
-      /* Alternatively, the symbol in the constant pool might be referenced
-	 by a different symbol.  */
-      if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl))
-	{
-	  bool marked;
-	  rtx tmp = get_pool_constant_mark (rtl, &marked);
-
-	  if (GET_CODE (tmp) == SYMBOL_REF)
-	    {
-	      rtl = tmp;
-	      if (CONSTANT_POOL_ADDRESS_P (tmp))
-		get_pool_constant_mark (tmp, &marked);
-	      else
-		marked = true;
-	    }
-
-	  /* If all references to this pool constant were optimized away,
-	     it was not output and thus we can't represent it.
-	     FIXME: might try to use DW_OP_const_value here, though
-	     DW_OP_piece complicates it.  */
-	  if (!marked)
-	    {
-	      expansion_failed (NULL_TREE, rtl,
-				"Constant was removed from constant pool.\n");
-	      return 0;
-	    }
-	}
-
       if (GET_CODE (rtl) == SYMBOL_REF
 	  && SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
 	{
@@ -11700,6 +11678,12 @@ loc_descriptor (rtx rtl, enum machine_mo
 				       initialized);
       if (loc_result == NULL)
 	loc_result = tls_mem_loc_descriptor (rtl);
+      if (loc_result == NULL)
+	{
+	  rtx new_rtl = avoid_constant_pool_reference (rtl);
+	  if (new_rtl != rtl)
+	    loc_result = loc_descriptor (new_rtl, mode, initialized);
+	}
       break;
 
     case CONCAT:
@@ -11971,10 +11955,19 @@ dw_loc_list_1 (tree loc, rtx varloc, int
 	  mode = GET_MODE (varloc);
 	  if (MEM_P (varloc))
 	    {
-	      varloc = XEXP (varloc, 0);
-	      have_address = 1;
+	      rtx addr = XEXP (varloc, 0);
+	      descr = mem_loc_descriptor (addr, mode, initialized);
+	      if (descr)
+		have_address = 1;
+	      else
+		{
+		  rtx x = avoid_constant_pool_reference (varloc);
+		  if (x != varloc)
+		    descr = mem_loc_descriptor (x, mode, initialized);
+		}
 	    }
-	  descr = mem_loc_descriptor (varloc, mode, initialized);
+	  else
+	    descr = mem_loc_descriptor (varloc, mode, initialized);
 	}
       else
 	return 0;

	Jakub



More information about the Gcc-patches mailing list