diff mbox series

Fix -Wshadow=local warnings in rtl.h

Message ID VI1PR03MB452892F64E88E21B5BC0B380E49F0@VI1PR03MB4528.eurprd03.prod.outlook.com
State New
Headers show
Series Fix -Wshadow=local warnings in rtl.h | expand

Commit Message

Bernd Edlinger Oct. 3, 2019, 3:17 p.m. UTC
Hi,

this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
which happen when this macro is used recursively in a macro
argument.  The __typeof (RTX) const _rtx in the inner macro
expansions shadows the outer macro expansions.

So reworked the macro to not use statement expressions but
use templates instead.  Since the 7-argument overload is not
used anywhere removed RTL_FLAG_CHECK7 for now.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.

Comments

Jakub Jelinek Oct. 3, 2019, 3:25 p.m. UTC | #1
On Thu, Oct 03, 2019 at 03:17:47PM +0000, Bernd Edlinger wrote:
> Hi,
> 
> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
> which happen when this macro is used recursively in a macro
> argument.  The __typeof (RTX) const _rtx in the inner macro
> expansions shadows the outer macro expansions.
> 
> So reworked the macro to not use statement expressions but
> use templates instead.  Since the 7-argument overload is not
> used anywhere removed RTL_FLAG_CHECK7 for now.

What effect does this have on the cc1/cc1plus .text sizes?
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.

	Jakub
Bernd Edlinger Oct. 3, 2019, 3:31 p.m. UTC | #2
On 10/3/19 5:25 PM, Jakub Jelinek wrote:
> On Thu, Oct 03, 2019 at 03:17:47PM +0000, Bernd Edlinger wrote:
>> Hi,
>>
>> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
>> which happen when this macro is used recursively in a macro
>> argument.  The __typeof (RTX) const _rtx in the inner macro
>> expansions shadows the outer macro expansions.
>>
>> So reworked the macro to not use statement expressions but
>> use templates instead.  Since the 7-argument overload is not
>> used anywhere removed RTL_FLAG_CHECK7 for now.
> 
> What effect does this have on the cc1/cc1plus .text sizes?
> 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.
> 
> 	Jakub
> 

I checked that the resulting code does not look completely stupid, but
I will try to find answers to your questions above by tomorrow.


Thanks
Bernd.
Segher Boessenkool Oct. 4, 2019, 8:26 a.m. UTC | #3
On Thu, Oct 03, 2019 at 05:25:55PM +0200, Jakub Jelinek wrote:
> On Thu, Oct 03, 2019 at 03:17:47PM +0000, Bernd Edlinger wrote:
> > this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
> > which happen when this macro is used recursively in a macro
> > argument.  The __typeof (RTX) const _rtx in the inner macro
> > expansions shadows the outer macro expansions.
> > 
> > So reworked the macro to not use statement expressions but
> > use templates instead.  Since the 7-argument overload is not
> > used anywhere removed RTL_FLAG_CHECK7 for now.
> 
> What effect does this have on the cc1/cc1plus .text sizes?
> 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.

Also, how much slower does it make RTL checking builds?


Segher
Richard Sandiford Oct. 4, 2019, 12:38 p.m. UTC | #4
Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
> Hi,
>
> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
> which happen when this macro is used recursively in a macro
> argument.  The __typeof (RTX) const _rtx in the inner macro
> expansions shadows the outer macro expansions.
>
> So reworked the macro to not use statement expressions but
> use templates instead.  Since the 7-argument overload is not
> used anywhere removed RTL_FLAG_CHECK7 for now.
>
>
> Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
> Is it OK for trunk?
>
>
> Thanks
> Bernd.
>
> 2019-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>
> 	* rtl.h (RTL_FLAG_CHECK): New variadic macro.
> 	(RTL_FLAG_CHECK1-6): Use RTL_FLAG_CHECK.
> 	(RTL_FLAG_CHECK7): Remove.
> 	(rtl_flag_check, check_rtl_code): New helper functions.
>
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h	(revision 276484)
> +++ gcc/rtl.h	(working copy)
> @@ -1249,66 +1249,18 @@ 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, ...) 					\
> +  ((__typeof (&*(RTX))) rtl_flag_check (check_rtl_code<__VA_ARGS__>,	\
> +					NAME, RTX, __FILE__, __LINE__,	\
> +					__FUNCTION__))

Yet another comment on this one, sorry, but why not just make
rtl_flag_check a template function instead of defining two versions
of it and using __typeof?  Is the idea is to make sure that GET_CODE
is only applied to genuine rtxes rather than some random structure
with a field called "code"?  If so, I think we should do that in
GET_CODE itself, and do it regardless of whether rtl checking is
enabled.  E.g. something like:

#define GET_CODE(RTX) ((rtx_code) static_cast<const_rtx> (RTX)->code)

(Wonder how much code that will break :-))

And if we do use templates instead of const_rtx/rtx variants,
it might be simpler to keep the checking and assert together:

#define RTL_FLAG_CHECK(NAME, RTX, ...) 				\
  (rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,	\
				__FUNCTION__))

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;
}

...etc...

which could also address some of the fears around cost.

Personally I'm not fussed about keeping the checking and assert
together though, just a suggestion.

Richard
Bernd Edlinger Oct. 4, 2019, 4:45 p.m. UTC | #5
On 10/4/19 2:38 PM, Richard Sandiford wrote:
> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>> Hi,
>>
>> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
>> which happen when this macro is used recursively in a macro
>> argument.  The __typeof (RTX) const _rtx in the inner macro
>> expansions shadows the outer macro expansions.
>>
>> So reworked the macro to not use statement expressions but
>> use templates instead.  Since the 7-argument overload is not
>> used anywhere removed RTL_FLAG_CHECK7 for now.
>>
>>
>> Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
>> Is it OK for trunk?
>>
>>
>> Thanks
>> Bernd.
>>
>> 2019-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>>
>> 	* rtl.h (RTL_FLAG_CHECK): New variadic macro.
>> 	(RTL_FLAG_CHECK1-6): Use RTL_FLAG_CHECK.
>> 	(RTL_FLAG_CHECK7): Remove.
>> 	(rtl_flag_check, check_rtl_code): New helper functions.
>>
>> Index: gcc/rtl.h
>> ===================================================================
>> --- gcc/rtl.h	(revision 276484)
>> +++ gcc/rtl.h	(working copy)
>> @@ -1249,66 +1249,18 @@ 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, ...) 					\
>> +  ((__typeof (&*(RTX))) rtl_flag_check (check_rtl_code<__VA_ARGS__>,	\
>> +					NAME, RTX, __FILE__, __LINE__,	\
>> +					__FUNCTION__))
> 
> Yet another comment on this one, sorry, but why not just make
> rtl_flag_check a template function instead of defining two versions
> of it and using __typeof?  Is the idea is to make sure that GET_CODE
> is only applied to genuine rtxes rather than some random structure
> with a field called "code"?  If so, I think we should do that in
> GET_CODE itself, and do it regardless of whether rtl checking is
> enabled.  E.g. something like:
> 

Actually I wanted to do it with a template, and invoke it using __typeof(RTX).

BUT with that I ran into a lmitation of the template vs. block statements
See PR#91803:  We cannot instantiate a template on the
type of a statement expression, only when the expression is completely
written down without statement expressions.

So even if we remove that limitation, it will be impossible to use
templates dependent on __typeof(statement-expressions) as we need
to bootstrap from rather old gcc versions.

However if we are able to replace all statement-expressions in
rtl.h then it will probably be possible to use a template here,
without that type cast.

I still need a const and a non-const version of that function because
otherwise the -Werror=cast-qual warning will kill me.


> #define GET_CODE(RTX) ((rtx_code) static_cast<const_rtx> (RTX)->code)
> 
> (Wonder how much code that will break :-))
> 
> And if we do use templates instead of const_rtx/rtx variants,
> it might be simpler to keep the checking and assert together:
> 
> #define RTL_FLAG_CHECK(NAME, RTX, ...) 				\
>   (rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,	\
> 				__FUNCTION__))
> 
> 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;
> }
> 
> ...etc...
> 

I somehow expected the typename T need to be given int the template arguments
like rtl_flag_check<__typeof(RTX), __VA_ARGS__> (NAME, RTX,

Could be that there is way to make that work without __typeof ?


> which could also address some of the fears around cost.
> 
> Personally I'm not fussed about keeping the checking and assert
> together though, just a suggestion.
> 

Okay I'll consider that.

BTW, I noticed that the patch is still incomplete and breaks
with --enable-checking=yes,rtl :-/

I did not try that before, just did it after Jakub mentioned it.


Thanks
Bernd.
Richard Sandiford Oct. 4, 2019, 5:09 p.m. UTC | #6
Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
> On 10/4/19 2:38 PM, Richard Sandiford wrote:
>> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>>> Hi,
>>>
>>> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
>>> which happen when this macro is used recursively in a macro
>>> argument.  The __typeof (RTX) const _rtx in the inner macro
>>> expansions shadows the outer macro expansions.
>>>
>>> So reworked the macro to not use statement expressions but
>>> use templates instead.  Since the 7-argument overload is not
>>> used anywhere removed RTL_FLAG_CHECK7 for now.
>>>
>>>
>>> Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
>>> Is it OK for trunk?
>>>
>>>
>>> Thanks
>>> Bernd.
>>>
>>> 2019-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>>>
>>> 	* rtl.h (RTL_FLAG_CHECK): New variadic macro.
>>> 	(RTL_FLAG_CHECK1-6): Use RTL_FLAG_CHECK.
>>> 	(RTL_FLAG_CHECK7): Remove.
>>> 	(rtl_flag_check, check_rtl_code): New helper functions.
>>>
>>> Index: gcc/rtl.h
>>> ===================================================================
>>> --- gcc/rtl.h	(revision 276484)
>>> +++ gcc/rtl.h	(working copy)
>>> @@ -1249,66 +1249,18 @@ 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, ...) 					\
>>> +  ((__typeof (&*(RTX))) rtl_flag_check (check_rtl_code<__VA_ARGS__>,	\
>>> +					NAME, RTX, __FILE__, __LINE__,	\
>>> +					__FUNCTION__))
>> 
>> Yet another comment on this one, sorry, but why not just make
>> rtl_flag_check a template function instead of defining two versions
>> of it and using __typeof?  Is the idea is to make sure that GET_CODE
>> is only applied to genuine rtxes rather than some random structure
>> with a field called "code"?  If so, I think we should do that in
>> GET_CODE itself, and do it regardless of whether rtl checking is
>> enabled.  E.g. something like:
>> 
>
> Actually I wanted to do it with a template, and invoke it using __typeof(RTX).
>
> BUT with that I ran into a lmitation of the template vs. block statements
> See PR#91803:  We cannot instantiate a template on the
> type of a statement expression, only when the expression is completely
> written down without statement expressions.
>
> So even if we remove that limitation, it will be impossible to use
> templates dependent on __typeof(statement-expressions) as we need
> to bootstrap from rather old gcc versions.
>
> However if we are able to replace all statement-expressions in
> rtl.h then it will probably be possible to use a template here,
> without that type cast.
>
> I still need a const and a non-const version of that function because
> otherwise the -Werror=cast-qual warning will kill me.
>
>
>> #define GET_CODE(RTX) ((rtx_code) static_cast<const_rtx> (RTX)->code)
>> 
>> (Wonder how much code that will break :-))
>> 
>> And if we do use templates instead of const_rtx/rtx variants,
>> it might be simpler to keep the checking and assert together:
>> 
>> #define RTL_FLAG_CHECK(NAME, RTX, ...) 				\
>>   (rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,	\
>> 				__FUNCTION__))
>> 
>> 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;
>> }
>> 
>> ...etc...
>> 
>
> I somehow expected the typename T need to be given int the template arguments
> like rtl_flag_check<__typeof(RTX), __VA_ARGS__> (NAME, RTX,
>
> Could be that there is way to make that work without __typeof ?

Yeah, the typename will be deduced automatically in the example above.
I don't think we need __typeof here.

Richard
Bernd Edlinger Oct. 4, 2019, 6:11 p.m. UTC | #7
On 10/4/19 7:09 PM, Richard Sandiford wrote:
> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>>
>> Actually I wanted to do it with a template, and invoke it using __typeof(RTX).
>>
>> BUT with that I ran into a lmitation of the template vs. block statements
>> See PR#91803:  We cannot instantiate a template on the
>> type of a statement expression, only when the expression is completely
>> written down without statement expressions.
>>
>> So even if we remove that limitation, it will be impossible to use
>> templates dependent on __typeof(statement-expressions) as we need
>> to bootstrap from rather old gcc versions.
>>
>> However if we are able to replace all statement-expressions in
>> rtl.h then it will probably be possible to use a template here,
>> without that type cast.
>>
>> I still need a const and a non-const version of that function because
>> otherwise the -Werror=cast-qual warning will kill me.
>>
>>
>>> #define GET_CODE(RTX) ((rtx_code) static_cast<const_rtx> (RTX)->code)
>>>
>>> (Wonder how much code that will break :-))
>>>
>>> And if we do use templates instead of const_rtx/rtx variants,
>>> it might be simpler to keep the checking and assert together:
>>>
>>> #define RTL_FLAG_CHECK(NAME, RTX, ...) 				\
>>>   (rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,	\
>>> 				__FUNCTION__))
>>>
>>> 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;
>>> }
>>>
>>> ...etc...
>>>
>>
>> I somehow expected the typename T need to be given int the template arguments
>> like rtl_flag_check<__typeof(RTX), __VA_ARGS__> (NAME, RTX,
>>
>> Could be that there is way to make that work without __typeof ?
> 
> Yeah, the typename will be deduced automatically in the example above.
> I don't think we need __typeof here.
> 

Yes, indeed it works.

The updated patch uses only one template function for rtl_flag_check.

It also fixes the --enable-checking=rtl issue.  I wonder if that can
also be simplified into one template, unlike the rtl_flag_check the
result is either a const or a non-const object but not the same
type as the rtvec probably you'll have
immediately an idea here?


Thanks
Bernd.
Bernd Edlinger Oct. 5, 2019, 6:12 a.m. UTC | #8
On 10/3/19 5:25 PM, Jakub Jelinek wrote:
> On Thu, Oct 03, 2019 at 03:17:47PM +0000, Bernd Edlinger wrote:
>> Hi,
>>
>> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
>> which happen when this macro is used recursively in a macro
>> argument.  The __typeof (RTX) const _rtx in the inner macro
>> expansions shadows the outer macro expansions.
>>
>> So reworked the macro to not use statement expressions but
>> use templates instead.  Since the 7-argument overload is not
>> used anywhere removed RTL_FLAG_CHECK7 for now.
> 
> 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.

> 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.


Bernd.
Bernd Edlinger Oct. 5, 2019, 6:15 a.m. UTC | #9
On 10/4/19 10:26 AM, Segher Boessenkool wrote:
> On Thu, Oct 03, 2019 at 05:25:55PM +0200, Jakub Jelinek wrote:
>> On Thu, Oct 03, 2019 at 03:17:47PM +0000, Bernd Edlinger wrote:
>>> this fixes -Wshadow=local warnings in the RTL_FLAG_CHECKx macros,
>>> which happen when this macro is used recursively in a macro
>>> argument.  The __typeof (RTX) const _rtx in the inner macro
>>> expansions shadows the outer macro expansions.
>>>
>>> So reworked the macro to not use statement expressions but
>>> use templates instead.  Since the 7-argument overload is not
>>> used anywhere removed RTL_FLAG_CHECK7 for now.
>>
>> What effect does this have on the cc1/cc1plus .text sizes?
>> 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.
> 
> Also, how much slower does it make RTL checking builds?
> 

Okay, I bootstrapped r276457:

with patch,  --enable-languages=all --enable-checking=yes,rtl
1:03:30

unpatched, --enable-languages=all --enable-checking=yes,rtl
1:03:18

unpatched, --enable-languages=all
0:58:41


The difference is only small, if at all significant.

I used the later version of the patch here:
https://gcc.gnu.org/ml/gcc-patches/2019-10/msg00365.html

since the original version did not work with --enable-checking=rtl.


Bernd.
Jakub Jelinek Oct. 5, 2019, 7:24 a.m. UTC | #10
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.

> > 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.

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
Bernd Edlinger Oct. 6, 2019, 7:52 p.m. UTC | #11
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
>
Bernd Edlinger Oct. 20, 2019, 9:25 p.m. UTC | #12
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:
>>> 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.
> 
> 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.
> 

Okay, I think I have fixed both the "s" ignoring the skip status on inlined
subroutines, with a gdb-patch I posted here:
http://sourceware.org/ml/gdb-patches/2019-10/msg00685.html

And the "n" jumping in the bottom half if the inlined template, will be fixed
by the patch "Fix dwarf-lineinfo inconsistency of inlined subroutines"
which I posted here:
https://gcc.gnu.org/ml/gcc-patches/2019-10/msg01459.html

Those only affect optimized code, and are already there with the tree.h
as you will probably know.

With those two patches the rtl-checking patch creates both on non-optimized
stage-1 compiler and an optimized stage-3 compiler a very consistent debug
impression.

I have cleaned up the rtl checking patch once more, removed the no longer used
RTL_CHECKC3, XC3EXP macros, and found a way to suppress a template specialization
in gdbinit.in using a regular expression matching syntax, instead of suppressing
all of rtl.h, that might be more specific than suppressing per file.
Suppressing all of rtl.h would work as well, if that is considered a better approach.


Now I think the show-stoppers, regarding debuggability of the template-driven
rtl-checking macros are no longer an issue, right?

Also performance-wise it is better than what we had before, IMHO.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.
diff mbox series

Patch

2019-10-03  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* rtl.h (RTL_FLAG_CHECK): New variadic macro.
	(RTL_FLAG_CHECK1-6): Use RTL_FLAG_CHECK.
	(RTL_FLAG_CHECK7): Remove.
	(rtl_flag_check, check_rtl_code): New helper functions.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 276484)
+++ gcc/rtl.h	(working copy)
@@ -1249,66 +1249,18 @@  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, ...) 					\
+  ((__typeof (&*(RTX))) rtl_flag_check (check_rtl_code<__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 +1274,87 @@  extern void rtl_check_failed_flag (const char *, c
     ATTRIBUTE_NORETURN ATTRIBUTE_COLD
     ;
 
+static inline rtx
+rtl_flag_check (bool (*check) (const_rtx), const char *name, rtx rtl,
+		const char *file, int line, const char *func)
+{ 
+  if (!check (rtl))
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+static inline const_rtx
+rtl_flag_check (bool (*check) (const_rtx), const char *name, const_rtx rtl,
+		const char *file, int line, const char *func)
+{ 
+  if (!check (rtl))
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1>
+inline bool
+check_rtl_code (const_rtx rtl)
+{ 
+  if (GET_CODE (rtl) != C1)
+    return false;
+  return true;
+}
+
+template<RTX_CODE C1, RTX_CODE C2>
+inline bool
+check_rtl_code (const_rtx rtl)
+{ 
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2)
+    return false;
+  return true;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3>
+inline bool
+check_rtl_code (const_rtx rtl)
+{ 
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3)
+    return false;
+  return true;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4>
+inline bool
+check_rtl_code (const_rtx rtl)
+{ 
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4)
+    return false;
+  return true;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, RTX_CODE C5>
+inline bool
+check_rtl_code (const_rtx rtl)
+{ 
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4
+      && GET_CODE (rtl) != C5)
+    return false;
+  return true;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, RTX_CODE C5, RTX_CODE C6>
+inline bool
+check_rtl_code (const_rtx rtl)
+{ 
+  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)
+    return false;
+  return true;
+}
+
 #else	/* not ENABLE_RTL_FLAG_CHECKING */
 
 #define RTL_FLAG_CHECK1(NAME, RTX, C1)					(RTX)
@@ -1330,7 +1363,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