* Re: [PATCH 00/11] pragma once: treewide conversion [not found] <YDvLYzsGu+l1pQ2y@localhost.localdomain> @ 2021-02-28 17:46 ` Linus Torvalds 2021-02-28 19:34 ` Alexey Dobriyan 0 siblings, 1 reply; 12+ messages in thread From: Linus Torvalds @ 2021-02-28 17:46 UTC (permalink / raw) To: Alexey Dobriyan, Luc Van Oostenryck Cc: Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Sun, Feb 28, 2021 at 8:57 AM Alexey Dobriyan <adobriyan@gmail.com> wrote: > > This is bulk deletion of preprocessor include guards and conversion > to #pragma once directive. So as mentioned earlier, I'm not 100% convinced about the advantage of #pragma once. But I decided to actually test it, and it turns out that it causes problems for at least sparse. Sparse *does* support pragma once, but it does it purely based on pathname equality. So a simple test-program like this: File 'pragma.h': #pragma once #include "header.h" works fine. But this doesn't work at all: #pragma once #include "./header.h" because it causes the filename to be different every time, and you eventually end up with trying to open "././....../pragma.h" and it causes ENAMETOOLONG. So at least sparse isn't ready for this. I guess sparse could always simplify the name, but that's non-trivial. And honestly, using st_dev/st_ino is problematic too, since (a) they can easily be re-used for generated files (b) you'd have to actually open/fstat the filename to use it, which obviates one of the optimizations Trying the same on gcc, you don't get that endless "add "./" behavior" that sparse did, but a quick test shows that it actually opens the file and reads it three times: once for "pramga.h", once for "./pragma.h" and a third time for "pragma.h". It only seems to _expand_ it once, though. I have no idea what gcc does. Maybe it does some "different name, so let's open and read it, and then does st_dev/st_ino again". But if so, why the _third_ time? Is it some guard against "st_ino might have been re-used, so I'll open the original name and re-verify"? End result: #pragma is fundamentally less reliable than the traditional #ifdef guard. The #ifdef guard works fine even if you re-read the file for whatever reason, while #pragma relies on some kind of magical behavior. I'm adding Luc in case he has any ideas of what the magical behavior might be. Honestly, I think #pragma once is complete garbage. It's really is fundamenetally more complicated than the #ifdef guard, and it has absolutely zero upsides. I'm not taking this pramga series unless somebody can explain why it's a good thing. Because all I see are downsides. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-02-28 17:46 ` [PATCH 00/11] pragma once: treewide conversion Linus Torvalds @ 2021-02-28 19:34 ` Alexey Dobriyan 2021-02-28 20:00 ` Linus Torvalds 2021-03-01 0:29 ` Luc Van Oostenryck 0 siblings, 2 replies; 12+ messages in thread From: Alexey Dobriyan @ 2021-02-28 19:34 UTC (permalink / raw) To: Linus Torvalds Cc: Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Sun, Feb 28, 2021 at 09:46:17AM -0800, Linus Torvalds wrote: > On Sun, Feb 28, 2021 at 8:57 AM Alexey Dobriyan <adobriyan@gmail.com> wrote: > > > > This is bulk deletion of preprocessor include guards and conversion > > to #pragma once directive. > > So as mentioned earlier, I'm not 100% convinced about the advantage of > #pragma once. > > But I decided to actually test it, and it turns out that it causes > problems for at least sparse. Oh no. > Sparse *does* support pragma once, but it does it purely based on > pathname equality. Doing what gcc or clang does seems like a smart thing to do. > So a simple test-program like this: > > File 'pragma.h': > > #pragma once > #include "header.h" > > works fine. But this doesn't work at all: > > #pragma once > #include "./header.h" > > because it causes the filename to be different every time, and you > eventually end up with trying to open "././....../pragma.h" and it > causes ENAMETOOLONG. > > So at least sparse isn't ready for this. > > I guess sparse could always simplify the name, but that's non-trivial. > > And honestly, using st_dev/st_ino is problematic too, since > > (a) they can easily be re-used for generated files > > (b) you'd have to actually open/fstat the filename to use it, which > obviates one of the optimizations fstat is more or less necessary anyway to allocate just enough memory for 1 read. fstat is not a problem, read is (and subsequent parsing). > Trying the same on gcc, you don't get that endless "add "./" behavior" > that sparse did, but a quick test shows that it actually opens the > file and reads it three times: once for "pramga.h", once for > "./pragma.h" and a third time for "pragma.h". It only seems to > _expand_ it once, though. > > I have no idea what gcc does. Maybe it does some "different name, so > let's open and read it, and then does st_dev/st_ino again". But if so, > why the _third_ time? Is it some guard against "st_ino might have been > re-used, so I'll open the original name and re-verify"? > > End result: #pragma is fundamentally less reliable than the > traditional #ifdef guard. The #ifdef guard works fine even if you > re-read the file for whatever reason, while #pragma relies on some > kind of magical behavior. > > I'm adding Luc in case he has any ideas of what the magical behavior might be. gcc does open "/" + "whatever between quotes" fstat so that "1.h" and "./1.h" differ https://github.com/gcc-mirror/gcc/blob/master/libcpp/files.c#L377 clang does better: "./" + "whatever between quotes" open fstat normalise pathname via readlink /proc/*/fd I think it is quite hard to break something with double inclusion without trying to actually break stuff. Macros has to be token for token identical or compiler warn. Types definition too. Function prototypes and so on. This is how I found half of the exception list. The "no leading ./ in includes is trivially enforced with checkpatch.pl or even grep! And it will optimise the build now that gcc behaviour has been uncovered. Include guards aren't without problems. We have at least 1 identical include guard in the tree for two completely unrelated headers (allmodconfig of some fringe arch found it) Nobody complains because only defconfigs are run apparently. Developer can typo it disabling double inclusion. #ifndef FOO_H #define FOO_h #endif I've seen a reference to a static checker checking for such stuff so this problem exists. Invisibly broken inlcude guards (see qla2xxx patch in the series). ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-02-28 19:34 ` Alexey Dobriyan @ 2021-02-28 20:00 ` Linus Torvalds [not found] ` <877dmo10m3.fsf@tromey.com> 2021-03-01 0:29 ` Luc Van Oostenryck 1 sibling, 1 reply; 12+ messages in thread From: Linus Torvalds @ 2021-02-28 20:00 UTC (permalink / raw) To: Alexey Dobriyan Cc: Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Sun, Feb 28, 2021 at 11:34 AM Alexey Dobriyan <adobriyan@gmail.com> wrote: > > > > > End result: #pragma is fundamentally less reliable than the > > traditional #ifdef guard. The #ifdef guard works fine even if you > > re-read the file for whatever reason, while #pragma relies on some > > kind of magical behavior. You continue to not even answer this very fundamental question. "#pragma once" doesn't seem to have a _single_ actual real advantage. Everybody already does the optimization of not even opening - much less reading and re-parsing - headers that have the traditional #ifdef guard. And even if you _don't_ do that optimization, the #ifdef guard fundmentally semantically guarantyees the right behavior. So the #ifdef guard is (a) standard (b) simple (c) reliable (d) traditional and you have yet to explain a _single_ advantage of "#pragma once". Why add this incredible churn that has no upside? So no. We're not using #pragma once unless y9ou can come up with some very strong argument for it And no, having to come up with a name for the #ifdef guard is not a strong argument. It's simply not that complicated. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <877dmo10m3.fsf@tromey.com>]
* Re: [PATCH 00/11] pragma once: treewide conversion [not found] ` <877dmo10m3.fsf@tromey.com> @ 2021-03-03 20:17 ` Linus Torvalds 2021-03-04 13:55 ` David Laight 0 siblings, 1 reply; 12+ messages in thread From: Linus Torvalds @ 2021-03-03 20:17 UTC (permalink / raw) To: Tom Tromey Cc: Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Wed, Mar 3, 2021 at 11:46 AM Tom Tromey <tom@tromey.com> wrote: > > It's also worth noting that in GCC it is slower than include guards. > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58770 > > It's just a bug, probably easy to fix. On the other hand, nobody has > ever bothered to do so. That bugzilla is actually worth reading, if only to explain how the include guard is more robust technology compared to #pragma once. The traditional include guarding with #ifndef/#define/#endif around the contents has the advantage that a compiler _can_ generate the obvious trivial optimizations of just memoizing that "oh, I've seen this filename already, and it had that include guard pattern, so I don't need to include it again". But, I hear you say "that's exactly what '#pragma once' does too!". No, it's not. There's actually two huge and very fundamental differences between '#pragma once' and the traditional include guard optimization: (a) the traditional include guard optimization HAS NO HIDDEN SEMANTIC MEANING. It's a pure optimization that doesn't actually change anything else. If you don't do the optimization, absolutely nothing changes. (b) the traditional include guard model allows for overriding and is simply more flexible And the GCC bugzilla talks about some of the issues with (a), and I already mentioned one similar issue with (a) wrt sparse: exactly what is it that "#pragma once" really protects? Is it the filename? Is it the _canonical_ filename? What about symbolic links or hardlinks? Is it the inode number? What about filesystems that don't really have those concepts? The above questions aren't some made-up example. They are literally FUNDAMENTAL DESIGN MISTAKES in "#pragma once". In contrast, include guards just work. You give the guard an explicit name, and that solves all the problems above, and allows for extra flexibility (ie the (b) issue: you can override things and include things twice if you know you're playing games, but you can also use the guard name to see "have I already included this file" for when you have possible nasty circular include file issues etc). So the traditional include guard model is simply technically the superior model. This is why I'm NAK'ing "#pragma once". It was never a good idea, and the alleged advantage ("faster builds by avoiding double includes") was always pure garbage because preprocessors could do the same optimization using the traditional include guards. In fact, because the traditional include guards have well-defined meaning and doesn't have any of the questions about what makes a file unique, and a missed optimization doesn't cause any semantic differences, a compiler has a much _easier_ time with that optimization than with the ostensibly simpler "#pragma once". Most #pragma things are not wonderful. But '#pragma once' is actively bad. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH 00/11] pragma once: treewide conversion 2021-03-03 20:17 ` Linus Torvalds @ 2021-03-04 13:55 ` David Laight 2021-03-04 20:16 ` Linus Torvalds 0 siblings, 1 reply; 12+ messages in thread From: David Laight @ 2021-03-04 13:55 UTC (permalink / raw) To: 'Linus Torvalds', Tom Tromey Cc: Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list > (a) the traditional include guard optimization HAS NO HIDDEN SEMANTIC > MEANING. It's a pure optimization that doesn't actually change > anything else. If you don't do the optimization, absolutely nothing > changes. And if the parser is well written the optimisation is probably irrelevant compared to the compile time. OTOH that probably requires using mmap(), memchr('\n') to look for line starts, a fast search for '[ ]*#' followed by else/endif and a final horrid backwards check for a continuation line. That optimisation will generally speed up header file processing. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-03-04 13:55 ` David Laight @ 2021-03-04 20:16 ` Linus Torvalds 2021-03-05 9:19 ` David Laight 2021-03-23 10:03 ` Pavel Machek 0 siblings, 2 replies; 12+ messages in thread From: Linus Torvalds @ 2021-03-04 20:16 UTC (permalink / raw) To: David Laight Cc: Tom Tromey, Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Thu, Mar 4, 2021 at 5:55 AM David Laight <David.Laight@aculab.com> wrote: > > > (a) the traditional include guard optimization HAS NO HIDDEN SEMANTIC > > MEANING. It's a pure optimization that doesn't actually change > > anything else. If you don't do the optimization, absolutely nothing > > changes. > > And if the parser is well written the optimisation is probably > irrelevant compared to the compile time. That's actually surprisingly not even remotely true. People always think that the optimization phases of a compiler are the expensive ones. And yes, there are certain optimizations that can be *really* expensive, and people just don't even do them because they are _so_ expensive and are exponential in time. And yes, there can be some patterns that expose bad scaling in some compiler algorithms, and histyorically that has often been seen when people use generators to automatically generate huge functions (or huge initializers), and then the compiler has some O(n**3) thing in it that is entirely unnoticeable for normal code written by a human, but means that a million-entry initializer takes five hours to compile. But in reality, on very real normal code, the *front end* of the compiler is often the most costly thing by far. Very much just the lexer and the simple parser. Things that are "simple" and people think are fast. But they are are often the slowest part in C style languages, because you have to lex and parse _everything_. You include maybe a dozen header files, maybe more. Those in turn often include another dozen support header files. You easily end up tokenizing and parsing hundreds of header files for even the simplest programs - and 99,.9% of that isn't ever *used*, and never actually generates any code that needs to be optimized. Think of all the complex macros and functions and type definitions you get when you include something basic like <stdio.h>. Trust me, it's a _lot_ of small details that get tokenixed, parsed and memoized. And then all you do is a 'printf("Hello world");' and the amount of actual code generation and optimization by the back-end is basically zero. And C++ is about an order of magnitude worse, because you really take this whole approach and turn it up to 11 with templates, namespaces, STL, and a lot of all that infrastructure that is there for all the possible cases, but that most files that include it only use a small tiny portion of. So in C-style (and particularly C++) languages, reading header files, tokenizing them and parsing them can _easily_ be the bulk of your compile time. Absolutely every single serious C/C++ compiler integrates tbe preprocessor _into_ the compiler, because the traditional model of having a separate "cpp" phase actually made the tokenization problem happen _twice_: once by the pre-processor, and then a second time by the compiler. Integrating the two phases, so that you can use just one tokenizer, and one single set of identifiers, actually speeds up compile speed _enormously_. Yes, yes, tokenization and parsing really is the simple part of a compiler. Good register allocation is _hard_. SSA makes a lot of the basic optimizations actually fairly straightforward and simple, but more complex transformations (loop invariant stuff, vectorization, various things like that) are really much much much more complex than the simple front-end. But that simple front end is the thing that touches absolutely _everything_, whether it actually generates code or not. And yes, this is mainly a C-style language problem. If you have hardcoded modules approach and not the "include files that describe all the different interfaces", you don't end up in that situation where you spend a lot of time parsign the possible interfaces over and over again. And C++ really is hugely worse, and takes this issue to another level. You can have simple single C++ files that end up basically having to parse hundreds of thousands of lines of fairly complex code, because they use several complex libraries, and that's how the library header files are set up,m with multiple levels (ie the GUI header files depend on, and include the lower-level object header files, which in turn depend on "simple" core libraries like STL and Boost. This is why pretty much every compiler out there does that include file header guard optimization. Because avoiding having to read and parse a file multiple times really does show up as a big big win. Even when it's all hidden behind the #ifndef/#define/#endif guarding logic, the cost of reading the file and lexing and parsing it enough to _see_ those guards is not cheap. Doing it once is required and important, but then you memoize the fact that "oh, all the stuff I needed to parse was behind this macro test, so next time I see this file, if that macro is set, I can just ignore it". So it is actually a very important optimization. It's just that the optimization is better done with that explicit guard memoization than it is with '#pragma once' Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH 00/11] pragma once: treewide conversion 2021-03-04 20:16 ` Linus Torvalds @ 2021-03-05 9:19 ` David Laight 2021-03-05 21:23 ` Linus Torvalds 2021-03-23 10:03 ` Pavel Machek 1 sibling, 1 reply; 12+ messages in thread From: David Laight @ 2021-03-05 9:19 UTC (permalink / raw) To: 'Linus Torvalds' Cc: Tom Tromey, Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list From: Linus Torvalds > Sent: 04 March 2021 20:16 > > On Thu, Mar 4, 2021 at 5:55 AM David Laight <David.Laight@aculab.com> wrote: > > > > > (a) the traditional include guard optimization HAS NO HIDDEN SEMANTIC > > > MEANING. It's a pure optimization that doesn't actually change > > > anything else. If you don't do the optimization, absolutely nothing > > > changes. > > > > And if the parser is well written the optimisation is probably > > irrelevant compared to the compile time. > > That's actually surprisingly not even remotely true. The point is that you can skip the unwanted parts of #if without having to parse the file at all. You just need to detect the line breaks. So yes, you need to read the file and look at every byte. But you don't need to even start tokenising it. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-03-05 9:19 ` David Laight @ 2021-03-05 21:23 ` Linus Torvalds 2021-03-06 13:07 ` Miguel Ojeda 0 siblings, 1 reply; 12+ messages in thread From: Linus Torvalds @ 2021-03-05 21:23 UTC (permalink / raw) To: David Laight Cc: Tom Tromey, Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Fri, Mar 5, 2021 at 1:19 AM David Laight <David.Laight@aculab.com> wrote: > > The point is that you can skip the unwanted parts of > #if without having to parse the file at all. > You just need to detect the line breaks. That's not actually true AT ALL. You still need to at the very least parse the preprocessor tokens, looking for things like #if, #else, and #endif. Because those can - and do - nest inside the whole thing, so you're not even looking for the final #endif, you have to be aware that there might be new #if statements that means that now you now have to increment the nesting count for the endif. And to do even just *THAT*, you need to do all the comment parsing, and all the string parsing, because a #endif means something entirely different if there was a "/*" or a string on a previous line that hasn't been terminated yet (yes, unterminated strings are bad practice, but ..). And regardless of even _those_ issues, you still should do all the other syntactic tokenization stuff (ie all the quoting, the the character handling: 'a' is a valid C token, but if you see the string "it's" outside of a comment, that's a syntax error even if it's inside a disabled region. IOW, this is an incorrect file: #if 0 it's a bug to do this, and the compiler should scream #endif because it's simply not a valid token sequence. The fact that it's inside a "#if 0" region doesn't change that fact at all. So you did need to do all the tokenization logic. The same goes for all the wide string stuff, the tri-graph horrors, etc etc. End result: you need to still do basically all of the basic lexing, and while you can then usually quickly throw the result mostly away (and you could possibly use a simplified lexer _because_ you throw it away), you actually didn't really win much. Doing a specialized lexer just for the disabled regions is probably simply a bad idea: the fact that you need to still do all the #if nesting etc checking means that you still do need to do a modicum of tokenization etc. Really: the whole "trivial" front-end parsing phase of C - and particularly C++ - is a huge huge deal. It's going to show in the profiles of the compiler quite decisively, unless you have a compiler that then spends absolutely insane time on optimization and tries to do things that basically no sane compiler does (because developers wouldn't put up with the time sink). So yes, I've even used things like super-optimizers that chew on small pieces of code for _days_ because they have insane exponential costs etc. I've never done it seriously, because it really isn't realistic, but it can be a fun exercise to try. Outside of those kinds of super-optimizers, lexing and parsing is a big big deal. (And again - this is very much language-specific. The C/C++ model of header files is very very flexible, and has a lot of conveniences, but it's also a big part of why the front end is such a big deal. Other language models have other trade-offs). Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-03-05 21:23 ` Linus Torvalds @ 2021-03-06 13:07 ` Miguel Ojeda 2021-03-06 21:33 ` Linus Torvalds 0 siblings, 1 reply; 12+ messages in thread From: Miguel Ojeda @ 2021-03-06 13:07 UTC (permalink / raw) To: Linus Torvalds Cc: David Laight, Tom Tromey, Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Fri, Mar 5, 2021 at 10:25 PM Linus Torvalds <torvalds@linux-foundation.org> wrote: > > And regardless of even _those_ issues, you still should do all the > other syntactic tokenization stuff (ie all the quoting, the the > character handling: 'a' is a valid C token, but if you see the string > "it's" outside of a comment, that's a syntax error even if it's inside > a disabled region. IOW, this is an incorrect file: > > #if 0 > it's a bug to do this, and the compiler should scream > #endif > > because it's simply not a valid token sequence. The fact that it's > inside a "#if 0" region doesn't change that fact at all. So you did > need to do all the tokenization logic. Compilers don't scream that much, only GCC seems to give a warning. I assume it is because it is just undefined rather than a required error/diagnostic, i.e. the "If a ’ or a " character matches the last category, the behavior is undefined." in 6.4. Concerning #pragma once: I actually would like to have a standard #once directive if what is a "seen file" could be defined a bit more precisely. Even if just says it creates a guard with something similar to the result of `__FILE__` would be good enough for many projects out there, and one can still use guards when flexibility is needed and/or corner cases are expected (which, if detected, the compiler could also warn about). Cheers, Miguel ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-03-06 13:07 ` Miguel Ojeda @ 2021-03-06 21:33 ` Linus Torvalds 0 siblings, 0 replies; 12+ messages in thread From: Linus Torvalds @ 2021-03-06 21:33 UTC (permalink / raw) To: Miguel Ojeda Cc: David Laight, Tom Tromey, Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Sat, Mar 6, 2021 at 5:07 AM Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: > > Concerning #pragma once: I actually would like to have a standard > #once directive if what is a "seen file" could be defined a bit more > precisely. I think it would be ok if you had something like #pragma once IDTOKEN which would basically act *exactly* as a "#ifndef IDTOKEN/#define IDTOKEN" with that final #endif at the end of the file. But even then it should have the rule that it must be the very first thing in the file (ignoring whitespace and pure comments). Then it would literally be just a cleaner and simpler version of the guarding logic, with none of the semantic confusion that #pragma once now has. Because I cannot see any other way to define what "seen file" really means. There's no sane "implied IDTOKEN" that I can see. It can't really be the pathname, because pathnames are actually really hard to turn into canonical form in user space thanks to things like symlinks. It can't be st_ino/st_dev stat information, because the C preprocessor isn't a "POSIX only" thing. It could be a "Ok, #pragma once only works if you don't have multiple ways to reach the same file, and you never have ambiguous include paths". But that's actually not all that unusual in real projects: you often have fairly complex include paths, you have C files that include the header in the same directory with just "filename.h", but it _could_ get included indirectly from _another_ header that gave a pathname relative to the project root, etc etc. This is not unrelated to another complete morass of horrible problems: precompiled header files. That feature had exactly the same reason for it as "#pragma once" - slow build speeds due to the cost of parsing complex header file hierarchies. And I guarantee that multiple compiler teams spent hundreds of person-years of effort on trying to make it work. And several compilers do support the notion. And they ALL have big warnings about when you should enable it, and when you shouldn't, and what things don't work if you use them, and about how it can cause really really subtle problems. Because it turns out that precompiled header files are a major pain and a major mistake. Some projects still use them, because they can be such a huge timesaver (again: particularly C++ projects that just have a "include everything" approach to headers because trying to separate things out is too hard). But they all come with huge warnings about how they break the actual real semantics of a compiler, and if you do _anything_ to change the build ("hey, I'd like to use a different compiler option"), things may or may not work. Linus ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-03-04 20:16 ` Linus Torvalds 2021-03-05 9:19 ` David Laight @ 2021-03-23 10:03 ` Pavel Machek 1 sibling, 0 replies; 12+ messages in thread From: Pavel Machek @ 2021-03-23 10:03 UTC (permalink / raw) To: Linus Torvalds Cc: David Laight, Tom Tromey, Alexey Dobriyan, Luc Van Oostenryck, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list [-- Attachment #1: Type: text/plain, Size: 1126 bytes --] Hi! > > > (a) the traditional include guard optimization HAS NO HIDDEN SEMANTIC > > > MEANING. It's a pure optimization that doesn't actually change > > > anything else. If you don't do the optimization, absolutely nothing > > > changes. > > > > And if the parser is well written the optimisation is probably > > irrelevant compared to the compile time. > > That's actually surprisingly not even remotely true. > > People always think that the optimization phases of a compiler are the > expensive ones. And yes, there are certain optimizations that can be > *really* expensive, and people just don't even do them because they > are _so_ expensive and are exponential in time. Well, linux kernel can be compiled in two _seconds_ if you take compiler optimized for fast parsing... and quick code generation. See "SUSE Labs Conference 2018 - Compiling the Linux kernel in a second (give or take)" on youtube. So yes, gcc's frontend may be slow, but that does not mean job can not be done quickly by suitable compiler. Best regards, Pavel -- http://www.livejournal.com/~pavelmachek [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 181 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 00/11] pragma once: treewide conversion 2021-02-28 19:34 ` Alexey Dobriyan 2021-02-28 20:00 ` Linus Torvalds @ 2021-03-01 0:29 ` Luc Van Oostenryck 1 sibling, 0 replies; 12+ messages in thread From: Luc Van Oostenryck @ 2021-03-01 0:29 UTC (permalink / raw) To: Alexey Dobriyan Cc: Linus Torvalds, Linux Kernel Mailing List, Andrew Morton, Sparse Mailing-list On Sun, Feb 28, 2021 at 10:34:46PM +0300, Alexey Dobriyan wrote: > > gcc does > > open "/" + "whatever between quotes" > fstat > > so that "1.h" and "./1.h" differ When I try the following with GCC 10.2: $ cat header.h #pragma once #include "./header.h" .. plenty of stuff .. $ strace -f gcc -E header.h I see that the file is opened 4 times (3 times with the name "header.h" and once with "./header.h"). Each of these open is followed by a fstat(). More annoyingly, the file is also read 4 times (3 times entirely and once only the fist 4096 bytes). When the equivalent is done with an include guard instead, the file is only read twice (once with each names) and read twice (entirely). -- Luc ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-03-23 10:04 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <YDvLYzsGu+l1pQ2y@localhost.localdomain>
2021-02-28 17:46 ` [PATCH 00/11] pragma once: treewide conversion Linus Torvalds
2021-02-28 19:34 ` Alexey Dobriyan
2021-02-28 20:00 ` Linus Torvalds
[not found] ` <877dmo10m3.fsf@tromey.com>
2021-03-03 20:17 ` Linus Torvalds
2021-03-04 13:55 ` David Laight
2021-03-04 20:16 ` Linus Torvalds
2021-03-05 9:19 ` David Laight
2021-03-05 21:23 ` Linus Torvalds
2021-03-06 13:07 ` Miguel Ojeda
2021-03-06 21:33 ` Linus Torvalds
2021-03-23 10:03 ` Pavel Machek
2021-03-01 0:29 ` Luc Van Oostenryck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).