On 10/5/19 9:24 AM, Jakub Jelinek wrote:
> On Sat, Oct 05, 2019 at 06:12:37AM +0000, Bernd Edlinger wrote:
>> On 10/3/19 5:25 PM, Jakub Jelinek wrote:
>>> What effect does this have on the cc1/cc1plus .text sizes?
>>
>> r276457:
>>
>> with patch, --enable-languages=all --enable-checking=yes,rtl
>> $ size gcc/cc1
>>    text    data     bss     dec     hex filename
>> 35117708          50984 1388192 36556884        22dd054 gcc/cc1
>> $ size gcc/cc1plus
>>    text    data     bss     dec     hex filename
>> 37871569          54640 1391936 39318145        257f281 gcc/cc1plus
>>
>> unpatched, --enable-languages=all --enable-checking=yes,rtl
>> $ size gcc/cc1
>>    text    data     bss     dec     hex filename
>> 36972031          50984 1388192 38411207        24a1bc7 gcc/cc1
>> $ size gcc/cc1plus
>>    text    data     bss     dec     hex filename
>> 39725980          54640 1391936 41172556        2743e4c gcc/cc1plus
>>
>> I am a bit surprised, that the patch gives smaller code. I used not the 
>> original
>> Version of this patch, but the one based on Richard's suggestion.
> 
> In that case, can you check if all the non-failed checks are actually
> inlined?  We do want to inline the if (x->code != 123) check_failed (...);
> and don't want to inline the check_failed (...).  With partial inlining, it
> might be ok if we inline the if and don't inline the actual caller of
> check_failed, but I'd worry about checks for multiple codes if we inline
> from if (x->code != 123 && x->code != 235 && x->code != 348) inline say
> just x->code != 123 or x->code != 123 && x->code != 235 and leave the rest
> in the out of line function.
> 

Ah, the check functions were not inlined at all because an inline keyword was 
missing,
that explains the very small text size.

So in the attached patch, I merged all checking code into one template, added
an inline keyword, and now it is inlined as expected, the code is still a bit 
smaller
than the original implementation, though.

I don't know why exactly the size is smaller, but everything looks completely 
correct
now (numbers are again for r276457 with attached patch):

$ size gcc/cc1
   text    data     bss     dec     hex filename
36222783          50984 1388192 37661959        23ead07 gcc/cc1
$ size gcc/cc1plus
   text    data     bss     dec     hex filename
38976708          54640 1391936 40423284        268cf74 gcc/cc1plus

I added a skip for all of rtl.h, since otherwise gdb would need all possible 
template
invocations of rtl_check_code<> and rtl_check_bounds<> in the skip statement.

n works now, but s only in the stage1 compiler.  In the stage3 compiler
s steps one line into the inlined code and then back to the called function.

But that is generally the case for all inline functions, like INSN_UID
and contains_struct_check which is in tree.h, should be skipped, but same here.

That does not happen with the statement expression since all code is on the
same line.

Is that a show stopper for this patch, or just a bug in the gdb?

>>> Does this affect debuggability of --enable-checking=yes,rtl compilers?
>>> I mean, often when we replace some macros with inlines step in GDB
>>> becomes a bigger nightmare, having to go through tons of inline frames.
>>> gdbinit.in has a lengthy list of inlines to skip in rtl.h, shouldn't this be
>>> added to that list?  Not 100% sure how well it will work on rtl checking
>>> vs. non-rtl checking builds.
>>>
>>
>> I don't see a big problem here.  If I type "s" in gdb it jumps to the check
>> function and the next s jumps back, adding skip instructions in gdbinit.in
>> does not seem to have any effect for me, but the debug is not that 
>> uncomfortable
>> anyway.
>>
>> Interesting is that gdb also jumps in the check function when I press n.
>> That is also Independent of the gdbinit.in, seems to be a bug due to inlining
>> code from another line than the original macro, but nothing terrilby bad.
> 

the issue with n is gone now.

the s works in stage1 now, but not in stage3.

Attached is an improved patch that fixes the inline issue and adds all of rtl.h
(including rhs_regno) to the exclusions.

Don't know if there is still a consensus to add -Wshadow=local or if the 
resistance
is too big, then it is probably fine to keep the rtl checking code as-is.


Bernd.

> Unfortunately, for me the above two counts as terribly bad, show
> stopper here.  A lot of function calls in RTL are like:
> rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
> rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y))
> force_operand (XEXP (dest_mem, 0), target)
> etc.  (just random examples), during debugging one is absolutely
> uninterested in stepping into the implementation of XEXP, you know what it
> means, you want to go stright into the rtx_equal_for_memref_p etc.  call. 
> It is already bad that one has to step through the poly_int* stuff or
> rhs_regno for REGNO (we should add rhs_regno to gdbinit.in and some of the
> poly_int* stuff too).  And no, one can't use n instead of s, because then
> the whole call is skipped.  b rtx_equal_for_memref_p; n works, but it is
> time consuming and one needs to delete the breakpoint again.
> 
>       Jakub
> 
2019-10-04  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	* gdbinit.in: Add skip file rtl.h
	* rtl.h (RTL_CHECK1, RTL_CHECK2, RTL_CHECKC1, RTL_CHECKC2
	RTVEC_ELT): Reimplement with inline functions.
	(RTL_FLAG_CHECK): New variadic macro.
	(RTL_FLAG_CHECK1-6): Use RTL_FLAG_CHECK.
	(RTL_FLAG_CHECK7): Remove.
	(rtvec_check): New helper function.
	(rtl_check_bounds, rtl_check_code,
	rtl_flag_check): New helper templates.

Index: gcc/gdbinit.in
===================================================================
--- gcc/gdbinit.in	(revision 276625)
+++ gcc/gdbinit.in	(working copy)
@@ -282,23 +282,7 @@ skip file line-map.h
 skip file timevar.h
 
 # Likewise, skip various inline functions in rtl.h.
-skip rtx_expr_list::next
-skip rtx_expr_list::element
-skip rtx_insn_list::next
-skip rtx_insn_list::insn
-skip rtx_sequence::len
-skip rtx_sequence::element
-skip rtx_sequence::insn
-skip INSN_UID
-skip PREV_INSN
-skip SET_PREV_INSN
-skip NEXT_INSN
-skip SET_NEXT_INSN
-skip BLOCK_FOR_INSN
-skip PATTERN
-skip INSN_LOCATION
-skip INSN_HAS_LOCATION
-skip JUMP_LABEL_AS_INSN
+skip file rtl.h
 
 # Restore pagination to the previous state.
 python if __gcc_prev_pagination: gdb.execute("set pagination on")
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 276625)
+++ gcc/rtl.h	(working copy)
@@ -1070,43 +1070,17 @@ is_a_helper <rtx_note *>::test (rtx_insn *insn)
 #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
 /* 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) __extension__				\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     const enum rtx_code _code = GET_CODE (_rtx);			\
-     if (_n < 0 || _n >= GET_RTX_LENGTH (_code))			\
-       rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,		\
-				__FUNCTION__);				\
-     if (GET_RTX_FORMAT (_code)[_n] != C1)				\
-       rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__,	\
-			       __FUNCTION__);				\
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECK1(RTX, N, C1)						\
+  rtl_check_bounds<C1> (RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
-#define RTL_CHECK2(RTX, N, C1, C2) __extension__			\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     const enum rtx_code _code = GET_CODE (_rtx);			\
-     if (_n < 0 || _n >= GET_RTX_LENGTH (_code))			\
-       rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,		\
-				__FUNCTION__);				\
-     if (GET_RTX_FORMAT (_code)[_n] != C1				\
-	 && GET_RTX_FORMAT (_code)[_n] != C2)				\
-       rtl_check_failed_type2 (_rtx, _n, C1, C2, __FILE__, __LINE__,	\
-			       __FUNCTION__);				\
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECK2(RTX, N, C1, C2)					\
+  rtl_check_bounds<C1, C2> (RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
-#define RTL_CHECKC1(RTX, N, C) __extension__				\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     if (GET_CODE (_rtx) != (C))					\
-       rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__,		\
-			       __FUNCTION__);				\
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECKC1(RTX, N, C1)						\
+  rtl_check_code<C1> (RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
-#define RTL_CHECKC2(RTX, N, C1, C2) __extension__			\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     const enum rtx_code _code = GET_CODE (_rtx);			\
-     if (_code != (C1) && _code != (C2))				\
-       rtl_check_failed_code2 (_rtx, (C1), (C2), __FILE__, __LINE__,	\
-			       __FUNCTION__); \
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECKC2(RTX, N, C1, C2)					\
+  rtl_check_code<C1, C2> (RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
 #define RTL_CHECKC3(RTX, N, C1, C2, C3) __extension__			\
 (*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
@@ -1116,12 +1090,8 @@ is_a_helper <rtx_note *>::test (rtx_insn *insn)
 			       __LINE__, __FUNCTION__);			\
      &_rtx->u.fld[_n]; }))
 
-#define RTVEC_ELT(RTVEC, I) __extension__				\
-(*({ __typeof (RTVEC) const _rtvec = (RTVEC); const int _i = (I);	\
-     if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec))				\
-       rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__,	\
-				  __FUNCTION__);			\
-     &_rtvec->elem[_i]; }))
+#define RTVEC_ELT(RTVEC, I)						\
+  rtvec_check (RTVEC, I, __FILE__, __LINE__, __FUNCTION__)
 
 #define XWINT(RTX, N) __extension__					\
 (*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
@@ -1222,6 +1192,120 @@ extern void rtvec_check_failed_bounds (const_rtvec
 				       const char *)
     ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
 
+static inline rtx const&
+rtvec_check (const_rtvec vec, int i,
+	     const char *file, int line, const char *func)
+{
+  if (i < 0 || i >= GET_NUM_ELEM (vec))
+    rtvec_check_failed_bounds (vec, i, file, line, func);
+  return vec->elem[i];
+}
+
+static inline rtx&
+rtvec_check (rtvec vec, int i,
+	     const char *file, int line, const char *func)
+{
+  if (i < 0 || i >= GET_NUM_ELEM (vec))
+    rtvec_check_failed_bounds (vec, i, file, line, func);
+  return vec->elem[i];
+}
+
+template<char C1>
+inline const rtunion&
+rtl_check_bounds (const_rtx rtl, int n,
+		  const char *file, int line, const char *function)
+{
+  const enum rtx_code code = GET_CODE (rtl);
+  if (n < 0 || n >= GET_RTX_LENGTH (code))
+    rtl_check_failed_bounds (rtl, n, file, line, function);
+  if (GET_RTX_FORMAT (code)[n] != C1)
+    rtl_check_failed_type1 (rtl, n, C1, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<char C1>
+inline rtunion&
+rtl_check_bounds (rtx rtl, int n,
+		  const char *file, int line, const char *function)
+{
+  const enum rtx_code code = GET_CODE (rtl);
+  if (n < 0 || n >= GET_RTX_LENGTH (code))
+    rtl_check_failed_bounds (rtl, n, file, line, function);
+  if (GET_RTX_FORMAT (code)[n] != C1)
+    rtl_check_failed_type1 (rtl, n, C1, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<char C1, char C2>
+inline const rtunion&
+rtl_check_bounds (const_rtx rtl, int n,
+		  const char *file, int line, const char *function)
+{
+  const enum rtx_code code = GET_CODE (rtl);
+  if (n < 0 || n >= GET_RTX_LENGTH (code))
+    rtl_check_failed_bounds (rtl, n, file, line, function);
+  if (GET_RTX_FORMAT (code)[n] != C1
+      && GET_RTX_FORMAT (code)[n] != C2)
+    rtl_check_failed_type2 (rtl, n, C1, C2, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<char C1, char C2>
+inline rtunion&
+rtl_check_bounds (rtx rtl, int n,
+		  const char *file, int line, const char *function)
+{
+  const enum rtx_code code = GET_CODE (rtl);
+  if (n < 0 || n >= GET_RTX_LENGTH (code))
+    rtl_check_failed_bounds (rtl, n, file, line, function);
+  if (GET_RTX_FORMAT (code)[n] != C1
+      && GET_RTX_FORMAT (code)[n] != C2)
+    rtl_check_failed_type2 (rtl, n, C1, C2, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<RTX_CODE C1>
+inline const rtunion&
+rtl_check_code (const_rtx rtl, int n,
+		const char *file, int line, const char *function)
+{
+  if (GET_CODE (rtl) != C1)
+    rtl_check_failed_code1 (rtl, C1, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<RTX_CODE C1>
+inline rtunion&
+rtl_check_code (rtx rtl, int n,
+		const char *file, int line, const char *function)
+{
+  if (GET_CODE (rtl) != C1)
+    rtl_check_failed_code1 (rtl, C1, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<RTX_CODE C1, RTX_CODE C2>
+inline const rtunion&
+rtl_check_code (const_rtx rtl, int n,
+		const char *file, int line, const char *function)
+{
+  if (GET_CODE (rtl) != C1
+      && GET_CODE (rtl) != C2)
+    rtl_check_failed_code2 (rtl, C1, C2, file, line, function);
+  return rtl->u.fld[n];
+}
+
+template<RTX_CODE C1, RTX_CODE C2>
+inline rtunion&
+rtl_check_code (rtx rtl, int n,
+		const char *file, int line, const char *function)
+{
+  if (GET_CODE (rtl) != C1
+      && GET_CODE (rtl) != C2)
+    rtl_check_failed_code2 (rtl, C1, C2, file, line, function);
+  return rtl->u.fld[n];
+}
+
 #else   /* not ENABLE_RTL_CHECKING */
 
 #define RTL_CHECK1(RTX, N, C1)      ((RTX)->u.fld[N])
@@ -1249,66 +1333,17 @@ extern void rtvec_check_failed_bounds (const_rtvec
 #define RTX_FLAG(RTX, FLAG)	((RTX)->FLAG)
 
 #if defined ENABLE_RTL_FLAG_CHECKING && (GCC_VERSION >= 2007)
-#define RTL_FLAG_CHECK1(NAME, RTX, C1) __extension__			\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1)						\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
+#define RTL_FLAG_CHECK(NAME, RTX, ...)					\
+  rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,		\
+					__FUNCTION__)
 
-#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) __extension__		\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2)			\
-     rtl_check_failed_flag  (NAME,_rtx, __FILE__, __LINE__,		\
-			      __FUNCTION__);				\
-   _rtx; })
+#define RTL_FLAG_CHECK1 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK2 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK3 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK4 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK5 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK6 RTL_FLAG_CHECK
 
-#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) __extension__		\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2			\
-       && GET_CODE (_rtx) != C3)					\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) __extension__	\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE(_rtx) != C4)		\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			      __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) __extension__	\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4		\
-       && GET_CODE (_rtx) != C5)					\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6)		\
-  __extension__								\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4		\
-       && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6)		\
-     rtl_check_failed_flag  (NAME,_rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7)		\
-  __extension__								\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4		\
-       && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6		\
-       && GET_CODE (_rtx) != C7)					\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
 #define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) 				\
   __extension__								\
 ({ __typeof (RTX) const _rtx = (RTX);					\
@@ -1322,6 +1357,75 @@ extern void rtl_check_failed_flag (const char *, c
     ATTRIBUTE_NORETURN ATTRIBUTE_COLD
     ;
 
+template<RTX_CODE C1, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, RTX_CODE C5, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4
+      && GET_CODE (rtl) != C5)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, RTX_CODE C5, RTX_CODE C6, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4
+      && GET_CODE (rtl) != C5 && GET_CODE (rtl) != C6)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
 #else	/* not ENABLE_RTL_FLAG_CHECKING */
 
 #define RTL_FLAG_CHECK1(NAME, RTX, C1)					(RTX)
@@ -1330,7 +1434,6 @@ extern void rtl_check_failed_flag (const char *, c
 #define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4)			(RTX)
 #define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5)			(RTX)
 #define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6)		(RTX)
-#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7)		(RTX)
 #define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) 				(RTX)
 #endif
 

Reply via email to