Noob question about simple customization of GCC.
How hard would it be to add a tree-like structure and headers/sections to the -v gcc option so you can see the call structure. Would this be a reasonable first contribution/customization for a noob? It'll be a while before I can reasonably work on this. GCC version config | cc1 main.c | cc1 config and | output -> tempfile.s '*extra space' *between each lowest level command | as -v | output -> tempfile.o | collect2.exe | output |- ld.exe | output -> tempfile.exe
Optional machine prefix for programs in for -B dirs, matching Clang
Problem: It's somewhat annoying to have to tell GCC --with-as=... --with-ld=... just to prefix those commands the same way GCC is prefixed. In particular, when doing host-only build (skipping all target libraries), one otherwise doesn't need the target-specific binutils to be yet built, but --with-as and --with-ld will complain if the referenced exes cannot be found. This might sound esoteric, but as someone that spends a lot of time optimizing bootstrap dependency graphs for incrementality / parallelism, it is quite a real-world annoyance. Solution: I think the solution is to stop making cross compilers rely on these --with-flags to do the obvious things. Executables like `collect2` hidden within a libexesubdir (libexec/gcc//) have no need for prefixing, but the assembler and linker are very much public-facing executables in their own right, and usually are prefixed. Per [1], Clang does in fact look up prefixed exes against -B across the board. Making GCC look up exes that same way seems like a fine solution too. What do you all think? John [1]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-b-prefix
Re: Optional machine prefix for programs in for -B dirs, matching Clang
On Wed, 4 Aug 2021, 08:26 John Ericson wrote: > Problem: > > It's somewhat annoying to have to tell GCC --with-as=... --with-ld=... > just to prefix those commands the same way GCC is prefixed. > Doesn't GCC automatically look for those commands in the --prefix directory that you configure GCC with? Or is that only for native compilers?
Re: Optional machine prefix for programs in for -B dirs, matching Clang
On Wed, Aug 4, 2021, at 3:32 AM, Jonathan Wakely via Gcc wrote: > > Doesn't GCC automatically look for those commands in the --prefix directory > that you configure GCC with? Or is that only for native compilers? > It will search only if --with-*=... was not passed, and it will never prefix the query. So yes in practice for cross compilers people do the --with-* and no searching happens, and for native compilers no one bothers and searching does happen. But to be a pedant strictly speaking the behavior is independent of whether the compiler is host == target or not.
Re: Optional machine prefix for programs in for -B dirs, matching Clang
On Wed, 4 Aug 2021 at 08:41, John Ericson wrote: > > On Wed, Aug 4, 2021, at 3:32 AM, Jonathan Wakely via Gcc wrote: > > > > Doesn't GCC automatically look for those commands in the --prefix directory > > that you configure GCC with? Or is that only for native compilers? > > > > It will search only if --with-*=... was not passed, and it will never prefix > the query. So yes in practice for cross compilers people do the --with-* and > no searching happens, and for native compilers no one bothers and searching > does happen. But to be a pedant strictly speaking the behavior is independent > of whether the compiler is host == target or not. I've just checked, and I have a few cross-compilers (for testing purposes) where I configure binutils and gcc with the same --prefix, and don't use --with-as or --with-ld, and GCC finds the right assembler and linker. So do you need to change anything in GCC? Can't you just not use --with-as and --with-ld if they are causing problems?
Re: [RFC] Adding a new attribute to function param to mark it as constant
On 03/08/2021 18:44, Martin Sebor wrote: On 8/3/21 4:11 AM, Prathamesh Kulkarni via Gcc wrote: On Tue, 27 Jul 2021 at 13:49, Richard Biener wrote: On Mon, Jul 26, 2021 at 11:06 AM Prathamesh Kulkarni via Gcc wrote: On Fri, 23 Jul 2021 at 23:29, Andrew Pinski wrote: On Fri, Jul 23, 2021 at 3:55 AM Prathamesh Kulkarni via Gcc wrote: Hi, Continuing from this thread, https://gcc.gnu.org/pipermail/gcc-patches/2021-July/575920.html The proposal is to provide a mechanism to mark a parameter in a function as a literal constant. Motivation: Consider the following intrinsic vshl_n_s32 from arrm/arm_neon.h: __extension__ extern __inline int32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vshl_n_s32 (int32x2_t __a, const int __b) { return (int32x2_t)__builtin_neon_vshl_nv2si (__a, __b); } and it's caller: int32x2_t f (int32x2_t x) { return vshl_n_s32 (x, 1); } Can't you do similar to what is done already in the aarch64 back-end: #define __AARCH64_NUM_LANES(__v) (sizeof (__v) / sizeof (__v[0])) #define __AARCH64_LANE_CHECK(__vec, __idx) \ __builtin_aarch64_im_lane_boundsi (sizeof(__vec), sizeof(__vec[0]), __idx) ? Yes this is about lanes but you could even add one for min/max which is generic and such; add an argument to say the intrinsics name even. You could do this as a non-target builtin if you want and reuse it also for the aarch64 backend. Hi Andrew, Thanks for the suggestions. IIUC, we could use this approach to check if the argument falls within a certain range (min / max), but I am not sure how it will help to determine if the arg is a constant immediate ? AFAIK, vshl_n intrinsics require that the 2nd arg is immediate ? Even the current RTL builtin checking is not consistent across optimization levels: For eg: int32x2_t f(int32_t *restrict a) { int32x2_t v = vld1_s32 (a); int b = 2; return vshl_n_s32 (v, b); } With pristine trunk, compiling with -O2 results in no errors because constant propagation replaces 'b' with 2, and during expansion, expand_builtin_args is happy. But at -O0, it results in the error - "argument 2 must be a constant immediate". So I guess we need some mechanism to mark a parameter as a constant ? I guess you want to mark it in a way that the frontend should force constant evaluation and error if that's not possible? C++ doesn't allow to declare a parameter as 'constexpr' but something like void foo (consteval int i); since I guess you do want to allow passing constexpr arguments in C++ or in C extended forms of constants like static const int a[4]; foo (a[1]); ? But yes, this looks useful to me. Hi Richard, Thanks for the suggestions and sorry for late response. I have attached a prototype patch that implements consteval attribute. As implemented, the attribute takes at least one argument(s), which refer to parameter position, and the corresponding parameter must be const qualified, failing which, the attribute is ignored. I'm curious why the argument must be const-qualified. If it's to keep it from being changed in ways that would prevent it from being evaluated at compile-time in the body of the function then to be effective, the enforcement of the constraint should be on the definition of the function. Otherwise, the const qualifier could be used in a declaration of a function but left out from a subsequent definition of it, letting it modify it, like so: __attribute__ ((consteval (1))) void f (const int); inline __attribute__ ((always_inline)) void f (int i) { ++i; } In this particular case it's because the inline function is implementing an intrinsic operation in the architecture and the instruction only supports a literal constant value. At present we catch this while trying to expand the intrinsic, but that can lead to poor diagnostics because we really want to report against the line of code calling the intrinsic. R. That said, if compile-time function evaluation is the goal then a fully general solution is an attribute that applies to the whole function, not just a subset of its arguments. That way arguments can also be assigned to local variables within the function that can then be modified while still evaluated at compile time and used where constant expressions are expected. I.e., the design goal is [a subset of] C++ constexpr. (Obviously a much bigger project.) A few notes on the prototype patch: conventionally GCC warnings about attributes do not mention when an attribute is ignored. It may be a nice touch to add to all of them but I'd recommend against doing that in individual handlers. Since the attribute allows pointer constants the warning issued when an argument is not one should be generalized (i.e., not refer to just integer constants). (Other than that, C/C++ warnings should start in lowercase and not end in a period). Martin The patch does type-checking for arguments in check_function_consteval_attr, which simply does a linear search to
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, 4 Aug 2021 at 03:27, Segher Boessenkool wrote: > > Hi! > > On Fri, Jul 23, 2021 at 04:23:42PM +0530, Prathamesh Kulkarni via Gcc wrote: > > The constraint here is that, vshl_n intrinsics require that the > > second arg (__b), > > should be an immediate value. > > Something that matches the "n" constraint, not necessarily a literal, > but stricter than just "immediate". It probably is a good idea to allow > only "integer constant expression"s, so that the validity of the source > code does not depend on what the optimisers do with the code. > > > As Richard suggested, sth like: > > void foo(int x __attribute__((literal_constant (min_val, max_val))); > > The Linux kernel has a macro __is_constexpr to test if something is an > integer constant expression, see . That is a much > better idea imo. There could be a builtin for that of course, but an > attribute is less powerful, less usable, less useful. Hi Segher, Thanks for the suggestions. I am not sure tho if we could use a macro similar to __is_constexpr to check if parameter is constant inside an inline function (which is the case for intrinsics) ? For eg: #define __is_constexpr(x) \ (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) inline int foo(const int x) { _Static_assert (__is_constexpr (x)); return x; } int main() { return foo (1); } results in: foo.c: In function ‘foo’: foo.c:8:3: error: static assertion failed 8 | _Static_assert (__is_constexpr (x)); Initially we tried to use __Static_assert (__builtin_constant_p (arg)) for the same purpose but that did not work because while parsing the intrinsic function, the FE cannot determine if the arg is indeed a constant. I guess the static assertion or __is_constexpr would work only if the intrinsic were defined as a macro instead of an inline function ? Or am I misunderstanding ? Thanks, Prathamesh > > > Segher
Re: Add ops_num to targetm.sched.reassociation_width hook
On Wed, Aug 4, 2021 at 2:07 AM Aaron Sawdey wrote: > > Richard, > > So, I’m noticing that in get_reassociation_width() we know how many ops > (ops_num) are in the expression being considered for parallel reassociation, > but this is not passed to the target hook. In my testing this seems like it > might be useful to have. If you determine the maximum width that gives > additional speedup for a large number of terms, and then use that as the > width from the target hook, get_reassociation_width() is more aggressive than > you would like for small expressions with maybe 4-16 terms and produces code > that is slower than optimal. For example in many cases you want to continue > using a width of 1 until you get to 16 terms or so. My testing shows this to > be the case for power8, power9, and power10 processors. > > So, I’m wondering how it might be received if I posted a patch that adds this > to the reassociation_width target hook (and of course fixes all uses of that > target hook)? You probably saw that get_reassociation_width already tries to optimize things. So what exactly would you change and why is it slower for 4-16 terms but not for 17+ ones? I suppose "is slower" is --param mining on some benchmarks on your side and eventually you manage to pick the best threshold to not run into register pressure issues (by luck) for those benchmarks? That said, I question you can explain why it is slower, right? Richard. > Thanks! >Aaron > > > Aaron Sawdey, Ph.D. saw...@linux.ibm.com > IBM Linux on POWER Toolchain > >
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, Aug 04, 2021 at 03:20:45PM +0530, Prathamesh Kulkarni wrote: > On Wed, 4 Aug 2021 at 03:27, Segher Boessenkool > wrote: > > The Linux kernel has a macro __is_constexpr to test if something is an > > integer constant expression, see . That is a much > > better idea imo. There could be a builtin for that of course, but an > > attribute is less powerful, less usable, less useful. > Hi Segher, > Thanks for the suggestions. I am not sure tho if we could use a macro > similar to __is_constexpr > to check if parameter is constant inside an inline function (which is > the case for intrinsics) ? I said we can make a builtin that returns if its arg is an ICE -- we do not have to do tricky tricks :-) The macro would work fine in an inline function though, or, where do you see potential problems? > For eg: > #define __is_constexpr(x) \ > (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) > > inline int foo(const int x) > { > _Static_assert (__is_constexpr (x)); > return x; > } > > int main() > { > return foo (1); > } > > results in: > foo.c: In function ‘foo’: > foo.c:8:3: error: static assertion failed > 8 | _Static_assert (__is_constexpr (x)); And that is correct, x is *not* an integer constant expression here. Because it is a variable, instead :-) If you do this in a macro it should work though? > Initially we tried to use __Static_assert (__builtin_constant_p (arg)) > for the same purpose but that did not work > because while parsing the intrinsic function, the FE cannot determine > if the arg is indeed a constant. Yes. If you want something like that you need to test very late during compilation whether something is a constant then: it will not be earlier. > I guess the static assertion or __is_constexpr would work only if the > intrinsic were defined as a macro instead of an inline function ? > Or am I misunderstanding ? Both __builtin_constant_p and __is_constexpr will not work in your use case (since a function argument is not a constant, let alone an ICE). It only becomes a constant value later on. The manual (for the former) says: You may use this built-in function in either a macro or an inline function. However, if you use it in an inlined function and pass an argument of the function as the argument to the built-in, GCC never returns 1 when you call the inline function with a string constant or compound literal (see Compound Literals) and does not return 1 when you pass a constant numeric value to the inline function unless you specify the -O option. An integer constant expression is well-defined whatever the optimisation level is, it is a feature of the language. If some x is an ICE you can do asm ("" :: "n"(x)); and if it is a constant you can do asm ("" :: "i"(x)); (not that that gets you much further, but it might help explorng this). Segher
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, 4 Aug 2021 at 15:49, Segher Boessenkool wrote: > > On Wed, Aug 04, 2021 at 03:20:45PM +0530, Prathamesh Kulkarni wrote: > > On Wed, 4 Aug 2021 at 03:27, Segher Boessenkool > > wrote: > > > The Linux kernel has a macro __is_constexpr to test if something is an > > > integer constant expression, see . That is a much > > > better idea imo. There could be a builtin for that of course, but an > > > attribute is less powerful, less usable, less useful. > > Hi Segher, > > Thanks for the suggestions. I am not sure tho if we could use a macro > > similar to __is_constexpr > > to check if parameter is constant inside an inline function (which is > > the case for intrinsics) ? > > I said we can make a builtin that returns if its arg is an ICE -- we do > not have to do tricky tricks :-) > > The macro would work fine in an inline function though, or, where do you > see potential problems? > > > For eg: > > #define __is_constexpr(x) \ > > (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int > > *)8))) > > > > inline int foo(const int x) > > { > > _Static_assert (__is_constexpr (x)); > > return x; > > } > > > > int main() > > { > > return foo (1); > > } > > > > results in: > > foo.c: In function ‘foo’: > > foo.c:8:3: error: static assertion failed > > 8 | _Static_assert (__is_constexpr (x)); > > And that is correct, x is *not* an integer constant expression here. > Because it is a variable, instead :-) > > If you do this in a macro it should work though? > > > Initially we tried to use __Static_assert (__builtin_constant_p (arg)) > > for the same purpose but that did not work > > because while parsing the intrinsic function, the FE cannot determine > > if the arg is indeed a constant. > > Yes. If you want something like that you need to test very late during > compilation whether something is a constant then: it will not be earlier. > > > I guess the static assertion or __is_constexpr would work only if the > > intrinsic were defined as a macro instead of an inline function ? > > Or am I misunderstanding ? > > Both __builtin_constant_p and __is_constexpr will not work in your use > case (since a function argument is not a constant, let alone an ICE). > It only becomes a constant value later on. The manual (for the former) > says: > You may use this built-in function in either a macro or an inline > function. However, if you use it in an inlined function and pass an > argument of the function as the argument to the built-in, GCC never > returns 1 when you call the inline function with a string constant or > compound literal (see Compound Literals) and does not return 1 when you > pass a constant numeric value to the inline function unless you specify > the -O option. Indeed, that's why I was thinking if we should use an attribute to mark param as a constant, so during type-checking the function call, the compiler can emit a diagnostic if the passed arg is not a constant. Alternatively -- as you suggest, we could define a new builtin, say __builtin_ice(x) that returns true if 'x' is an ICE. And wrap the intrinsic inside a macro that would check if the arg is an ICE ? For eg: __extension__ extern __inline int32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vshl_n_s32_1 (int32x2_t __a, const int __b) { return __builtin_neon_vshl_nv2si (__a, __b); } #define vshl_n_s32(__a, __b) \ ({ typeof (__a) a = (__a); \ _Static_assert (__builtin_constant_p ((__b)), #__b " is not an integer constant"); \ vshl_n_s32_1 (a, (__b)); }) void f(int32x2_t x, const int y) { vshl_n_s32 (x, 2); vshl_n_s32 (x, y); int z = 1; vshl_n_s32 (x, z); } With this, the compiler rejects vshl_n_s32 (x, y) and vshl_n_s32 (x, z) at all optimization levels since neither 'y' nor 'z' is an ICE. Instead of __builtin_constant_p, we could use __builtin_ice. Would that be a reasonable approach ? But this changes the semantics of intrinsic from being an inline function to a macro, and I am not sure if that's a good idea. Thanks, Prathamesh > An integer constant expression is well-defined whatever the optimisation > level is, it is a feature of the language. > > If some x is an ICE you can do > asm ("" :: "n"(x)); > and if it is a constant you can do > asm ("" :: "i"(x)); > (not that that gets you much further, but it might help explorng this). > > > Segher
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, Aug 04, 2021 at 05:20:58PM +0530, Prathamesh Kulkarni wrote: > On Wed, 4 Aug 2021 at 15:49, Segher Boessenkool > wrote: > > Both __builtin_constant_p and __is_constexpr will not work in your use > > case (since a function argument is not a constant, let alone an ICE). > > It only becomes a constant value later on. The manual (for the former) > > says: > > You may use this built-in function in either a macro or an inline > > function. However, if you use it in an inlined function and pass an > > argument of the function as the argument to the built-in, GCC never > > returns 1 when you call the inline function with a string constant or > > compound literal (see Compound Literals) and does not return 1 when you > > pass a constant numeric value to the inline function unless you specify > > the -O option. > Indeed, that's why I was thinking if we should use an attribute to mark param > as > a constant, so during type-checking the function call, the compiler > can emit a diagnostic if the passed arg > is not a constant. That will depend on the vagaries of what optimisations the compiler managed to do :-( > Alternatively -- as you suggest, we could define a new builtin, say > __builtin_ice(x) that returns true if 'x' is an ICE. (That is a terrible name, it's not clear at all to the reader, just write it out? It is fun if you know what it means, but infuriating otherwise.) > And wrap the intrinsic inside a macro that would check if the arg is an ICE ? That will work yeah. Maybe not as elegant as you'd like, but not all that bad, and it *works*. Well, hopefully it does :-) > For eg: > > __extension__ extern __inline int32x2_t > __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) > vshl_n_s32_1 (int32x2_t __a, const int __b) > { > return __builtin_neon_vshl_nv2si (__a, __b); > } > > #define vshl_n_s32(__a, __b) \ > ({ typeof (__a) a = (__a); \ >_Static_assert (__builtin_constant_p ((__b)), #__b " is not an > integer constant"); \ >vshl_n_s32_1 (a, (__b)); }) > > void f(int32x2_t x, const int y) > { > vshl_n_s32 (x, 2); > vshl_n_s32 (x, y); > > int z = 1; > vshl_n_s32 (x, z); > } > > With this, the compiler rejects vshl_n_s32 (x, y) and vshl_n_s32 (x, > z) at all optimization levels since neither 'y' nor 'z' is an ICE. You used __builtin_constant_p though, which works differently, so the test is not conclusive, might not show what you want to show. > Instead of __builtin_constant_p, we could use __builtin_ice. > Would that be a reasonable approach ? I think it will work, yes. > But this changes the semantics of intrinsic from being an inline > function to a macro, and I am not sure if that's a good idea. Well, what happens if you call the actual builtin directly, with some non-constant parameter? That just fails with a more cryptic error, right? So you can view this as some syntactic sugar to make these intrinsics easier to use. Hrm I now remember a place I could have used this: #define mtspr(n, x) do { asm("mtspr %1,%0" : : "r"(x), "n"(n)); } while (0) #define mfspr(n) ({ \ u32 x; asm volatile("mfspr %0,%1" : "=r"(x) : "n"(n)); x; \ }) It is quite similar to your builtin code really, and I did resort to macros there, for similar reasons :-) Segher
Re: [RFC] Adding a new attribute to function param to mark it as constant
On 04/08/2021 13:46, Segher Boessenkool wrote: > On Wed, Aug 04, 2021 at 05:20:58PM +0530, Prathamesh Kulkarni wrote: >> On Wed, 4 Aug 2021 at 15:49, Segher Boessenkool >> wrote: >>> Both __builtin_constant_p and __is_constexpr will not work in your use >>> case (since a function argument is not a constant, let alone an ICE). >>> It only becomes a constant value later on. The manual (for the former) >>> says: >>> You may use this built-in function in either a macro or an inline >>> function. However, if you use it in an inlined function and pass an >>> argument of the function as the argument to the built-in, GCC never >>> returns 1 when you call the inline function with a string constant or >>> compound literal (see Compound Literals) and does not return 1 when you >>> pass a constant numeric value to the inline function unless you specify >>> the -O option. >> Indeed, that's why I was thinking if we should use an attribute to mark >> param as >> a constant, so during type-checking the function call, the compiler >> can emit a diagnostic if the passed arg >> is not a constant. > > That will depend on the vagaries of what optimisations the compiler > managed to do :-( > >> Alternatively -- as you suggest, we could define a new builtin, say >> __builtin_ice(x) that returns true if 'x' is an ICE. > > (That is a terrible name, it's not clear at all to the reader, just > write it out? It is fun if you know what it means, but infuriating > otherwise.) > >> And wrap the intrinsic inside a macro that would check if the arg is an ICE ? > > That will work yeah. Maybe not as elegant as you'd like, but not all > that bad, and it *works*. Well, hopefully it does :-) > >> For eg: >> >> __extension__ extern __inline int32x2_t >> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) >> vshl_n_s32_1 (int32x2_t __a, const int __b) >> { >> return __builtin_neon_vshl_nv2si (__a, __b); >> } >> >> #define vshl_n_s32(__a, __b) \ >> ({ typeof (__a) a = (__a); \ >>_Static_assert (__builtin_constant_p ((__b)), #__b " is not an >> integer constant"); \ >>vshl_n_s32_1 (a, (__b)); }) >> >> void f(int32x2_t x, const int y) >> { >> vshl_n_s32 (x, 2); >> vshl_n_s32 (x, y); >> >> int z = 1; >> vshl_n_s32 (x, z); >> } >> >> With this, the compiler rejects vshl_n_s32 (x, y) and vshl_n_s32 (x, >> z) at all optimization levels since neither 'y' nor 'z' is an ICE. > > You used __builtin_constant_p though, which works differently, so the > test is not conclusive, might not show what you want to show. > >> Instead of __builtin_constant_p, we could use __builtin_ice. >> Would that be a reasonable approach ? > > I think it will work, yes. > >> But this changes the semantics of intrinsic from being an inline >> function to a macro, and I am not sure if that's a good idea. > > Well, what happens if you call the actual builtin directly, with some > non-constant parameter? That just fails with a more cryptic error, > right? So you can view this as some syntactic sugar to make these > intrinsics easier to use. > > Hrm I now remember a place I could have used this: > > #define mtspr(n, x) do { asm("mtspr %1,%0" : : "r"(x), "n"(n)); } while (0) > #define mfspr(n) ({ \ > u32 x; asm volatile("mfspr %0,%1" : "=r"(x) : "n"(n)); x; \ > }) > > It is quite similar to your builtin code really, and I did resort to > macros there, for similar reasons :-) > > > Segher > We don't want to have to resort to macros. Not least because at some point we want to replace the content of arm_neon.h with a single #pragma directive to remove all the parsing of the header that's needed. What's more, if we had a suitable pragma we'd stand a fighting chance of being able to extend support to other languages as well that don't use the pre-processor, such as Fortran or Ada (not that that is on the cards right now). R.
Re: Optional machine prefix for programs in for -B dirs, matching Clang
> On Aug 4, 2021, at 3:32 AM, Jonathan Wakely via Gcc wrote: > > On Wed, 4 Aug 2021, 08:26 John Ericson wrote: > >> Problem: >> >> It's somewhat annoying to have to tell GCC --with-as=... --with-ld=... >> just to prefix those commands the same way GCC is prefixed. >> > > Doesn't GCC automatically look for those commands in the --prefix directory > that you configure GCC with? Or is that only for native compilers? It does. That's how I configure my cross-builds. paul
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, Aug 04, 2021 at 02:00:42PM +0100, Richard Earnshaw wrote: > We don't want to have to resort to macros. Not least because at some > point we want to replace the content of arm_neon.h with a single #pragma > directive to remove all the parsing of the header that's needed. What's > more, if we had a suitable pragma we'd stand a fighting chance of being > able to extend support to other languages as well that don't use the > pre-processor, such as Fortran or Ada (not that that is on the cards > right now). So how do you want to handle constants-that-are-not-yet-constant, say before inlining? And how do you want to deal with those possibly not ever becoming constant, perhaps because you used a too low "n" in -On (but there are very many random other causes)? And, what *is* a constant, anyway? This is even more fuzzy if you consider those other languages as well. (Does skipping parsing of some trivial header save so much time? Huh!) Segher
Re: [RFC] Adding a new attribute to function param to mark it as constant
On 04/08/2021 14:40, Segher Boessenkool wrote: On Wed, Aug 04, 2021 at 02:00:42PM +0100, Richard Earnshaw wrote: We don't want to have to resort to macros. Not least because at some point we want to replace the content of arm_neon.h with a single #pragma directive to remove all the parsing of the header that's needed. What's more, if we had a suitable pragma we'd stand a fighting chance of being able to extend support to other languages as well that don't use the pre-processor, such as Fortran or Ada (not that that is on the cards right now). So how do you want to handle constants-that-are-not-yet-constant, say before inlining? And how do you want to deal with those possibly not ever becoming constant, perhaps because you used a too low "n" in -On (but there are very many random other causes)? And, what *is* a constant, anyway? This is even more fuzzy if you consider those other languages as well. (Does skipping parsing of some trivial header save so much time? Huh!) Trivial? arm_neon.h is currently 20k lines of source. What's more, it has to support inline functions that might not be available when the header is parsed, but might become available if the user subsequently compiles a function with different attributes enabled. It is very definitely *NOT* trivial. R. Segher
Re: Re: Optional machine prefix for programs in for -B dirs, match ing Clang
Hello, On Wed, 4 Aug 2021, John Ericson wrote: > > Doesn't GCC automatically look for those commands in the --prefix > > directory that you configure GCC with? Or is that only for native > > compilers? > > It will search only if --with-*=... was not passed, and it will never > prefix the query. So yes in practice for cross compilers people do the > --with-* Hmm, no? Because as you said ... > I think the solution is to stop making cross compilers rely on these > --with-flags to do the obvious things. Executables like `collect2` > hidden within a libexesubdir (libexec/gcc//) have no > need for prefixing, but the assembler and linker are very much > public-facing executables in their own right, and usually are prefixed. ... the 'as' and 'ld' executables should be simply found within the version and target specific GCC libexecsubdir, possibly by being symlinks to whatever you want. That's at least how my crosss are configured and installed, without any --with-{as,ld} options. > and no searching happens, and for native compilers no one > bothers and searching does happen. But to be a pedant strictly speaking > the behavior is independent of whether the compiler is host == target or > not. Ciao, Michael.
Re: daily report on extending static analyzer project [GSoC]
AIM for today: - Extract out the pointer that is being used to call the vfunc from the current region. - Search it's regions to find out which subclass the pointer is actually pointing to. - Make use of this information to filter out one most probable call to function out of all of the possible functions that can be called at that callsite. — PROGRESS : - From observation, a typical vfunc call that isn't devirtualised by the compiler's front end looks something like this "OBJ_TYPE_REF(_2;(struct A)a_ptr_5(D)->0) (a_ptr_5(D))" where "a_ptr_5(D)" is pointer that is being used to call the virtual function. - We can access it's region to see what is the type of the object the pointer is actually pointing to. - This is then used to find a call with DECL_CONTEXT of the object from the all the possible targets of that polymorphic call. - The changes can be tested on refs/users/arsenic/heads/polymorphic_cal branch of the repository. - I tested the changes with on the following test program ( https://godbolt.org/z/fqrsE1d84 ) And it successfully provided the following analysis : ``` /Users/ankursaini/Desktop/test.cpp: In member function ‘virtual int B::deallocate()’: /Users/ankursaini/Desktop/test.cpp:25:13: warning: double-‘free’ of ‘b.B::ptr’ [CWE-415] [-Wanalyzer-double-free] 25 | free(ptr); | ^ ‘void test()’: events 1-2 | | 35 | void test() | | ^~~~ | | | | | (1) entry to ‘test’ |.. | 40 | b.allocate(); | | | | | | | (2) calling ‘B::allocate’ from ‘test’ | +--> ‘void B::allocate()’: events 3-4 | | 19 | void allocate () | | ^~~~ | | | | | (3) entry to ‘B::allocate’ | 20 | { | 21 | ptr = (int*)malloc(sizeof(int)); | | ~~~ | | | | | (4) allocated here | <--+ | ‘void test()’: events 5-6 | | 40 | b.allocate(); | | ~~^~ | | | | | (5) returning to ‘test’ from ‘B::allocate’ | 41 | foo(aptr); | | ~ | || | |(6) calling ‘foo’ from ‘test’ | +--> ‘void foo(A*)’: events 7-8 | | 30 | void foo(A *a_ptr) | | ^~~ | | | | | (7) entry to ‘foo’ | 31 | { | 32 | printf("%d\n",a_ptr->deallocate()); | | ~~ | | | | | (8) calling ‘B::deallocate’ from ‘foo’ | +--> ‘virtual int B::deallocate()’: events 9-10 | | 23 | int deallocate (void) | | ^~ | | | | | (9) entry to ‘B::deallocate’ | 24 | { | 25 | free(ptr); | | ~ | | | | | (10) first ‘free’ here | <--+ | ‘void foo(A*)’: event 11 | | 32 | printf("%d\n",a_ptr->deallocate()); | | ~~^~~~ | | | | | (11) returning to ‘foo’ from ‘B::deallocate’ | <--+ | ‘void test()’: events 12-13 | | 41 | foo(aptr); | | ~~~^~ | || | |(12) returning to ‘test’ from ‘foo’ |.. | 45 | foo(aptr); | | ~ | || | |(13) calling ‘foo’ from ‘test’ | +--> ‘void foo(A*)’: events 14-15 | | 30 | void foo(A *a_ptr) | | ^~~ | | | | | (14) entry to ‘foo’ | 31 | { | 32 | printf("%d\n",a_ptr->deallocate()); | | ~~ | | | | | (15) calling ‘B::deallocate’ from ‘foo’ | +--> ‘virtual int B::deallocate()’: events 16-17 | | 23 | int deallocate (void) | | ^~ | | | | | (16) entry to ‘B::deallocate’ | 24 | { | 25 | free(ptr); | | ~
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, Aug 04, 2021 at 03:27:00PM +0100, Richard Earnshaw wrote: > On 04/08/2021 14:40, Segher Boessenkool wrote: > >On Wed, Aug 04, 2021 at 02:00:42PM +0100, Richard Earnshaw wrote: > >>We don't want to have to resort to macros. Not least because at some > >>point we want to replace the content of arm_neon.h with a single #pragma > >>directive to remove all the parsing of the header that's needed. What's > >>more, if we had a suitable pragma we'd stand a fighting chance of being > >>able to extend support to other languages as well that don't use the > >>pre-processor, such as Fortran or Ada (not that that is on the cards > >>right now). > > > >So how do you want to handle constants-that-are-not-yet-constant, say > >before inlining? And how do you want to deal with those possibly not > >ever becoming constant, perhaps because you used a too low "n" in -On > >(but there are very many random other causes)? And, what *is* a > >constant, anyway? This is even more fuzzy if you consider those > >other languages as well. > > > >(Does skipping parsing of some trivial header save so much time? Huh!) > > Trivial? arm_neon.h is currently 20k lines of source. What's more, it > has to support inline functions that might not be available when the > header is parsed, but might become available if the user subsequently > compiles a function with different attributes enabled. It is very > definitely *NOT* trivial. Ha yes :-) I just assumed without looking that it would be like other architectures' intrinsics headers. Whoops. Now I could ask how this monster came to be this big, but I will wisely back away. Slowly :-) Segher
Re: [RFC] Adding a new attribute to function param to mark it as constant
* Segher Boessenkool: > On Wed, Aug 04, 2021 at 03:27:00PM +0100, Richard Earnshaw wrote: >> On 04/08/2021 14:40, Segher Boessenkool wrote: >> >On Wed, Aug 04, 2021 at 02:00:42PM +0100, Richard Earnshaw wrote: >> >>We don't want to have to resort to macros. Not least because at some >> >>point we want to replace the content of arm_neon.h with a single #pragma >> >>directive to remove all the parsing of the header that's needed. What's >> >>more, if we had a suitable pragma we'd stand a fighting chance of being >> >>able to extend support to other languages as well that don't use the >> >>pre-processor, such as Fortran or Ada (not that that is on the cards >> >>right now). >> > >> >So how do you want to handle constants-that-are-not-yet-constant, say >> >before inlining? And how do you want to deal with those possibly not >> >ever becoming constant, perhaps because you used a too low "n" in -On >> >(but there are very many random other causes)? And, what *is* a >> >constant, anyway? This is even more fuzzy if you consider those >> >other languages as well. >> > >> >(Does skipping parsing of some trivial header save so much time? Huh!) >> >> Trivial? arm_neon.h is currently 20k lines of source. What's more, it >> has to support inline functions that might not be available when the >> header is parsed, but might become available if the user subsequently >> compiles a function with different attributes enabled. It is very >> definitely *NOT* trivial. > > Ha yes :-) I just assumed without looking that it would be like other > architectures' intrinsics headers. Whoops. But isn't it? $ echo '#include ' | gcc -E - | wc -l 41045 Thanks, Florian
Re: [RFC] Adding a new attribute to function param to mark it as constant
On Wed, Aug 04, 2021 at 07:08:08PM +0200, Florian Weimer wrote: > * Segher Boessenkool: > > > On Wed, Aug 04, 2021 at 03:27:00PM +0100, Richard Earnshaw wrote: > >> On 04/08/2021 14:40, Segher Boessenkool wrote: > >> >On Wed, Aug 04, 2021 at 02:00:42PM +0100, Richard Earnshaw wrote: > >> >>We don't want to have to resort to macros. Not least because at some > >> >>point we want to replace the content of arm_neon.h with a single #pragma > >> >>directive to remove all the parsing of the header that's needed. What's > >> >>more, if we had a suitable pragma we'd stand a fighting chance of being > >> >>able to extend support to other languages as well that don't use the > >> >>pre-processor, such as Fortran or Ada (not that that is on the cards > >> >>right now). > >> > > >> >So how do you want to handle constants-that-are-not-yet-constant, say > >> >before inlining? And how do you want to deal with those possibly not > >> >ever becoming constant, perhaps because you used a too low "n" in -On > >> >(but there are very many random other causes)? And, what *is* a > >> >constant, anyway? This is even more fuzzy if you consider those > >> >other languages as well. > >> > > >> >(Does skipping parsing of some trivial header save so much time? Huh!) > >> > >> Trivial? arm_neon.h is currently 20k lines of source. What's more, it > >> has to support inline functions that might not be available when the > >> header is parsed, but might become available if the user subsequently > >> compiles a function with different attributes enabled. It is very > >> definitely *NOT* trivial. > > > > Ha yes :-) I just assumed without looking that it would be like other > > architectures' intrinsics headers. Whoops. > > But isn't it? > > $ echo '#include ' | gcc -E - | wc -l > 41045 $ echo '#include ' | gcc -E - -maltivec | wc -l 9 Most of this file (774 lines) is #define's, which take essentially no time at all. And none of the other archs I have looked at have big headers either! Segher
Re: Optional machine prefix for programs in for -B dirs, match ing Clang
On Wed, Aug 4, 2021, at 10:48 AM, Michael Matz wrote: > ... the 'as' and 'ld' executables should be simply found within the > version and target specific GCC libexecsubdir, possibly by being symlinks > to whatever you want. That's at least how my crosss are configured and > installed, without any --with-{as,ld} options. Yes that does work, and that's probably the best option today. I'm just a little wary of unprefixing things programmatically. For some context, this is NixOS where we assemble a ton of cross compilers automatically and each package gets its own isolated many FHS. For that reason I would like to eventually avoid the target-specific subdirs entirely, as I have the separate package trees to disambiguate things. Now, I know that exact same argument could also be used to say target prefixing is also superfluous, but eventually things on the PATH need to be disambiguated. There is no requirement that the libexec things be named like the bin things, but I sort of feel it's one less thing to remember and makes debugging easier. I am sympathetic to the issue that if GCC accepts everything Clang does and vice-versa, we'll Postel's-law ourselves ourselves over time into madness as mistakes are accumulated rather than weeded out. But this one thing feels pretty innocuous to me, and it could also be made stricter by ensuring that we never *both* add the machine subdir *and* prefix the path --- i.e. at most 1 target-disambiguating method is used at a time. I now have some patches for this change I suppose I could also submit. Cheers, John
Re: daily report on extending static analyzer project [GSoC]
On Wed, 2021-08-04 at 21:32 +0530, Ankur Saini wrote: [...snip...] > > - From observation, a typical vfunc call that isn't devirtualised by > the compiler's front end looks something like this > "OBJ_TYPE_REF(_2;(struct A)a_ptr_5(D)->0) (a_ptr_5(D))" > where "a_ptr_5(D)" is pointer that is being used to call the virtual > function. > > - We can access it's region to see what is the type of the object the > pointer is actually pointing to. > > - This is then used to find a call with DECL_CONTEXT of the object > from the all the possible targets of that polymorphic call. [...] > > Patch file ( prototype ) : > > + /* Call is possibly a polymorphic call. > + > + In such case, use devirtisation tools to find > + possible callees of this function call. */ > + > + function *fun = get_current_function (); > + gcall *stmt = const_cast (call); > + cgraph_edge *e = cgraph_node::get (fun->decl)->get_edge (stmt); > + if (e->indirect_info->polymorphic) > + { > +void *cache_token; > +bool final; > +vec targets > + = possible_polymorphic_call_targets (e, &final, &cache_token, true); > +if (!targets.is_empty ()) > + { > +tree most_propbable_taget = NULL_TREE; > +if(targets.length () == 1) > + return targets[0]->decl; > + > +/* From the current state, check which subclass the pointer that > + is being used to this polymorphic call points to, and use to > + filter out correct function call. */ > +tree t_val = gimple_call_arg (call, 0); Maybe rename to "this_expr"? > +const svalue *sval = get_rvalue (t_val, ctxt); and "this_sval"? ...assuming that that's what the value is. Probably should reject the case where there are zero arguments. > + > +const region *reg > + = [&]()->const region * > + { > +switch (sval->get_kind ()) > + { > +case SK_INITIAL: > + { > +const initial_svalue *initial_sval > + = sval->dyn_cast_initial_svalue (); > +return initial_sval->get_region (); > + } > + break; > +case SK_REGION: > + { > +const region_svalue *region_sval > + = sval->dyn_cast_region_svalue (); > +return region_sval->get_pointee (); > + } > + break; > + > +default: > + return NULL; > + } > + } (); I think the above should probably be a subroutine. That said, it's not clear to me what it's doing, or that this is correct. I'm guessing that you need to see if *((void **)this) is a vtable pointer (or something like that), and, if so, which class it is for. Is there a way of getting the vtable pointer as an svalue? > +gcc_assert (reg); > + > +tree known_possible_subclass_type; > +known_possible_subclass_type = reg->get_type (); > +if (reg->get_kind () == RK_FIELD) > + { > + const field_region* field_reg = reg->dyn_cast_field_region (); > + known_possible_subclass_type > + = DECL_CONTEXT (field_reg->get_field ()); > + } > + > +for (cgraph_node *x : targets) > + { > +if (DECL_CONTEXT (x->decl) == known_possible_subclass_type) > + most_propbable_taget = x->decl; > + } > +return most_propbable_taget; > + } > + } > + >return NULL_TREE; > } Dave