This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR18683: Bad C++/cgraph/middle-end/rs6000 interaction (fix2)

PR middle-end/18683 is a critical ICE-on-valid regression in current
mainline affecting C++ on powerpc targets.  It is caused by an obscure
interaction between the rs6000 backend and the g++ front-end during
local register allocation.  The unfortunate sequence of events (described
in the bugzilla PR) causes reg_renumber to be reset to zero during
register allocation, which leads to a segmentation fault.

There are several possible ways to tackle this issue...

In the patch below, the solution is to prevent reg_class from calling
make_decl_rtl during local register allocation in the rs6000 backend.
The cause is that the function current_file_function_operand, which
checks whether an symbol reference is local to the current translation
unit, attempts to compare against current_function_decl's DECL_RTL.
It turns out that for the testcase in the PR, we've not yet generated
an assembler name for this C++ template (unless we've been generating
debugging dumps!?), which invokes make_decl_rtl which has the
unanticipated side-effect of reseting the reg_renumber array to zero.

The work-around (and micro-optimization) below is that a symbol
reference (probably?) can't refer to the current function if we haven't
yet generated an assembler name for it.  This is implemented by testing
DECL_RTL_SET_P before referencing DECL_RTL.

In addition to this change, I'll also submit another change to the
middle-end that is also sufficient to resolve the failure.  However
both of these fixes may possibly be papering over a more fundamental
problem in the interaction between g++ and cgraph; should we guarantee
that current_function_decl has an assembler name before generating RTL?

The following patch has been tested on powerpc-unknown-linux-gnu with
a full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?

2004-12-20  Roger Sayle  <>

	PR middle-end/18683
	* config/rs6000/rs6000.c (current_file_function_operand): Only check
	current_function_decl's DECL_RTL if it has already been set.

	* g++.dg/opt/pr18683-1.C: New test case.

Index: config/rs6000/rs6000.c
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.765
diff -c -3 -p -r1.765 rs6000.c
*** config/rs6000/rs6000.c	14 Dec 2004 18:43:48 -0000	1.765
--- config/rs6000/rs6000.c	20 Dec 2004 05:54:02 -0000
*************** current_file_function_operand (rtx op,
*** 2960,2966 ****
    return (GET_CODE (op) == SYMBOL_REF
  	  && (SYMBOL_REF_LOCAL_P (op)
! 	      || (op == XEXP (DECL_RTL (current_function_decl), 0))));

  /* Return 1 if this operand is a valid input for a move insn.  */
--- 2960,2967 ----
    return (GET_CODE (op) == SYMBOL_REF
  	  && (SYMBOL_REF_LOCAL_P (op)
! 	      || (DECL_RTL_SET_P (current_function_decl)
! 		  && op == XEXP (DECL_RTL (current_function_decl), 0))));

  /* Return 1 if this operand is a valid input for a move insn.  */

// PR middle-end/18683
// { dg-do compile }
// { dg-options "-O0" }

template<typename _CharT>
struct basic_ostream
  basic_ostream& operator<<(int __n);

extern basic_ostream<char>  cout;

template<int> struct linear_congruential
  template<class CharT>
  friend basic_ostream<CharT>&
  operator<<(basic_ostream<CharT>& os,
             const linear_congruential& lcg)
    return os << 1;

void instantiate_all()
  linear_congruential<0> lcf;
  cout << lcf;

Roger Sayle,                         E-mail:
OpenEye Scientific Software,         WWW:
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]