[PATCH] S/390: Fix PR 36745: ICE in gen_reg_rtx, at emit-rtl.c:868

Andreas Krebbel Andreas.Krebbel@de.ibm.com
Fri Jul 11 08:27:00 GMT 2008


Hello,

when a symbol ref is moved to a gpr compiling with -fPIC the address
of the symbol is loaded from a got entry.  To do so a load from memory
is generated which needs a temporary register.  For this register a
new pseudo is allocated during RTL expansion.

RTL expansion marks the target register of the load with a REG_EQUAL
note containing the symbol_ref.  That way optimizers exploiting the
REG_EQUAL note might again create SYMBOL_REF -> register moves which
have to be expanded as above.  This happens in the testcase for the
parameter of the inline assembly.  GCSE replaces the register loaded
with the address of _q_value with the SYMBOL_REF from the REG_EQUAL
note.  Reload then generates an input reload for the inline assembly
moving the SYMBOL_REF to a GPR again.  Since no new pseudos are
allowed to be allocated during reload this fails with an ICE in
gen_rtx_reg.

The attached patch changes legitimize_pic_address to use the target
register of the move as temporary if no new pseudos are allowed.
Since we need the temporary register to be used as part of an address
we have the usual problem of not being able to use r0 for that.  The
patch therefore also adds a secondary reload requesting a scratch
register in that case.

I'll wait committing the patch until next week to give Uli a chance to
intervene.

Bootstrapped on s390 and s390x.
No new regressions. Testcase is fixed.

Bye,

-Andreas-



2008-07-11  Andreas Krebbel  <krebbel1@de.ibm.com>

	PR target/36745
	* config/s390/s390.c: (s390_secondary_reload): Add a secondary
	reload for symbol refs moved to r0 with -fPIC.
	(legitimize_pic_address): Use the target register as temporary
	reg if possible.
	(emit_symbolic_move): Adjust comment.
	* config/s390/s390.md (reloadsi_PIC_addr, reloaddi_PIC_addr):
	New expanders.

2008-07-11  Andreas Krebbel  <krebbel1@de.ibm.com>

	PR target/36745
	* g++.dg/torture/pr36745.C: New testcase.


Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c.orig	2008-07-10 13:23:22.000000000 +0200
+++ gcc/config/s390/s390.c	2008-07-11 09:30:59.000000000 +0200
@@ -3026,6 +3026,14 @@ s390_secondary_reload (bool in_p, rtx x,
 	}
     }
 
+  /* A scratch address register is needed when a SYMBOL_REF is copied
+     to r0 compiling with -fPIC.  In other cases the target register
+     might be used as temporary (see legitimize_pic_address).  */
+  if (in_p && GET_CODE (x) == SYMBOL_REF && flag_pic == 2 && class != ADDR_REGS)
+    sri->icode = (TARGET_64BIT ?
+		  CODE_FOR_reloaddi_PIC_addr :
+		  CODE_FOR_reloadsi_PIC_addr);
+
   /* Either scratch or no register needed.  */
   return NO_REGS;
 }
@@ -3272,7 +3280,10 @@ legitimize_pic_address (rtx orig, rtx re
           /* If the GOT offset might be >= 4k, we determine the position
              of the GOT entry via a PC-relative LARL (@GOTENT).  */
 
-          rtx temp = gen_reg_rtx (Pmode);
+          rtx temp = reg ? reg : gen_reg_rtx (Pmode);
+
+	  gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
+		      || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
 
           new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
           new = gen_rtx_CONST (Pmode, new);
@@ -3287,7 +3298,10 @@ legitimize_pic_address (rtx orig, rtx re
           /* If the GOT offset might be >= 4k, we have to load it
              from the literal pool (@GOT).  */
 
-          rtx temp = gen_reg_rtx (Pmode);
+          rtx temp = reg ? reg : gen_reg_rtx (Pmode);
+
+	  gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
+		      || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
 
 	  if (reload_in_progress || reload_completed)
 	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
@@ -3707,7 +3721,10 @@ legitimize_tls_address (rtx addr, rtx re
   return new;
 }
 
-/* Emit insns to move operands[1] into operands[0].  */
+/* Emit insns making the address in operands[1] valid for a standard
+   move to operands[0].  operands[1] is replaced by an address which
+   should be used instead of the former RTX to emit the move
+   pattern.  */
 
 void
 emit_symbolic_move (rtx *operands)
Index: gcc/testsuite/g++.dg/torture/pr36745.C
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/g++.dg/torture/pr36745.C	2008-07-10 13:23:34.000000000 +0200
@@ -0,0 +1,119 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC" } */
+/* { dg-require-effective-target fpic } */
+typedef long unsigned int size_t;
+class QBasicAtomicInt
+{
+public:
+  int _q_value;
+  inline bool operator== (int value) const
+  {
+  }
+  bool ref ();
+  bool deref ();
+};
+inline bool
+QBasicAtomicInt::ref ()
+{
+  __asm__ ("": "=m" (_q_value): :);
+  return true;
+}
+
+namespace std
+{
+  using::size_t;
+}
+extern "C++"
+{
+  inline void *operator new (std::size_t, void *__p)
+  {
+    return __p;
+  }
+}
+struct QMapData
+{
+  QBasicAtomicInt ref;
+  static QMapData shared_null;
+};
+template < class Key, class T > class QMap
+{
+  QMapData *d;
+public: inline QMap ():d (&QMapData::shared_null)
+  {
+  }
+  inline ~ QMap ()
+  {
+    if (!d->ref.deref ())
+      freeData (d);
+  }
+  void freeData (QMapData * d);
+};
+struct QVectorData
+{
+  static QVectorData shared_null;
+};
+template < typename T > struct QVectorTypedData
+{
+  QBasicAtomicInt ref;
+};
+template < typename T > class QVector
+{
+  union
+  {
+    QVectorData *p;
+    QVectorTypedData < T > *d;
+  };
+public: inline QVector ():p (&QVectorData::shared_null)
+  {
+    d->ref.ref ();
+  }
+  inline void detach ()
+  {
+    if (d->ref == 1)
+      detach_helper ();
+  }
+  inline T *data ()
+  {
+    detach ();
+  }
+  T & operator[](int i);
+  void detach_helper ();
+  void realloc ();
+};
+template < typename T > void QVector < T >::detach_helper ()
+{
+  realloc ();
+}
+
+template < typename T > inline T & QVector < T >::operator[](int i)
+{
+  return data ()[i];
+}
+template < typename T > void QVector < T >::realloc ()
+{
+  T *j, *i;
+  i->~T ();
+  while (j-- == i)
+    new (j) T;
+}
+
+void
+mergeInto (QVector < int >*a)
+{
+};
+struct QRegExpAutomatonState
+{
+  QVector < int >outs;
+  QMap < int, int >reenter;
+  QMap < int, int >anchors;
+};
+class QRegExpEngine
+{
+  void addCatTransitions ();
+  QVector < QRegExpAutomatonState > s;
+};
+void
+QRegExpEngine::addCatTransitions ()
+{
+  mergeInto (&s[2].outs);
+}
Index: gcc/config/s390/s390.md
===================================================================
--- gcc/config/s390/s390.md.orig	2008-07-10 13:23:22.000000000 +0200
+++ gcc/config/s390/s390.md	2008-07-10 13:23:34.000000000 +0200
@@ -1175,6 +1175,16 @@
   DONE;
 })
 
+(define_expand "reload<mode>_PIC_addr"
+  [(parallel [(match_operand   0 "register_operand" "=d")
+	      (match_operand   1 "larl_operand"     "")
+	      (match_operand:P 2 "register_operand" "=a")])]
+  ""
+{
+  rtx new = legitimize_pic_address (operands[1], operands[2]);
+  emit_move_insn (operands[0], new);
+})
+
 ;
 ; movdi instruction pattern(s).
 ;



More information about the Gcc-patches mailing list