LWN: Comments on "Signed overflow optimization hazards in the kernel" https://lwn.net/Articles/511259/ This is a special feed containing comments posted to the individual LWN article titled "Signed overflow optimization hazards in the kernel". en-us Fri, 10 Oct 2025 19:32:52 +0000 Fri, 10 Oct 2025 19:32:52 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net About undefined behaviour... https://lwn.net/Articles/513139/ https://lwn.net/Articles/513139/ pwood John Regehr's blog posts on undefined behaviour are always worth reading (his research group developed the IOC patch to clang that a couple of people have linked to above.) In the context of integer behaviour in C he has a quiz <a rel="nofollow" href="http://blog.regehr.org/archives/721">here</a> which is worth a look. I'm not sure that you ever want to rely on undefined behaviour as suggested in the article as it means that the execution of your program is undefined and can change at the compiler's will. That is very different from relying on implementation defined behaviour. Thu, 23 Aug 2012 16:03:43 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/513072/ https://lwn.net/Articles/513072/ georgm <div class="FormattedComment"> The question concerns signed values, where wraps are not common. Unsigned benefit is clear.<br> </div> Thu, 23 Aug 2012 10:28:10 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/513059/ https://lwn.net/Articles/513059/ georgm <div class="FormattedComment"> A question:<br> <p> What is the reason to write "if((a-b) &lt; 0) ..." instead of just "if(a&lt;b)"?<br> </div> Thu, 23 Aug 2012 09:54:33 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/513056/ https://lwn.net/Articles/513056/ reddit <div class="FormattedComment"> The sensible way to do this is (int)(a - b) &lt; 0 where a and b are unsigned.<br> <p> </div> Thu, 23 Aug 2012 09:47:27 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512878/ https://lwn.net/Articles/512878/ etienne <div class="FormattedComment"> Seems like -ftrapv can work, but it is far from just adding an "into" instruction after each signed "add" on ia32 - note that "into" has disappeared in amd64 instruction set.<br> <p> $ cat test.c <br> int a, b, c;<br> void main (void) {<br> c = a + b;<br> }<br> $ gcc -m32 -O2 -ftrapv test.c <br> $ objdump -d a.out <br> <p> a.out: file format elf32-i386<br> ....<br> 080483f0 &lt;main&gt;:<br> push %ebp<br> mov %esp,%ebp<br> and $0xfffffff0,%esp<br> sub $0x10,%esp<br> mov 0x804a01c,%eax<br> mov %eax,0x4(%esp)<br> mov 0x804a020,%eax<br> mov %eax,(%esp)<br> call 8048420 &lt;__addvsi3&gt;<br> mov %eax,0x804a024<br> leave <br> ret <br> ....<br> 08048420 &lt;__addvsi3&gt;:<br> push %ebp<br> mov %esp,%ebp<br> push %ebx<br> sub $0x4,%esp<br> mov 0xc(%ebp),%ecx<br> mov 0x8(%ebp),%edx<br> call 804845c &lt;__i686.get_pc_thunk.bx&gt;<br> add $0x1bc2,%ebx<br> test %ecx,%ecx<br> lea (%ecx,%edx,1),%eax<br> js 8048450 &lt;__addvsi3+0x30&gt;<br> cmp %edx,%eax<br> setl %dl<br> test %dl,%dl<br> jne 8048457 &lt;__addvsi3+0x37&gt;<br> add $0x4,%esp<br> pop %ebx<br> pop %ebp<br> ret <br> xchg %ax,%ax<br> cmp %edx,%eax<br> setg %dl<br> jmp 8048444 &lt;__addvsi3+0x24&gt;<br> call 80482fc &lt;abort@plt&gt;<br> <p> <p> Without ftrapv:<br> 080483c0 &lt;main&gt;:<br> mov 0x804a01c,%eax<br> add 0x804a018,%eax<br> push %ebp<br> mov %esp,%ebp<br> mov %eax,0x804a020<br> pop %ebp<br> ret <br> <p> </div> Wed, 22 Aug 2012 13:21:45 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512864/ https://lwn.net/Articles/512864/ jezuch <div class="FormattedComment"> <font class="QuotedText">&gt; A code using lots of non-restrict pointers will certainly be difficult to vectorize. Such code can sometimes be auto-parallelized but I don't believe gcc has that capability.</font><br> <p> It sorta-kinda does (-ftree-parallelize-loops) but I haven't tested it much. But I expect it to be even weaker than vectorization.<br> <p> <font class="QuotedText">&gt; gcc's vectorization is also pretty weak, though it is getting better. That may be part of what you're seeing.</font><br> <p> It may be that. Or it may be that most of the code in non-HPC world does not lend itself to vectorization easily. I actually don't know, I'm just an amateur and hobbyist :)<br> </div> Wed, 22 Aug 2012 10:39:16 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512857/ https://lwn.net/Articles/512857/ mpr22 <tt>-ftrapv</tt> is an architecture-independent compiler option to GCC. I don't know whether it works. Wed, 22 Aug 2012 08:51:38 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512702/ https://lwn.net/Articles/512702/ daglwn <div class="FormattedComment"> <font class="QuotedText">&gt; but then, HPC code relies more on optimization by hand and leaves little </font><br> <font class="QuotedText">&gt; to the compiler, as I understand it)</font><br> <p> Not true. The Intel compiler, for example, will vectorize its brains out automatically.<br> <p> A code using lots of non-restrict pointers will certainly be difficult to vectorize. Such code can sometimes be auto-parallelized but I don't believe gcc has that capability.<br> <p> gcc's vectorization is also pretty weak, though it is getting better. That may be part of what you're seeing.<br> <p> </div> Tue, 21 Aug 2012 14:30:00 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512634/ https://lwn.net/Articles/512634/ jezuch <div class="FormattedComment"> As someone who insists on rebuilding some of Debian's packages for my own machine (for fun and not for profit), I can tell that vectorization very rarely has any significant impact. Yes, it can provide a great boost in some synthetic benchmarks or maybe in HPC code (but then, HPC code relies more on optimization by hand and leaves little to the compiler, as I understand it), but very few loops in real-world code are well-formed enough to be suitable for auto-vectorization. I won't make your browser visibly faster :)<br> </div> Tue, 21 Aug 2012 07:58:41 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512494/ https://lwn.net/Articles/512494/ daglwn <div class="FormattedComment"> You don't believe vectorization can significantly speed up code?<br> </div> Mon, 20 Aug 2012 16:45:15 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512400/ https://lwn.net/Articles/512400/ etienne <div class="FormattedComment"> <font class="QuotedText">&gt; So it is not too early to start future-proofing the Linux kernel by removing its reliance on signed integer overflow!</font><br> <p> Would be nice to have a GCC option for ia32 so that any "add" used for signed arithmetic is followed with "into" (exception if overflow).<br> It will not slow too much the execution ("into" will not be predicted as a taken jump), and could help locate potential problems...<br> <p> </div> Mon, 20 Aug 2012 08:59:56 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512394/ https://lwn.net/Articles/512394/ jezuch <div class="FormattedComment"> <font class="QuotedText">&gt; The compiler wants to know it's safe to assume this loop goes around 16 times. That isn't true if "x + 16" could overflow.</font><br> <p> If you want to make it explicit, there's a flag for this in GCC: -funsafe-loop-optimizations (along with -Wunsafe-loop-optimizations if you want to know when it happens; it's a warning, though, so beware of build environments which insist on -Werror). AFACT there are two cases handled by this flag: assuming that the loop counter does not overflow, and assuming that the loop is not infinite. Don't know the exact implementation details, though.<br> </div> Mon, 20 Aug 2012 07:22:52 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512381/ https://lwn.net/Articles/512381/ PaulMcKenney <div class="FormattedComment"> No problem!<br> <p> I must admit that it would be nice if "(signed typeof(a))" and (unsigned typeof(b))" flipped the signedness of "a" and "b", but my version of gcc really doesn't like either variant. ;-)<br> </div> Mon, 20 Aug 2012 00:44:56 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512342/ https://lwn.net/Articles/512342/ baldrick <div class="FormattedComment"> By "signed" I meant "signed integer type of the same size" and by "unsigned" I meant "unsigned integer type of the same size". The "same size" means: the same number of bits as the original integer type, so in the case of example 2 this means "signed long long" and "unsigned long long". Sorry for not being clear.<br> </div> Sun, 19 Aug 2012 17:00:06 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512291/ https://lwn.net/Articles/512291/ giraffedata <blockquote> The result of ... converting an integer to a signed integer type when the value cannot be represented in an object of that type ... <p> For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; </blockquote> <p> I must be reading that wrongly, because that's not at all what GCC does. With -m32, int is a signed integer type of width 32. UINT_MAX reduced modulo 2^32 is UINT_MAX, which is not within the range of int. So this does not describe what (int)UINT_MAX does. <p> Rather, what GCC does appears to be the opposite of what the standard requires for conversion from negative number to unsigned integer (add UINT_MAX+1 until it fits): it subtracts UINT_MAX+1 until the value is within the range of int (in this case -1). Sat, 18 Aug 2012 23:58:03 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512287/ https://lwn.net/Articles/512287/ jzbiciak <div class="FormattedComment"> I see I missed ppisa's impressive macros upthread. Those certainly seem to take into account a range of integer types as well! <br> </div> Sat, 18 Aug 2012 23:04:44 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512285/ https://lwn.net/Articles/512285/ jzbiciak <P>Where I've heard it coming up is when you have code that effectively looks like this:</P> <PRE> for (i = x; i < x + 16; i++) { /* code that does not modify either x or i */ } </PRE> <P> The compiler wants to know it's safe to assume this loop goes around 16 times. That isn't true if "x + 16" could overflow. </P> Sat, 18 Aug 2012 22:56:51 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512283/ https://lwn.net/Articles/512283/ jzbiciak <P>This seems like it argues for a macro to hide the ugliness. Name it something obvious such as "before()". It makes the intent obvious and ensures the ugly math is done correctly. Something like:</P> <PRE> /* return true if timestamp 'a' is earlier than timestamp 'b' */ #define before(a,b) (ULONG_MAX/2 &gt; ((unsigned long)(a) - (unsigned long)(b))) </PRE> <P>Or is this just an invitation to more problems?</P> Sat, 18 Aug 2012 22:51:33 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512281/ https://lwn.net/Articles/512281/ ppisa <div class="FormattedComment"> Hmm, cast to unsigned used to work even for signed types and in practice works still. a+=20 is translated into single add instruction on all targets I know. The other reason for casting is, that sometimes you can strore in object only shorter part of time stamp or generation counter, if you know, that live period is small enough or if you only check for change. Casting both to smaller of the two makes subtraction possibly cheaper, the result has to be casted to smaller one anyway.<br> <p> But main reason for casting to ensure thing works on existing code<br> with signed types.<br> <p> Best wishes,<br> <p> Pavel<br> <p> </div> Sat, 18 Aug 2012 22:34:04 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512264/ https://lwn.net/Articles/512264/ PaulMcKenney <div class="FormattedComment"> True enough!<br> <p> However, the Linux kernel's code can be legitimately used in any GPLv2 project, including those that might run on systems with non-twos-complement signed integer arithmetic. This sharing of code among compatibly licensed projects is a very good thing, in my view.<br> <p> Which means in this case, where there is a solution that meets the C standard, and which loses nothing by doing so (at least on x86 and Power), it only makes sense to use that C-standard solution.<br> <p> </div> Sat, 18 Aug 2012 19:48:57 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512260/ https://lwn.net/Articles/512260/ PaulMcKenney <div class="FormattedComment"> Cool, that was the sort of thing I was thinking of with my "sizeof()" earlier, though I still do feel more comfortable with using the constants than relying on casting.<br> <p> But why the casts to unsigned integral types? I would instead have expected a requirement that the caller's cyclic arithmetic be carried out in unsigned integers, so that the casts were unnecessary.<br> </div> Sat, 18 Aug 2012 19:02:34 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512258/ https://lwn.net/Articles/512258/ PaulMcKenney <div class="FormattedComment"> One objection was that there really are still non-twos-complement machines in common use. As was noted by the comment to this article discussing saturating adders, where 32767+1==32767. But this would be addressed by "implementation defined" rather than "undefined".<br> <p> Another objection was that there are systems still in common use that trap on signed integer overflow. If the C standard required wrapping, compilers for such systems would require special edge-case checks on pretty much any signed integer operation.<br> <p> And there was of course also the objection that signed integer overflow always has been undefined. ;-)<br> </div> Sat, 18 Aug 2012 18:19:43 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512256/ https://lwn.net/Articles/512256/ ppisa <div class="FormattedComment"> I hope that behavior of unsigned to signed conversion stays defined (at least for GCC and GCC replacement compilers - LLVM, Intel atc.). GCC defines behavior in current manual version<br> <p> <a href="http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html">http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation...</a><br> <p> I use ((signed type)((unsigned type)a - (unsigned type)b) &gt; 0) often in our embedded code and in the fact I am probably author/coauthor of that MX1 example - if that line was not not rewritten by somebody.<br> <p> Paul's example behavior is correct according to my knowledge (unsigned) is equivalent to (unsigned int) ie on 32 bit target 32 bit subtraction is evaluated and then sign is extended to 64 bits when conversion to (signed it) and then 64 bit signed type is required.<br> <p> What is common trap is that plain<br> <p> (unsigned type) a - (unsigned type) b <br> <p> is not considered (type) nor (signed type). It is signed but interpreted as so big signed to hold additional bit if it is compared with zero. So additional cast to signed type same or smaller than both inputs (a and b) has to be used.<br> <p> I use next mechanism to allow cyclic comparison between different<br> hardware, position, time, state generation counters etc in our code.<br> <p> <a href="http://ulan.git.sourceforge.net/git/gitweb.cgi?p=ulan/ulut;a=blob;f=ulut/ul_utdefs.h;#l42">http://ulan.git.sourceforge.net/git/gitweb.cgi?p=ulan/ulut;...</a><br> <p> Library is licensed GPL, LGPL, MPL, but code fragment can be taken as public domain, if it helps somebody.<br> <p> #ifndef ul_cyclic_gt<br> #define ul_cyclic_gt(x,y) \<br> ((sizeof(x)&gt;=sizeof(long long))&amp;&amp;(sizeof(y)&gt;=sizeof(long long))? \<br> (long long)((unsigned long long)(x)-(unsigned long long)(y))&gt;0: \<br> (sizeof(x)&gt;=sizeof(long))&amp;&amp;(sizeof(y)&gt;=sizeof(long))? \<br> (long)((unsigned long)(x)-(unsigned long)(y))&gt;0: \<br> (sizeof(x)&gt;=sizeof(int))&amp;&amp;(sizeof(y)&gt;=sizeof(int))? \<br> (int)((unsigned int)(x)-(unsigned int)(y))&gt;0: \<br> (sizeof(x)&gt;=sizeof(short))&amp;&amp;(sizeof(y)&gt;=sizeof(short))? \<br> (short)((unsigned short)(x)-(unsigned short)(y))&gt;0: \<br> (signed char)((unsigned char)(x)-(unsigned char)(y))&gt;0 \<br> )<br> #endif /*ul_cyclic_gt*/<br> <p> #ifndef ul_cyclic_ge<br> #define ul_cyclic_ge(x,y) \<br> ((sizeof(x)&gt;=sizeof(long long))&amp;&amp;(sizeof(y)&gt;=sizeof(long long))? \<br> (long long)((unsigned long long)(x)-(unsigned long long)(y))&gt;=0: \<br> (sizeof(x)&gt;=sizeof(long))&amp;&amp;(sizeof(y)&gt;=sizeof(long))? \<br> (long)((unsigned long)(x)-(unsigned long)(y))&gt;=0: \<br> (sizeof(x)&gt;=sizeof(int))&amp;&amp;(sizeof(y)&gt;=sizeof(int))? \<br> (int)((unsigned int)(x)-(unsigned int)(y))&gt;=0: \<br> (sizeof(x)&gt;=sizeof(short))&amp;&amp;(sizeof(y)&gt;=sizeof(short))? \<br> (short)((unsigned short)(x)-(unsigned short)(y))&gt;=0: \<br> (signed char)((unsigned char)(x)-(unsigned char)(y))&gt;=0 \<br> )<br> #endif /*ul_cyclic_ge*/<br> <p> Please, if you know about some target, compiler or intention to break assumption (at least hopefully current GCC version guarantee) that unsigned to signed conversion reinterprets MSB as a sign. As for correctness of the code, there could be problem if target specifies some basic arithmetic type with some bits unused. It short 16 bit but stored in 32 bit entity. But none of our targets has that problem.<br> <p> Code is used in many targets, some of safety grade class applications so notice of possible (even future) breakage is critical for me and users.<br> </div> Sat, 18 Aug 2012 18:07:14 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512248/ https://lwn.net/Articles/512248/ ppisa <div class="FormattedComment"> It would worth to compile and run kernel for MIPS with GCC option -ftrapv, if its actual GCC implementation is not broken in the current GCC version. MIPS has wrapping (addu, addiu) and signed overflow generation (add, addi) variants of the instructions. But wrapping variants are used even for signed types to keep compatibility with usual C code writeup manners.<br> </div> Sat, 18 Aug 2012 17:20:01 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512178/ https://lwn.net/Articles/512178/ pdewacht But given that Linux is only intended to be compiled by gcc, we can rely on its implementation-defined behavior: <blockquote> The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 6.3.1.3). <blockquote> For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised. </blockquote> </blockquote> <p>(and I don't see how any compiler for a two's complement computer could define different behavior.) Fri, 17 Aug 2012 21:57:31 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512147/ https://lwn.net/Articles/512147/ gmaxwell <div class="FormattedComment"> JM, the clang integer overflow checker we've used on our projects isn't part of clang proper, it's a (very useful) patch: <a href="http://embed.cs.utah.edu/ioc/">http://embed.cs.utah.edu/ioc/</a><br> <p> Beyond the optimization possibilities, the existence of tools like this is also a reason for keeping the undefined behavior, e.g. continue using signed values for counters that don't need the extra unsigned range: Most of the time overflow that you didn't expect (and thus couldn't wrap in a casting macro) is a sign of a logic error. By keeping it invalid you gain the possibility of dynamic instrumentation to catch those errors.<br> <p> (Though I don't know if anyone has managed to get tools like this working with the kernel yet!)<br> </div> Fri, 17 Aug 2012 19:16:59 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512144/ https://lwn.net/Articles/512144/ iabervon <pre> int find(char *s, char c, int lim) { for (int i = 0; i != lim &amp;&amp; s[i]; i++) if (s[i] == c) return i; return -1; } int main() { find("foo", 'o', 1); find("foo", 'o', -1); } </pre> <p>If the compiler inlines the second call, it can drop the "i != lim" test by assuming that overflow is impossible.</p> Fri, 17 Aug 2012 19:09:44 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/512111/ https://lwn.net/Articles/512111/ josh <div class="FormattedComment"> What did the arguments against it say, other than "that would remove compiler optimization possibilities"?<br> </div> Fri, 17 Aug 2012 16:07:24 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511985/ https://lwn.net/Articles/511985/ wahern <p> You have that in reverse. Conversion to unsigned is always well defined. Conversion to signed where the value cannot be represented is implemented-defined: </p> <blockquote> C99 6.3.1.3 Signed and unsigned integers <ol> <li> When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.</li> <li> Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49) </li> <li> Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.</li> </ol> </blockquote> Fri, 17 Aug 2012 06:45:04 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511976/ https://lwn.net/Articles/511976/ jimparis <blockquote> Hmmm... If I compile the following with gcc 4.6.1 with -O2: <pre> unsigned long long signed_cast(unsigned long long a, unsigned long long b) { return (signed)((unsigned)a - (unsigned)b); } </pre> ...<br> This is a 32-bit subtraction on 64-bit quantities. </blockquote> Well, yeah, that's because "(signed)" is casting 32-bit when compiled with -m32. I might be misunderstanding your issue here but it seems you wanted: <pre> unsigned long long signed_cast(unsigned long long a, unsigned long long b) { return (signed long long)((unsigned long long)a - (unsigned long long)b); } </pre> Fri, 17 Aug 2012 05:05:29 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511961/ https://lwn.net/Articles/511961/ PaulMcKenney <div class="FormattedComment"> Though I could make the macros type-generic by (ab)using sizeof(). Not sure it is worth it, though.<br> </div> Fri, 17 Aug 2012 02:20:46 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511931/ https://lwn.net/Articles/511931/ mmorrow Here's my favorite undefined-signed-overflow example: <pre> int f(int x){while(x &lt; x + 1) x += 1; return x;} </pre> gives: <pre> f: .L2: jmp .L2 .ident "GCC: (GNU) 4.8.0 20120408 (experimental)" </pre> Thu, 16 Aug 2012 23:34:15 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511924/ https://lwn.net/Articles/511924/ klossner <div class="FormattedComment"> » I suspect that the dominance of twos complement was not due to ease of use, but rather due to the fact that it allows a single hardware adder to perform both signed and unsigned computations. «<br> <p> My recollection of those days is that the greater motivation was to get away from systems with two different representations of zero. There were ancient Fortran codes run on CDC mainframes that had to test results for both postive and negative zero.<br> <p> </div> Thu, 16 Aug 2012 23:19:28 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511919/ https://lwn.net/Articles/511919/ klossner <div class="FormattedComment"> Sure, a good programmer should have done that. But the C compiler is often presented with automatically-generated code that has never been seen by human eyes, for example after several levels of macro expansion have done their work. Folding out the resulting dead code is often a substantial win.<br> <p> </div> Thu, 16 Aug 2012 23:10:23 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511910/ https://lwn.net/Articles/511910/ cmccabe <div class="FormattedComment"> I still feel a little confused by this. If you have a loop like this:<br> <p> <font class="QuotedText">&gt; int i;</font><br> <font class="QuotedText">&gt; for (i = 0; i &lt; 5; i++) {</font><br> <font class="QuotedText">&gt; [expression not involving i]</font><br> <font class="QuotedText">&gt; }</font><br> <p> I don't see how -fnowrapv will prevent you from unrolling the loop. You know that starting at 0 and adding 1 will get you to 5 before it will get you to overflow.<br> <p> I guess you could come up with a scenario where you don't know the initial value of the counter, but you do have a constant positive increment and a set upper limit. So something like this:<br> <p> <font class="QuotedText">&gt; for (i = function_from_another_translation_unit(); i &lt; 5; i++) {</font><br> <font class="QuotedText">&gt; [expression not involving i]</font><br> <font class="QuotedText">&gt; }</font><br> <p> Even in this case, though, you still know that either you'll run the loop no times, or there will be no overflow. You have to get to something like this to start seeing a problem:<br> <p> <font class="QuotedText">&gt; for (i = function_from_another_translation_unit(); i &lt; 0x7ffffffe; i += 2) {</font><br> <font class="QuotedText">&gt; [expression not involving i]</font><br> <font class="QuotedText">&gt; }</font><br> <p> This is pretty exotic scenario, though. If i starts off as 0x7fffffff and -fwrapv is enabled, the loop will never terminate, whereas with -fnowrapv it's undefined. To me, this feels like buggy code in the first place, so I don't really care if it's not optimized.<br> <p> Am I missing something here? Is there a good example of a real-world scenario where -fnowrapv helps well-written code?<br> </div> Thu, 16 Aug 2012 23:10:05 +0000 About undefined behaviour... https://lwn.net/Articles/511907/ https://lwn.net/Articles/511907/ PaulMcKenney <div class="FormattedComment"> Thank you, highly recommended!<br> </div> Thu, 16 Aug 2012 22:52:19 +0000 About undefined behaviour... https://lwn.net/Articles/511905/ https://lwn.net/Articles/511905/ hummassa <div class="FormattedComment"> Great links! Thank you very much!!!<br> </div> Thu, 16 Aug 2012 22:50:11 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511904/ https://lwn.net/Articles/511904/ PaulMcKenney <div class="FormattedComment"> Whew! It goes back to being non-urgent. ;-)<br> </div> Thu, 16 Aug 2012 22:49:32 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511903/ https://lwn.net/Articles/511903/ PaulMcKenney <div class="FormattedComment"> Understood. And when it was suggested within the C11 Standards committee that signed-integer overflow be given twos-complement semantics, the discussion was both emphatic and short. ;-)<br> </div> Thu, 16 Aug 2012 22:48:42 +0000 Signed overflow optimization hazards in the kernel https://lwn.net/Articles/511887/ https://lwn.net/Articles/511887/ cmccabe <div class="FormattedComment"> I really doubt that using -fnowrapv or the equivalent provides much of a performance boost in practice.<br> <p> Most of the examples I've seen have been of the form "aha! I can (incorrectly) assume that this if statement that the programmer put here is a no-op!" In all of these cases I've seen, the "optimization" is something that a good programmer could have and probably would have done manually anyway.<br> <p> I'd really like to see some real-world performance numbers about the effects of this optimization. Based on everything I've seen so far, this is a case where compiler writers got so carried away considering what they _could_ do, that they didn't stop to think if they _should_.<br> </div> Thu, 16 Aug 2012 22:47:53 +0000