Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
A C compiler, upon seeing d[++k], is permitted to assume that the incremented value of k is within the array bounds, since otherwise undefined behavior occurs. For the code here, GCC can infer that k is in the range 0..15. A bit later, when GCC sees k<16, it says to itself: 'Aha-- that expression is always true, so we have an infinite loop.'"
Posted Mar 23, 2013 13:48 UTC (Sat)
by Thue (guest, #14277)
[Link] (11 responses)
My impression is that GCC is doing a poor job of that; as noted in the article, it doesn't give a warning with -O2. GCC should exist to help the programmer, not to follow the spec at any cost, and ignore the programmer's needs. If GCC can't give proper warnings, then they should turn off the optimizations, IMO.
Posted Mar 23, 2013 15:22 UTC (Sat)
by ssam (guest, #46587)
[Link] (8 responses)
Posted Mar 23, 2013 16:16 UTC (Sat)
by HelloWorld (guest, #56129)
[Link] (6 responses)
Posted Mar 23, 2013 16:38 UTC (Sat)
by ssam (guest, #46587)
[Link] (2 responses)
I sometimes use code like:
int a[] = {6,8,3};
maybe because i want to check if a particle in a simulation is in one of my regions of interest. I may often modify a, and then recompile the code (in my work its not unusual to recompile code before each run). Sometimes a will just be {}, so i would like the compiler remove the loop.
Posted Mar 23, 2013 17:32 UTC (Sat)
by apoelstra (subscriber, #75205)
[Link] (1 responses)
I do this too, and I also compile with -Werror, but IMHO I'd rather have the warning than not. A simple (ugly) solution is to couch your loop in #ifdef's, and just flip a preprocessor variable.
Posted Mar 26, 2013 5:31 UTC (Tue)
by bronson (subscriber, #4806)
[Link]
Compiler warnings would too... If the compiler emits 22 "might be true" warnings, and 21 of them are spurious, what are the chances I'll catch the meaningful one? Knowing me, probably next to nil.
Posted Mar 23, 2013 18:24 UTC (Sat)
by smurf (subscriber, #17840)
[Link] (2 responses)
The problem is that this kind of thing comes up in macros all the time, esp. in hand-optimized libraries. "(Foo < 8) ? _handcoded_special_function() : _generic_function()" is a common-enough idiom. You cannot just warn about that.
Posted Mar 23, 2013 18:52 UTC (Sat)
by mansr (guest, #85328)
[Link]
Posted Mar 25, 2013 13:37 UTC (Mon)
by dlthomas (guest, #89935)
[Link]
Posted Mar 23, 2013 18:27 UTC (Sat)
by mjw (subscriber, #16740)
[Link]
Posted Mar 23, 2013 15:31 UTC (Sat)
by proski (subscriber, #104)
[Link] (1 responses)
Posted Mar 25, 2013 13:41 UTC (Mon)
by dlthomas (guest, #89935)
[Link]
int d[16];
d[k] = 10; /*A*/
if(/*B*/ k < 16) {
The idea is that when it hits A, if that expression would be false, behavior is already undefined because of what happened at B, so let's optimize for the case that didn't segfault (or corrupt data).
Posted Mar 23, 2013 14:13 UTC (Sat)
by juzzor (guest, #89840)
[Link] (7 responses)
Posted Mar 23, 2013 14:37 UTC (Sat)
by felixfix (subscriber, #242)
[Link] (6 responses)
Posted Mar 23, 2013 14:46 UTC (Sat)
by juzzor (guest, #89840)
[Link] (5 responses)
Posted Mar 23, 2013 15:25 UTC (Sat)
by proski (subscriber, #104)
[Link] (4 responses)
Posted Mar 23, 2013 15:46 UTC (Sat)
by khim (subscriber, #9252)
[Link] (2 responses)
It's easy to do, but you'll be surprised to see just how many such warnings typical code will generate. There are lots of idioms explicitly built around them (think "do { ... } while (TRUE)" defines and recall that TRUE is often is defined "(!FALSE)"). It's trivial to produce bazillion "comparison is always true" warnings or not produce anything at all. To produce meaningful number of warnings… that's different story… it's really hard.
Posted Mar 23, 2013 17:54 UTC (Sat)
by HelloWorld (guest, #56129)
[Link] (1 responses)
Posted Mar 26, 2013 8:26 UTC (Tue)
by mlopezibanez (guest, #66088)
[Link]
Regardless, there are very few GCC developers, so if you think you could do something better, you should give it a try. Sometimes you realize how difficult your obvious thing turns out to be, and other times you realize that it was indeed obvious but nobody had time to do it before. I can tell you from personal experience that there is a lot of the latter in GCC.
Posted Mar 23, 2013 15:49 UTC (Sat)
by juzzor (guest, #89840)
[Link]
http://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=228bf2b8...
Posted Mar 23, 2013 15:51 UTC (Sat)
by mlopezibanez (guest, #66088)
[Link] (3 responses)
It is more like: "k is in the range 0..15, so this test I just found for k<16 is redundant, so change it to always true." It doesn't know that the test is used for exiting the loop. Well, in this simple case it does, and it should warn with -Waggressive-loop-optimizations. In other cases, the optimization can be disabled with -fno-aggressive-loop-optimizations.
Posted Mar 25, 2013 20:37 UTC (Mon)
by xorbe (guest, #3165)
[Link] (2 responses)
Therefore, it also can't be an infinite loop.
> It doesn't know that the test is used for exiting the loop.
What nonsense is this. "k<16" is the exact test in the for loop! Anyways, glad to know the situation is better than the initial blog post.
Posted Mar 25, 2013 21:09 UTC (Mon)
by mansr (guest, #85328)
[Link]
Posted Mar 26, 2013 0:57 UTC (Tue)
by nix (subscriber, #2304)
[Link]
Posted Mar 23, 2013 16:31 UTC (Sat)
by dougg (guest, #1894)
[Link] (4 responses)
Posted Mar 23, 2013 16:52 UTC (Sat)
by mansr (guest, #85328)
[Link] (3 responses)
Posted Mar 23, 2013 22:46 UTC (Sat)
by Trelane (guest, #56877)
[Link] (2 responses)
Posted Mar 23, 2013 23:05 UTC (Sat)
by mansr (guest, #85328)
[Link] (1 responses)
Posted Mar 24, 2013 1:42 UTC (Sun)
by wahern (subscriber, #37304)
[Link]
Posted Mar 23, 2013 17:21 UTC (Sat)
by jedbrown (subscriber, #49919)
[Link] (1 responses)
Posted Mar 23, 2013 23:10 UTC (Sat)
by tialaramex (subscriber, #21167)
[Link]
Posted Mar 23, 2013 17:22 UTC (Sat)
by butlerm (subscriber, #13312)
[Link] (8 responses)
Posted Mar 23, 2013 22:08 UTC (Sat)
by dvdeug (subscriber, #10998)
[Link]
Posted Mar 24, 2013 1:01 UTC (Sun)
by iabervon (subscriber, #722)
[Link] (6 responses)
The point is that GCC doesn't think you'll actually reach the undefined behavior part of the loop. Say you've got:
If you call this with a nul-terminated char array, or any array of at least 256 chars, it is well-defined. If you call it with a nul-terminated array of less than 256 chars, it will be faster if it uses an unconditional branch. It assumes that the programmer has some good reason to believe that short arrays are nul-terminated, which the compiler can't necessarily figure out.
Posted Mar 26, 2013 3:28 UTC (Tue)
by butlerm (subscriber, #13312)
[Link] (4 responses)
Posted Mar 26, 2013 4:12 UTC (Tue)
by iabervon (subscriber, #722)
[Link] (3 responses)
It doesn't really have an overall knowledge set that could find contradictions; it's got patterns that produce warnings and patterns that produce optimizations, and so it can't tell when optimizations are leading to total nonsense.
Posted Mar 26, 2013 5:10 UTC (Tue)
by dlang (guest, #313)
[Link] (2 responses)
The rest of the optimizations make sense, but that first one is optimistic thinking on the part of the compiler writer.
Posted Mar 26, 2013 8:39 UTC (Tue)
by mlopezibanez (guest, #66088)
[Link]
Of course, GCC could do better at static analysis and warning about such cases, but that is a different problem from optimization, and GCC needs new developers that are interested in such things.
Posted Mar 27, 2013 22:27 UTC (Wed)
by HelloWorld (guest, #56129)
[Link]
Posted Mar 27, 2013 19:23 UTC (Wed)
by HelloWorld (guest, #56129)
[Link]
Posted Mar 23, 2013 20:23 UTC (Sat)
by stevenb (guest, #11536)
[Link]
Nothing to see, move along...
Posted Mar 24, 2013 0:46 UTC (Sun)
by pflugstad (subscriber, #224)
[Link] (12 responses)
I also think this code is confusing and poor coding style. Why even have dd? I think this code:
is cleaner, easier to understand and maintain, and eliminates the bug. With any optimization at all, GCC should eliminate the repeated d[k] accesses so I would expect almost identical code and performance. Maybe I'm just missing something? Even if you leave dd in there, doing the assignment inside the block is cleaner and easier to understand than inside the for loop.
I also think that GCC using a undefined data access to essentially short circuit a for loop control variable is just busted - and it looks like they fixed this before the final GCC was actually released.
Posted Mar 24, 2013 1:55 UTC (Sun)
by pflugstad (subscriber, #224)
[Link] (9 responses)
And I still think it's buggy and unclear code.
Posted Mar 24, 2013 6:53 UTC (Sun)
by alankila (guest, #47141)
[Link] (8 responses)
Posted Mar 25, 2013 19:27 UTC (Mon)
by tjc (guest, #137)
[Link] (7 responses)
i++;
as a stand-alone statement would be a useful compromise, since it could still be used as the increment statement in a for loop, which is by far the most common idiom for this construct.
Posted Mar 25, 2013 23:13 UTC (Mon)
by HelloWorld (guest, #56129)
[Link] (4 responses)
Posted Mar 26, 2013 0:34 UTC (Tue)
by tjc (guest, #137)
[Link] (3 responses)
The Development of the C Language I think i++ is fine from a syntax point of view, so long as it's a stand-along statement, where it produces the same code as i += 1. But I try to avoid embedding increment operators within expressions that produce easily overlooked side effects.
Posted Mar 26, 2013 9:00 UTC (Tue)
by khim (subscriber, #9252)
[Link] (2 responses)
Well, your own link shows that it's not an "urban legend" but more like oversimplification: This is historically impossible, since there was no PDP-11 when B was developed. The PDP-7, however, did have a few `auto-increment' memory cells, with the property that an indirect memory reference through them incremented the cell. This feature probably suggested such operators to Thompson; the generalization to make them both prefix and postfix was his own. While factually incorrect (C design predates PDP-11) both "++" in C and
"(RX)+" in PDP-11's assembler come from the same source.
Posted Mar 26, 2013 16:04 UTC (Tue)
by hummassa (guest, #307)
[Link] (1 responses)
a = *b++
was a single instruction; they made easy to implement real fast stacks and queues, and zero-terminated strings (because "a = *b++" &c set the Z flag if the char was zero).
Posted Mar 26, 2013 16:52 UTC (Tue)
by brouhaha (guest, #1698)
[Link]
Posted Mar 26, 2013 8:09 UTC (Tue)
by alankila (guest, #47141)
[Link] (1 responses)
Posted Mar 26, 2013 16:26 UTC (Tue)
by tjc (guest, #137)
[Link]
Posted Mar 24, 2013 19:02 UTC (Sun)
by iabervon (subscriber, #722)
[Link] (1 responses)
It's like writing an exam question: it would be easy to write a question that everybody would get right, but you want to write a question that people who know the material will get right more often than people who don't. Obviously, in ordinary life, you want to ask questions which will be more likely to get correct answers, and you want to write code that all compilers will make as fast as possible, but that's not the situation here.
Posted Mar 25, 2013 5:09 UTC (Mon)
by cesarb (subscriber, #6266)
[Link]
It was not written to stress test compilers. It is just not very optimized (and since it is only a reference implementation, it does not have to be).
Posted Mar 25, 2013 7:53 UTC (Mon)
by jakub@redhat.com (guest, #31780)
[Link]
__attribute__((noinline, noclone)) int
int
Posted Mar 25, 2013 10:12 UTC (Mon)
by jezuch (subscriber, #52988)
[Link] (15 responses)
Well...
> for (dd=d[k=0]; k<16; dd=d[++k])
That's.... horrifying.
Posted Mar 25, 2013 15:43 UTC (Mon)
by hthoma (subscriber, #4743)
[Link] (14 responses)
> That's.... horrifying.
Exactly. Looks like obfuscated C contest stuff ...
I would guess that if you write it the "normal" way, i.e.
for(k = 0; k < 16; k++) {
the compiler would not optimize the code to an infinite loop and get a better chance to optimize.
Posted Mar 26, 2013 8:02 UTC (Tue)
by jezuch (subscriber, #52988)
[Link] (6 responses)
I guess it's a result of a *very* popular misconception that the more you cram into a single statement the faster it is ;)
Seeing how the compiler unwinds all of this stuff is an eye-opening experience. We, humans, have a very limited operating memory; the compiler can analyze much, much larger structures than we imagine it can.
Posted Mar 26, 2013 9:44 UTC (Tue)
by khim (subscriber, #9252)
[Link] (5 responses)
It may not run faster, but it certainly is shorter and a lot of guys (including me) always try to make code shorter. It's funny, really: it looks like I've finally found where these clashes come from. Less them two years ago I had no idea and struggled to understand, but now, after a lot of discussions with other guys on an important piece of code in our project, I know that there are two types of programmers: the ones who think about their program in C (C++, C#, Java, JavaScript (uh-oh), PHP (ugh), Python, etc) and the ones who think about their program in English (Hebrew, Mandarin, Russian, whatever). For the "C thinkers" size of the code is very important (the shorter it is the easier to observe large chunks of code at once) and most comments are just useless distraction (and/or admission of defeat: what, you mean this piece of code is so convoluted and cryptic that you can't understand it just from a C code... gosh I think it's time to give up and add couple of comments). Sure, high-level interface must be described in human language (C is great for low-level bit manipulations, but for description of relationship between HTML document and DOM tree, created from said document it's too low-level), but everything below it must be understandable from the code. For "English thinkers" comments are vital piece of the information: they expect to fully understand the program from comments alone and perceive the need to actually read C code as something degrading (or as necessary evil when something does not work). Even if they read C code they usually just compare it to the comment near it (and they become angry when they found no comments to compare the code to). For them size of code is less important (because they only ever perceive it in small pieces) and verbose style is, actually, better (it makes it easier to compare code to comments). I'm not sure which style is better, but I found that C thinkers usually produce fast and efficient code which may contain small, localized bugs (the code in article is prime example) while English thinkers produce code which is verbose and slow yet still contain plethora of bugs - but these bugs are distinctly different: instead of off-by-one errors or simple "++" vs "--" mixup we have cases where one module produces subtly broken object which is mishandled by another module and then everything blows up in a third one. Easy to understand why: there are no "safety net" in C thinkers code thus localized bugs are easy to miss, but interfaces are very narrow and well-defined while English thinkers produce the code which is locally correct but globally they are hopeless because there are so many interactions between different pieces of code. Think XBox or Wii bootloader code (few bugs in the initial runs which were eventually ironed out and now there are no new bugs in sight) vs JVM code (there are endless bugs without the end in sight - and most of them are because different pieces of code interact "quirckly").
Posted Mar 27, 2013 13:32 UTC (Wed)
by nye (guest, #51576)
[Link]
Posted Mar 27, 2013 15:16 UTC (Wed)
by redden0t8 (guest, #72783)
[Link] (1 responses)
I'm definitely a C-thinker, but over-shortening code (like in this article's example) really makes me cringe. I really don't understand the drive to make pieces of code as short as possible. I'm more along the lines of "clear and concise", with "clear" being more important than "concise". I guess you could think of it as writing code so as to optimize the time it takes to read and follow, rather than optimizing the line count.
Then again maybe this comes from being a hobbyist programmer and not a professional... maybe I just have a different definition of "clear" lol.
Posted Mar 27, 2013 17:43 UTC (Wed)
by dlang (guest, #313)
[Link]
the obfuscated C contest shows clear examples where concise is far more important than clear.
But the line itself if rather fuzzy.
hijacking an example from elsewhere. If you have a bucket filled with water and start punching holes in the bottom, when does it stop being a bucket that leaks and start being a sieve? At some point it will be very clear that you have passed the line, but exactly where the line is is hard to define.
Posted Mar 27, 2013 19:17 UTC (Wed)
by HelloWorld (guest, #56129)
[Link] (1 responses)
Posted Apr 1, 2013 14:51 UTC (Mon)
by khim (subscriber, #9252)
[Link]
Posted Apr 1, 2013 16:19 UTC (Mon)
by hummassa (guest, #307)
[Link] (6 responses)
for(auto x: dd)
?? (generates the same code, no errors and READABLE...)
Posted Apr 1, 2013 16:57 UTC (Mon)
by hummassa (guest, #307)
[Link] (5 responses)
auto satd = accumulate(begin(d), end(d), 0, [](int a, int x) { return a+abs(x); });
But I suppose that has the potential to be less efficient, at least it involves some function calls here...
Posted Apr 2, 2013 17:30 UTC (Tue)
by hummassa (guest, #307)
[Link] (4 responses)
Posted Apr 2, 2013 19:17 UTC (Tue)
by jwakely (subscriber, #60262)
[Link] (3 responses)
Posted Apr 2, 2013 20:08 UTC (Tue)
by nix (subscriber, #2304)
[Link] (1 responses)
Posted Apr 2, 2013 22:56 UTC (Tue)
by jwakely (subscriber, #60262)
[Link]
Posted Apr 2, 2013 21:18 UTC (Tue)
by hummassa (guest, #307)
[Link]
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
...
for (int i=0; i<(sizeof(a)/sizeof(int)); i++){
done_stuff_with(a[i]);
}
...
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
>> unusual syntax like k < 16 to express 1, because chances are that
>> wasn't the original intent.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Note that the original article was testing a pre-release GCC 4.8. The final version of GCC 4.8 contains the following bug fix:
Regehr: GCC 4.8 (pre-release) Breaks Broken SPEC 2006 Benchmarks
Bug 53265 - Warn when undefined behavior implies smaller iteration count
And the GCC 4.8 Release Notes were updated to explain:
In some loops that have known constant number of iterations, but undefined behavior is known to occur in the loop before reaching or during the last iteration, GCC will warn about the undefined behavior in the loop instead of deriving lower upper bound of the number of iterations for the loop. The warning can be disabled with -Wno-aggressive-loop-optimizations.
It's actually a common programming mistake often found by Valgrind. I'm afraid the new gcc would generate the code that would behave in unexpected ways without triggering Valgrind warnings.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
...
}
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
So gcc-4.8.0 is actually fine and John must have used a prerelease
version/
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
% gcc -S -o - -O2 test.c
.file "test.c"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
movl d(%rip), %ecx
movl $d+4, %edx
xorl %eax, %eax
.p2align 4,,10
.p2align 3
.L3:
movl %ecx, %esi
addq $4, %rdx
sarl $31, %esi
xorl %esi, %ecx
subl %esi, %ecx
addl %ecx, %eax
movl -4(%rdx), %ecx
cmpq $d+68, %rdx
jne .L3
rep ret
.cfi_endproc
.LFE0:
.size main, .-main
.comm d,64,32
.ident "GCC: (GNU) 4.8.0"
.section .note.GNU-stack,"",@progbits
% gcc -v
Using built-in specs.
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.0/gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.8.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/markus/gcc/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.0 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.0/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.0 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.0/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.0/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.0/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --without-ppl --without-cloog --enable-lto --enable-nls --without-included-gettext --with-system-zlib --disable-werror --enable-initfini-array --with-gold --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --disable-libgomp --enable-cld --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.8.0/python --enable-checking=release --disable-libgcj --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-build-config=slim-lto-bootstrap --with-boot-ldflags=-Wl,-O1,--hash-style=gnu,--as-needed,--gc-sections,--icf=safe,--icf-iterations=3 --enable-version-specific-runtime-libs --disable-libstdcxx-pch --enable-libstdcxx-time=yes
Thread model: posix
gcc version 4.8.0 (GCC)
It would be more interesting to know the description of the commit that changed the behavior. As others wrote, it would be nice if gcc emitted a warning ("comparison is always true") regardless of the code it generates.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
You could omit the warning whenever the expression to be tested is a constant-expression as defined by the C standard. The code to test for that is already there, so it should be trivial. In any case, it's time for the GCC developers to think about these issues, it's not the first time something like that comes up after all.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
#1 k starts as zero
#2 k is incremented every loop, which is its only assignment point.
#3 k is 16 when the loop stops.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
SPEC 2006
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
static inline int framelen(char s[]) {
for (int i = 0; i < 256; i++) {
if (!s[i])
return i;
}
return i;
}
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
That's not the chain of reasoning. The reasoning is that if the loop variable is out of range, the program's behaviour is undefined, thus not testing the variable is just as valid as testing it or doing something else entirely.
Use the string.h, Luke!
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
static inline int framelen(char s[]) {
return strnlen(s, 256);
}
;)
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Couldn't doing a read off the end of an array potentially cause a segfault? Depending on how the array was allocated? If so, seems to me like this is just buggy code, plain and simple.
access off end of array
int d[16];
int SATD (void)
{
int satd = 0, k;
for ( k=0; k<16; k++ ) {
satd += (d[k] < 0 ? -d[k] : d[k]);
}
return satd;
}
access off end of array
access off end of array
access off end of array
access off end of array
Actually, the ++/PDP-11 connection is urban legend -- see "More History", paragraph 2 at this link:
access off end of array
access off end of array
Actually, the ++/PDP-11 connection is urban legend -- see "More History", paragraph 2 at this link:
The Development of the C Languageaccess off end of array
a = *++b
a = *b--
a = *--b
*b++ = a
*++b = a
*b-- = a
*--b = a
Yes, but the 6809 came along much later than the PDP-11, so it's not relevant to discussion of where the C pre/post-increment/decrement operators came from.
access off end of array
access off end of array
access off end of array
access off end of array
access off end of array
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
int a[4];
foo (int x)
{
int i, r = 0, n = x & 31;
for (i = 0; i < n; i++)
r += a[i];
return r;
}
main ()
{
int x = 255;
__asm volatile ("" : "+r" (x));
return foo (x);
}
. With -O3 and not -fno-aggressive-loop-optimizations, GCC from the loop determines the high bound to be 4 and completely unrolls the loop into 4 reads from a (+ additions for 2nd and up iteration) preceeded each by test of the n variable, so the code won't actually read beyond end of a array, while with -O3 -fno-aggressive-loop-optimizations GCC won't compute the upper bound estimate so low (VRP can figure out it is 32, while other passes just estimate INT_MAX), so the loop happily will read beyond end of a, is vectorized (which is unlikely desirable for such small number of iterations), etc. Even without the "& 31" the situation is similar, and certainly for that case I don't see why a warning would be ever useful, the routine just can be valid only when called with a parameter 0 to 3, but there is no reason not to assume all the callers don't do that (the asm is optimization barrier, the compiler isn't supposed to look through it).
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
dd = d[k];
satd += (dd < 0 ? -dd : dd);
}
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Uh, no it's not. The obfuscated version is 25 tokens, the sensible one is 22 tokens. Sure, if you use conventional formatting, you'll end up with one more line for the normal version, but nobody says you have to do that...
Screen real estate is not measured in tokens. Inches, centimeters, may be pixels, but most definitely not tokens. But this measure it's shorter. Is it worth it? That's debatable and depends very much on the individual, but of course it's separate issue.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
satd += abs(x);
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
I am answering to my own comments in this subthread, and it really feels like I am losing my mind... :-DRegehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
anyway, I tried this with -O4 and both
for(auto x: d) satd += abs(x);
and
auto satd = accumulate(begin(d), end(d), 0, [](int a, int x) { return a+abs(x); });
generated the same code, roughly:
movl (%rax), %edx
movl (%rax), %ecx
addq $4, %rax
sarl $31, %edx
xorl %edx, %ecx
subl %edx, %ecx
leaq 64(%rsp), %r
addl %ecx, %ebx
cmpq %rax, %rdx
jne .L3 #,
which seemed nice to me.
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks
Regehr: GCC 4.8 Breaks Broken SPEC 2006 Benchmarks