RTL type checking

Zack Weinberg zack@bitmover.com
Fri Aug 27 16:44:00 GMT 1999


This patch implements type checking for RTL structures, and fixes some
(not all!) of the bugs thus exposed.  On x86, bootstrap gets as far as
the EH support in libgcc.a before aborting with a bug I am unable to fix.

If you bootstrap with gcc, the stage1 compiler is mind-bogglingly slow
unless you force optimization back on.  I never get to stage2, so I
dunno how slow it is.

Some of the fixes in here may not make terribly much sense.  If you
are going to transform an RTX from one type to another - REG to MEM,
for example - you must extract all the info you cared about from the
REG before changing it, and initialize it as a MEM only after changing
it.  This also comes up when deleting insns by turning them into
NOTE_INSN_DELETED notes.

The patch introduces a series of new accessor macros: X0INT, X0EXP,
etc.  These are just like XINT, XEXP, etc. except that they check for
a '0' slot instead of an 'i' slot or whatever.  In the future, we
probably want to replace '0' with a series of format letters that
encode type info as well as pass-specificity.

The bug I can't fix is:

./xgcc -B./ -O2 -DIN_GCC -W -Wall -O2 -I./include -fPIC -g1 \
  -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED -I. -I../../../src/egcs/gcc \
  -I../../../src/egcs/gcc/config -I../../../src/egcs/gcc/../include \
  -c ../../../src/egcs/gcc/cp/new1.cc -DL_op_newnt -o opnewnt.o
cp/new1.cc: In function `void * operator new(unsigned int, const nothrow_t &)':
cp/new1.cc:60: RTL check: expected elt 0 type 'i' or 'n', have 's'
	       (rtx symbol_ref)
cp/new1.cc:60: Internal compiler error in `expand_fixup_region_end',
	       at except.c:1547

I'll post more detailed analysis to -bugs.

zw

1999-08-27 14:49 -0700  Zack Weinberg  <zack@bitmover.com>

	* rtl.h (RTL_CHECK1, RTL_CHECK2): New macros, type check
	access against format if ENABLE_CHECKING is defined.
	(RTVEC_ELT): Bounds check access if ENABLE_CHECKING is
	defined.
	(XWINT, XINT, XSTR, XEXP, XVEC, XMODE, XBITMAP, XBBDEF):
	Define in terms of RTL_CHECK1/RTL_CHECK2 as appropriate.
	(XVECEXP, XVECLEN): Define in terms of RTVEC_ELT,
	GET_NUM_ELEM, and XVEC.
	(X0WINT, X0INT, X0STR, X0EXP, X0VEC, X0MODE, X0BITMAP, X0TREE,
	X0BBDEF, X0ADVFLAGS): New macros.  Type check for '0' slot
	instead of the normal slot type(s).
	(ADDR_DIFF_VEC_FLAGS): Use X0ADVFLAGS.
	(NOTE_SOURCE_FILE): Use X0STR.
	(NOTE_BLOCK_NUMBER, NOTE_EH_HANDLER, LABEL_NUSES,
	MEM_ALIAS_SET): Use X0INT.
	(NOTE_RANGE_INFO, NOTE_LIVE_INFO, NOTE_BASIC_BLOCK,
	JUMP_LABEL, LABEL_REFS, LABEL_NEXTREF, CONTAINING_INSN): Use
	X0EXP.

	* rtl.c (copy_rtx, copy_most_rtx): Copy '0' slots using
	X0WINT.
	(rtl_check_failed_bounds, rtl_check_failed_type1,
	rtl_check_failed_type2, rtvec_check_failed_bounds): New
	functions.

	* cse.c (canon_hash): Use XWINT for 'w' slots of a
	CONST_DOUBLE.
	(cse_insn): Decrement LABEL_NUSES for the target before
	deleting a jump, not after.
	* emit_rtl.c (gen_rtx_CONST_DOUBLE): Fill in slot 1 with
	X0EXP.
	* final.c (alter_subreg): When changing a SUBREG to a REG,
	compute the new regno before changing the RTX code, and set it
	in the RTX after changing the code.
	* flow.c (count_basic_blocks): Access 'w' slot with XWINT.
	(find_basic_blocks_1): Likewise.
	(delete_eh_regions): Use NOTE_EH_HANDLER not
	CODE_LABEL_NUMBER.
	* function.c (put_reg_into_stack): Change REG to MEM before
	initializing it as a MEM.
	(gen_mem_addressof): Likewise.
	(fixup_var_refs_insns): Save REG_NOTES of the insn so we can
	still use them after the insn is deleted.
	* integrate.c (copy_rtx_and_substitute): Copy '0' slots with
	X0WINT.
	* local-alloc.c (update_equiv_regs): Zap REG_NOTES before
	deleting an insn, not after.
	(block_alloc): Access PATTERN (insn) only if it is of class
	'i', and only if we need it (not REGISTER_CONSTRAINTS).
	Correct test for may_save_copy with REGISTER_CONSTRAINTS
	defined.
	* loop.c (check_dbra_loop): Verify bl->biv->add_val is a
	CONST_INT before using INTVAL on it.
	* print_rtl.c (print_rtx): Use X0STR.
	* real.h (CONST_DOUBLE_CHAIN): Use X0EXP.
	* regmove.c (fixup_match_1): Access PATTERN(insn) only if insn
	is class 'i'.
	* reload.c (loc_mentioned_in_p): Don't use XEXP when doing
	comparisons on RTL pointers.
	* reload1.c (reload): Turn REG into MEM before initializing it
	as a MEM.
	* varasm.c (mark_constant_pool): Skip CONST_DOUBLES in loop
	inspecting labels.
	* config/i386/i386.md (decrement_and_branch_until_zero+1
	anonymous insn): Fix typo.

===================================================================
Index: rtl.h
--- rtl.h	1999/08/27 20:36:56	1.123
+++ rtl.h	1999/08/27 21:48:41
@@ -222,20 +222,87 @@ typedef struct rtvec_def{
 
 /* General accessor macros for accessing the fields of an rtx.  */
 
-#define XWINT(RTX, N)	((RTX)->fld[N].rtwint)			/* w */
-#define XINT(RTX, N)	((RTX)->fld[N].rtint)			/* i,n */
-#define XSTR(RTX, N)	((RTX)->fld[N].rtstr)			/* s,S */
-#define XEXP(RTX, N)	((RTX)->fld[N].rtx)			/* e,u */
-#define XVEC(RTX, N)	((RTX)->fld[N].rtvec)			/* E,V */
-#define XVECLEN(RTX, N)	((RTX)->fld[N].rtvec->num_elem)		/* E,V */
-#define XMODE(RTX, N)	((RTX)->fld[N].rttype)			/* M */
-#define XBITMAP(RTX, N) ((RTX)->fld[N].rtbit)			/* b */
-#define XTREE(RTX, N)   ((RTX)->fld[N].rttree)			/* t */
-#define XBBDEF(RTX, N)	((RTX)->fld[N].bb)			/* B */
+#if defined ENABLE_CHECKING  && (__GNUC__ > 2 || __GNUC_MINOR__ > 6)
+/* The bit with a star outside the statement expr and an & inside is
+   so that N can be evaluated only once.  */
+#define RTL_CHECK1(RTX, N, C1)						\
+(*({ rtx _rtx = RTX; int _n = N;					\
+     enum rtx_code _code = GET_CODE (_rtx);				\
+     if (_n < 0 || _n >= GET_RTX_LENGTH (_code))			\
+       rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,		\
+				__PRETTY_FUNCTION__);			\
+     if (GET_RTX_FORMAT(_code)[_n] != C1)				\
+       rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__,	\
+			       __PRETTY_FUNCTION__);			\
+     &_rtx->fld[_n]; }))
+
+#define RTL_CHECK2(RTX, N, C1, C2)					\
+(*({ rtx _rtx = RTX; int _n = N;					\
+     enum rtx_code _code = GET_CODE (_rtx);				\
+     if (_n < 0 || _n >= GET_RTX_LENGTH (_code))			\
+       rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,		\
+				__PRETTY_FUNCTION__);			\
+     if (GET_RTX_FORMAT(_code)[_n] != C1				\
+	 && GET_RTX_FORMAT(_code)[_n] != C2)				\
+       rtl_check_failed_type2 (_rtx, _n, C1, C2, __FILE__, __LINE__,	\
+			       __PRETTY_FUNCTION__);			\
+     &_rtx->fld[_n]; }))
+
+#define RTVEC_ELT(RTVEC, I)						\
+(*({ rtvec _rtvec = RTVEC; int _i = I;					\
+     if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec))				\
+       rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__,	\
+				  __PRETTY_FUNCTION__);			\
+     &_rtvec->elem[_i]; }))
+
+extern void rtl_check_failed_bounds PROTO((rtx, int,
+					   const char *, int, const char *))
+    ATTRIBUTE_NORETURN;
+extern void rtl_check_failed_type1 PROTO((rtx, int, int,
+					  const char *, int, const char *))
+    ATTRIBUTE_NORETURN;
+extern void rtl_check_failed_type2 PROTO((rtx, int, int, int,
+					  const char *, int, const char *))
+    ATTRIBUTE_NORETURN;
+extern void rtvec_check_failed_bounds PROTO((rtvec, int,
+					     const char *, int, const char *))
+    ATTRIBUTE_NORETURN;
+
+#else   /* not ENABLE_CHECKING */
+
+#define RTL_CHECK1(RTX, N, C1)     ((RTX)->fld[N])
+#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->fld[N])
+#define RTVEC_ELT(RTVEC, I)	   ((RTVEC)->elem[I])
+
+#endif
+
+#define XWINT(RTX, N)	(RTL_CHECK1(RTX, N, 'w').rtwint)
+#define XINT(RTX, N)	(RTL_CHECK2(RTX, N, 'i', 'n').rtint)
+#define XSTR(RTX, N)	(RTL_CHECK2(RTX, N, 's', 'S').rtstr)
+#define XEXP(RTX, N)	(RTL_CHECK2(RTX, N, 'e', 'u').rtx)
+#define XVEC(RTX, N)	(RTL_CHECK2(RTX, N, 'E', 'V').rtvec)
+#define XMODE(RTX, N)	(RTL_CHECK1(RTX, N, 'M').rttype)
+#define XBITMAP(RTX, N) (RTL_CHECK1(RTX, N, 'b').rtbit)
+#define XTREE(RTX, N)   (RTL_CHECK1(RTX, N, 't').rttree)
+#define XBBDEF(RTX, N)	(RTL_CHECK1(RTX, N, 'B').bb)
+
+#define XVECEXP(RTX, N, M)	RTVEC_ELT (XVEC (RTX, N), M)
+#define XVECLEN(RTX, N)		GET_NUM_ELEM (XVEC (RTX, N))
+
+/* These are like XWINT, etc. except that they expect a '0' field instead
+   of the normal type code.  */
+
+#define X0WINT(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rtwint)
+#define X0INT(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rtint)
+#define X0STR(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rtstr)
+#define X0EXP(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rtx)
+#define X0VEC(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rtvec)
+#define X0MODE(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rttype)
+#define X0BITMAP(RTX, N)   (RTL_CHECK1(RTX, N, '0').rtbit)
+#define X0TREE(RTX, N)	   (RTL_CHECK1(RTX, N, '0').rttree)
+#define X0BBDEF(RTX, N)	   (RTL_CHECK1(RTX, N, '0').bb)
+#define X0ADVFLAGS(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_addr_diff_vec_flags)
 
-#define RTVEC_ELT(RTVEC, I)	((RTVEC)->elem[I])
-#define XVECEXP(RTX,N,M)	RTVEC_ELT (XVEC (RTX, N), M)
-
 
 /* ACCESS MACROS for particular fields of insns.  */
 
@@ -357,7 +424,7 @@ typedef struct rtvec_def{
 
 #define REG_NOTES(INSN)	XEXP(INSN, 6)
 
-#define ADDR_DIFF_VEC_FLAGS(RTX) ((RTX)->fld[4].rt_addr_diff_vec_flags)
+#define ADDR_DIFF_VEC_FLAGS(RTX) X0ADVFLAGS(RTX, 4)
 
 /* Don't forget to change reg_note_name in rtl.c.  */
 enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
@@ -404,11 +471,12 @@ extern const char * const reg_note_name[
    The NOTE_INSN_RANGE_{START,END} and NOTE_INSN_LIVE notes record their
    information as a rtx in the field.  */
 
-#define NOTE_SOURCE_FILE(INSN)  ((INSN)->fld[3].rtstr)
-#define NOTE_BLOCK_NUMBER(INSN) ((INSN)->fld[3].rtint)
-#define NOTE_RANGE_INFO(INSN)   ((INSN)->fld[3].rtx)
-#define NOTE_LIVE_INFO(INSN)    ((INSN)->fld[3].rtx)
-#define NOTE_BASIC_BLOCK(INSN)	((INSN)->fld[3].bb)
+#define NOTE_SOURCE_FILE(INSN) 	X0STR(INSN, 3)
+#define NOTE_BLOCK_NUMBER(INSN)	X0INT(INSN, 3)
+#define NOTE_EH_HANDLER(INSN)	X0INT(INSN, 3)
+#define NOTE_RANGE_INFO(INSN)  	X0EXP(INSN, 3)
+#define NOTE_LIVE_INFO(INSN)   	X0EXP(INSN, 3)
+#define NOTE_BASIC_BLOCK(INSN)	X0EXP(INSN, 3)
 
 /* If the NOTE_BLOCK_NUMBER field gets a -1, it means create a new
    block node for a live range block.  */
@@ -488,7 +556,7 @@ extern const char * const note_insn_name
 
 /* In jump.c, each label contains a count of the number
    of LABEL_REFs that point at it, so unused labels can be deleted.  */
-#define LABEL_NUSES(LABEL) ((LABEL)->fld[5].rtint)
+#define LABEL_NUSES(LABEL) X0INT(LABEL, 5)
 
 /* The original regno this ADDRESSOF was built for.  */
 #define ADDRESSOF_REGNO(RTX) XINT(RTX, 1)
@@ -499,24 +567,24 @@ extern const char * const note_insn_name
 /* In jump.c, each JUMP_INSN can point to a label that it can jump to,
    so that if the JUMP_INSN is deleted, the label's LABEL_NUSES can
    be decremented and possibly the label can be deleted.  */
-#define JUMP_LABEL(INSN)   ((INSN)->fld[7].rtx)
+#define JUMP_LABEL(INSN)   X0EXP(INSN, 7)
 
 /* Once basic blocks are found in flow.c,
    each CODE_LABEL starts a chain that goes through
    all the LABEL_REFs that jump to that label.
    The chain eventually winds up at the CODE_LABEL; it is circular.  */
-#define LABEL_REFS(LABEL) ((LABEL)->fld[6].rtx)
+#define LABEL_REFS(LABEL) X0EXP(LABEL, 6)
 
 /* This is the field in the LABEL_REF through which the circular chain
    of references to a particular label is linked.
    This chain is set up in flow.c.  */
 
-#define LABEL_NEXTREF(REF) ((REF)->fld[1].rtx)
+#define LABEL_NEXTREF(REF) X0EXP(REF, 1)
 
 /* Once basic blocks are found in flow.c,
    Each LABEL_REF points to its containing instruction with this field.  */
 
-#define CONTAINING_INSN(RTX) ((RTX)->fld[2].rtx)
+#define CONTAINING_INSN(RTX) X0EXP(RTX, 2)
 
 /* For a REG rtx, REGNO extracts the register number.  */
 
@@ -601,7 +669,7 @@ extern const char * const note_insn_name
    some front-ends, these numbers may correspond in some way to types,
    or other language-level entities, but they need not, and the
    back-end makes no such assumptions.  */
-#define MEM_ALIAS_SET(RTX) (XINT (RTX, 1))
+#define MEM_ALIAS_SET(RTX) X0INT(RTX, 1)
 
 /* For a LABEL_REF, 1 means that this reference is to a label outside the
    loop containing the reference.  */
===================================================================
Index: rtl.c
--- rtl.c	1999/08/27 20:36:54	1.38
+++ rtl.c	1999/08/27 21:48:42
@@ -387,7 +387,6 @@ copy_rtx (orig)
 	    XEXP (copy, i) = copy_rtx (XEXP (orig, i));
 	  break;
 
-	case '0':
 	case 'u':
 	  XEXP (copy, i) = XEXP (orig, i);
 	  break;
@@ -428,6 +427,11 @@ copy_rtx (orig)
 	  XSTR (copy, i) = XSTR (orig, i);
 	  break;
 
+	case '0':
+	  /* Copy this through the wide int field; that's safest. */
+	  X0WINT (copy, i) = X0WINT (orig, i);
+	  break;
+	  
 	default:
 	  abort ();
 	}
@@ -487,7 +491,6 @@ copy_most_rtx (orig, may_share)
 	    XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
 	  break;
 
-	case '0':
 	case 'u':
 	  XEXP (copy, i) = XEXP (orig, i);
 	  break;
@@ -522,6 +525,11 @@ copy_most_rtx (orig, may_share)
 	  XSTR (copy, i) = XSTR (orig, i);
 	  break;
 
+	case '0':
+	  /* Copy this through the wide int field; that's safest. */
+	  X0WINT (copy, i) = X0WINT (orig, i);
+	  break;
+
 	default:
 	  abort ();
 	}
@@ -934,6 +942,65 @@ read_rtx (infile)
   return return_rtx;
 }
 
+#if defined ENABLE_CHECKING && (__GNUC__ > 2 || __GNUC_MINOR__ > 6)
+void
+rtl_check_failed_bounds (r, n, file, line, func)
+    rtx r;
+    int n;
+    const char *file;
+    int line;
+    const char *func;
+{
+  error ("RTL check: access of elt %d of `%s' with last elt %d",
+	 n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r))-1);
+  fancy_abort (file, line, func);
+}
+
+void
+rtl_check_failed_type1 (r, n, c1, file, line, func)
+    rtx r;
+    int n;
+    int c1;
+    const char *file;
+    int line;
+    const char *func;
+{
+  error ("RTL check: expected elt %d type '%c', have '%c' (rtx %s)",
+	 n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)));
+  fancy_abort (file, line, func);
+}
+
+void
+rtl_check_failed_type2 (r, n, c1, c2, file, line, func)
+    rtx r;
+    int n;
+    int c1;
+    int c2;
+    const char *file;
+    int line;
+    const char *func;
+{
+  error ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s)",
+	 n, c1, c2,
+	 GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE(r)));
+  fancy_abort (file, line, func);
+}
+
+/* XXX Maybe print the vector?  */
+void
+rtvec_check_failed_bounds (r, n, file, line, func)
+    rtvec r;
+    int n;
+    const char *file;
+    int line;
+    const char *func;
+{
+  error ("RTL check: access of elt %d of vector with last elt %d",
+	 n, GET_NUM_ELEM (r)-1);
+  fancy_abort (file, line, func);
+}
+#endif /* ENABLE_CHECKING */
+
 /* These are utility functions used by fatal-error functions all over the
    code.  rtl.c happens to be linked by all the programs that need them,
    so these are here.  In the future we want to break out all error handling
@@ -962,11 +1029,10 @@ trim_filename (name)
 }
 
 /* Report an internal compiler error in a friendly manner and without
-   dumping core.  There are two versions because __FUNCTION__ isn't
-   available except in gcc 2.7 and later.  */
+   dumping core.  */
 
 extern void fatal PVPROTO ((const char *, ...))
-    ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+  ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
 
 void
 fancy_abort (file, line, function)
===================================================================
Index: cse.c
--- cse.c	1999/08/25 13:37:44	1.82
+++ cse.c	1999/08/27 21:32:10
@@ -2166,7 +2166,7 @@ canon_hash (x, mode)
       if (GET_MODE (x) != VOIDmode)
 	for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
 	  {
-	    unsigned tem = XINT (x, i);
+	    unsigned HOST_WIDE_INT tem = XWINT (x, i);
 	    hash += tem;
 	  }
       else
@@ -7376,13 +7376,13 @@ cse_insn (insn, libcall_insn)
 	 the insn.  */
       else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx)
 	{
+	  /* One less use of the label this insn used to jump to.  */
+	  if (JUMP_LABEL (insn) != 0)
+	    --LABEL_NUSES (JUMP_LABEL (insn));
 	  PUT_CODE (insn, NOTE);
 	  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 	  NOTE_SOURCE_FILE (insn) = 0;
 	  cse_jumps_altered = 1;
-	  /* One less use of the label this insn used to jump to.  */
-	  if (JUMP_LABEL (insn) != 0)
-	    --LABEL_NUSES (JUMP_LABEL (insn));
 	  /* No more processing for this set.  */
 	  sets[i].rtl = 0;
 	}
===================================================================
Index: emit-rtl.c
--- emit-rtl.c	1999/08/24 12:04:55	1.72
+++ emit-rtl.c	1999/08/27 21:32:10
@@ -217,7 +217,7 @@ gen_rtx_CONST_DOUBLE (mode, arg0, arg1, 
 
   PUT_MODE (r, mode);
   XEXP (r, 0) = arg0;
-  XEXP (r, 1) = NULL_RTX;
+  X0EXP (r, 1) = NULL_RTX;
   XWINT (r, 2) = arg1;
   XWINT (r, 3) = arg2;
 
===================================================================
Index: final.c
--- final.c	1999/08/26 05:18:41	1.86
+++ final.c	1999/08/27 21:32:13
@@ -3091,6 +3091,7 @@ alter_subreg (x)
 
   if (GET_CODE (y) == REG)
     {
+      int regno;
       /* If the word size is larger than the size of this register,
 	 adjust the register number to compensate.  */
       /* ??? Note that this just catches stragglers created by/for
@@ -3098,13 +3099,14 @@ alter_subreg (x)
 	 earlier, or kept _all_ subregs until now and eliminate
 	 gen_lowpart and friends.  */
 
-      PUT_CODE (x, REG);
 #ifdef ALTER_HARD_SUBREG
-      REGNO (x) = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
-				    GET_MODE (y), REGNO (y));
+      regno = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
+				GET_MODE (y), REGNO (y));
 #else
-      REGNO (x) = REGNO (y) + SUBREG_WORD (x);
+      regno = REGNO (y) + SUBREG_WORD (x);
 #endif
+      PUT_CODE (x, REG);
+      REGNO (x) = regno;
       /* This field has a different meaning for REGs and SUBREGs.  Make sure
 	 to clear it!  */
       x->used = 0;
===================================================================
Index: flow.c
--- flow.c	1999/08/26 05:18:41	1.141
+++ flow.c	1999/08/27 21:32:14
@@ -474,7 +474,7 @@ count_basic_blocks (f)
       if (code == CALL_INSN)
 	{
 	  rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-	  int region = (note ? XINT (XEXP (note, 0), 0) : 1);
+	  int region = (note ? XWINT (XEXP (note, 0), 0) : 1);
 	  prev_call = insn;
 	  call_had_abnormal_edge = 0;
 
@@ -554,7 +554,7 @@ find_basic_blocks_1 (f, bb_eh_end)
 	{
 	  /* Record whether this call created an edge.  */
 	  rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-	  int region = (note ? XINT (XEXP (note, 0), 0) : 1);
+	  int region = (note ? XWINT (XEXP (note, 0), 0) : 1);
 	  call_has_abnormal_edge = 0;
 
 	  /* If there is an EH region, we have an edge.  */
@@ -1614,7 +1614,7 @@ delete_eh_regions ()
 	if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG) ||
 	    (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)) 
 	  {
-	    int num = CODE_LABEL_NUMBER (insn);
+	    int num = NOTE_EH_HANDLER (insn);
 	    /* A NULL handler indicates a region is no longer needed,
 	       as long as it isn't the target of a rethrow.  */
 	    if (get_first_handler (num) == NULL && ! rethrow_used (num))
===================================================================
Index: function.c
--- function.c	1999/08/27 07:52:05	1.99
+++ function.c	1999/08/27 21:32:15
@@ -1341,11 +1341,11 @@ put_reg_into_stack (function, reg, type,
 	new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
     }
 
+  PUT_CODE (reg, MEM);
   PUT_MODE (reg, decl_mode);
   XEXP (reg, 0) = XEXP (new, 0);
   /* `volatil' bit means one thing for MEMs, another entirely for REGs.  */
   MEM_VOLATILE_P (reg) = volatile_p;
-  PUT_CODE (reg, MEM);
 
   /* If this is a memory ref that contains aggregate components,
      mark it as such for cse and loop optimize.  If we are reusing a
@@ -1495,6 +1495,9 @@ fixup_var_refs_insns (var, promoted_mode
 
       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
 	{
+	  /* Remember the notes in case we delete the insn.  */
+	  note = REG_NOTES (insn);
+
 	  /* If this is a CLOBBER of VAR, delete it.
 
 	     If it has a REG_LIBCALL note, delete the REG_LIBCALL
@@ -1653,10 +1656,13 @@ fixup_var_refs_insns (var, promoted_mode
 	  /* Also fix up any invalid exprs in the REG_NOTES of this insn.
 	     But don't touch other insns referred to by reg-notes;
 	     we will get them elsewhere.  */
-	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-	    if (GET_CODE (note) != INSN_LIST)
-	      XEXP (note, 0)
-		= walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
+	  while (note)
+	    {
+	      if (GET_CODE (note) != INSN_LIST)
+		XEXP (note, 0)
+		  = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
+	       note = XEXP (note, 1);
+	    }
 	}
 
       if (!ht)
@@ -2631,9 +2637,9 @@ gen_mem_addressof (reg, decl)
      address is being taken.  */
   REG_USERVAR_P (XEXP (r, 0)) = REG_USERVAR_P (reg);
 
-  XEXP (reg, 0) = r;
   PUT_CODE (reg, MEM);
   PUT_MODE (reg, DECL_MODE (decl));
+  XEXP (reg, 0) = r;
   MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
   MEM_SET_IN_STRUCT_P (reg, AGGREGATE_TYPE_P (type));
   MEM_ALIAS_SET (reg) = get_alias_set (decl);
===================================================================
Index: integrate.c
--- integrate.c	1999/08/25 13:37:44	1.59
+++ integrate.c	1999/08/27 21:32:19
@@ -2694,7 +2694,8 @@ copy_rtx_and_substitute (orig, map)
       switch (*format_ptr++)
 	{
 	case '0':
-	  XEXP (copy, i) = XEXP (orig, i);
+	  /* Copy this through the wide int field; that's safest.  */
+	  X0WINT (copy, i) = X0WINT (orig, i);
 	  break;
 
 	case 'e':
===================================================================
Index: local-alloc.c
--- local-alloc.c	1999/08/20 23:05:10	1.41
+++ local-alloc.c	1999/08/27 21:32:22
@@ -971,11 +971,11 @@ update_equiv_regs ()
 
 		  emit_insn_before (copy_rtx (PATTERN (equiv_insn)), insn);
 		  REG_NOTES (PREV_INSN (insn)) = REG_NOTES (equiv_insn);
+		  REG_NOTES (equiv_insn) = 0;
 
 		  PUT_CODE (equiv_insn, NOTE);
 		  NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
 		  NOTE_SOURCE_FILE (equiv_insn) = 0;
-		  REG_NOTES (equiv_insn) = 0;
 
 		  if (block < 0)
 		    REG_BASIC_BLOCK (regno) = 0;
@@ -1071,8 +1071,6 @@ block_alloc (b)
   insn = BLOCK_HEAD (b);
   while (1)
     {
-      register rtx body = PATTERN (insn);
-
       if (GET_CODE (insn) != NOTE)
 	insn_number++;
 
@@ -1083,6 +1081,9 @@ block_alloc (b)
 	  register rtx r0, r1;
 	  int combined_regno = -1;
 	  int i;
+#ifndef REGISTER_CONSTRAINTS
+	  register rtx body = PATTERN (insn);
+#endif
 
 	  this_insn_number = insn_number;
 	  this_insn = insn;
@@ -1184,11 +1185,11 @@ block_alloc (b)
 			 can only be in the same register as the output, give
 			 priority to an equivalence found from that insn.  */
 		      int may_save_copy
-			= ((SET_DEST (body) == r0 && SET_SRC (body) == r1)
 #ifdef REGISTER_CONSTRAINTS
-			   || (r1 == recog_operand[i] && must_match_0 >= 0)
+			= (r1 == recog_operand[i] && must_match_0 >= 0);
+#else
+			= (SET_DEST (body) == r0 && SET_SRC (body) == r1);
 #endif
-			   );
 		      
 		      if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
 			win = combine_regs (r1, r0, may_save_copy,
===================================================================
Index: loop.c
--- loop.c	1999/08/25 18:14:11	1.178
+++ loop.c	1999/08/27 21:32:25
@@ -7799,7 +7799,8 @@ check_dbra_loop (loop_end, insn_count, l
 	    }
 	}
     }
-  else if (INTVAL (bl->biv->add_val) > 0)
+  else if (GET_CODE (bl->biv->add_val) == CONST_INT
+	   && INTVAL (bl->biv->add_val) > 0)
     {
       /* Try to change inc to dec, so can apply above optimization.  */
       /* Can do this if:
===================================================================
Index: print-rtl.c
--- print-rtl.c	1999/08/20 23:05:10	1.30
+++ print-rtl.c	1999/08/27 21:32:26
@@ -185,8 +185,7 @@ print_rtx (in_rtx)
 	      }
 	    else
 	      {
-		/* Can't use XSTR because of type checking.  */
-		char *str = in_rtx->fld[i].rtstr;
+		char *str = X0STR (in_rtx, i);
 		if (str == 0)
 		  fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
 		else
===================================================================
Index: real.h
--- real.h	1999/03/06 05:34:26	1.12
+++ real.h	1999/08/27 21:32:26
@@ -452,7 +452,7 @@ union real_extract 
 #define CONST_DOUBLE_HIGH(r) XWINT (r, 3)
 
 /* Link for chain of all CONST_DOUBLEs in use in current function.  */
-#define CONST_DOUBLE_CHAIN(r) XEXP (r, 1)
+#define CONST_DOUBLE_CHAIN(r) X0EXP (r, 1)
 /* The MEM which represents this CONST_DOUBLE's value in memory,
    or const0_rtx if no MEM has been made for it yet,
    or cc0_rtx if it is not on the chain.  */
===================================================================
Index: regmove.c
--- regmove.c	1999/08/20 23:05:11	1.61
+++ regmove.c	1999/08/27 21:32:26
@@ -1905,7 +1905,9 @@ fixup_match_1 (insn, set, src, src_subre
 	  NOTE_SOURCE_FILE (insn) = 0;
 	  /* emit_insn_after_with_line_notes has no
 	     return value, so search for the new insn.  */
-	  for (insn = p; PATTERN (insn) != pat; )
+	  insn = p;
+	  while (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
+		 || PATTERN (insn) != pat)
 	    insn = PREV_INSN (insn);
 
 	  REG_NOTES (insn) = notes;
===================================================================
Index: reload.c
--- reload.c	1999/08/25 13:37:45	1.76
+++ reload.c	1999/08/27 21:32:28
@@ -1631,7 +1631,7 @@ loc_mentioned_in_p (loc, in)
 
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
-      if (loc == &XEXP (in, i))
+      if (loc == &in->fld[i].rtx)
 	return 1;
       if (fmt[i] == 'e')
         {
===================================================================
Index: reload1.c
--- reload1.c	1999/08/25 13:37:45	1.154
+++ reload1.c	1999/08/27 21:32:30
@@ -1110,6 +1110,7 @@ reload (first, global, dumpfile)
 	  if (reg_renumber[i] < 0)
 	    {
 	      rtx reg = regno_reg_rtx[i];
+	      PUT_CODE (reg, MEM);
 	      XEXP (reg, 0) = addr;
 	      REG_USERVAR_P (reg) = 0;
 	      RTX_UNCHANGING_P (reg) = is_readonly;
@@ -1118,7 +1119,6 @@ reload (first, global, dumpfile)
 	      /* We have no alias information about this newly created
 		 MEM.  */
 	      MEM_ALIAS_SET (reg) = 0;
-	      PUT_CODE (reg, MEM);
 	    }
 	  else if (reg_equiv_mem[i])
 	    XEXP (reg_equiv_mem[i], 0) = addr;
===================================================================
Index: varasm.c
--- varasm.c	1999/08/25 13:37:46	1.69
+++ varasm.c	1999/08/27 21:32:34
@@ -3745,6 +3745,9 @@ mark_constant_pool ()
       if (!pool->mark)
 	  continue;
 
+      /* skip CONST_DOUBLEs too - correct?  */
+      if (GET_CODE (pool->constant) == CONST_DOUBLE)
+	continue;
       label = XSTR (pool->constant, 0);
 
       /* Be sure the symbol's value is marked. */
===================================================================
Index: config/i386/i386.md
--- config/i386/i386.md		1999/08/27 07:07:06	1.79
+++ config/i386/i386.md		1999/08/27 21:32:38
@@ -6413,7 +6413,7 @@ byte_xor_operation:
 {
   CC_STATUS_INIT;
 
-  if (GET_CODE (operands[1]) == REG && REGNO (operands[2]) == 2 &&
+  if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 2 &&
       operands[2] == constm1_rtx && ix86_cpu == PROCESSOR_K6)
     return \"loop %l3\";
 


More information about the Gcc-patches mailing list