Path: csiph.com!weretis.net!feeder6.news.weretis.net!feeder.usenetexpress.com!feeder-in1.iad1.usenetexpress.com!border1.nntp.dca1.giganews.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news.iecc.com!.POSTED.news.iecc.com!nerds-end From: Bart Newsgroups: comp.compilers Subject: Re: Optimization techniques and undefined behavior Date: Wed, 1 May 2019 12:40:08 +0100 Organization: virginmedia.com Lines: 102 Sender: news@iecc.com Approved: comp.compilers@iecc.com Message-ID: <19-05-003@comp.compilers> References: <72d208c9-169f-155c-5e73-9ca74f78e390@gkc.org.uk> <19-04-021@comp.compilers> <19-04-023@comp.compilers> <19-04-037@comp.compilers> <19-04-039@comp.compilers> <19-04-042@comp.compilers> <19-04-045@comp.compilers> <19-04-049@comp.compilers> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="54093"; mail-complaints-to="abuse@iecc.com" Keywords: standards, arithmetic Posted-Date: 01 May 2019 21:32:14 EDT X-submission-address: compilers@iecc.com X-moderator-address: compilers-request@iecc.com X-FAQ-and-archives: http://compilers.iecc.com Content-Language: en-GB Xref: csiph.com comp.compilers:2239 On 30/04/2019 14:48, David Brown wrote: > On 29/04/2019 19:15, Bart wrote: >> On 29/04/2019 16:08, David Brown wrote: >>> On 29/04/2019 01:31, Bart wrote: >> >>>> then you don't want the compiler being clever about overflow. >>> >>> I /do/ want a result consistent with a single expression, or splitting >>> up the expression. >> >> Then the choice is between both ways giving you 1500000000, or both >> giving you -647483648. > > Let me repeat - I do not care what the results are here.  I don't care > if they are consistent with each other.  I don't care if they change > between runs of the compiler.  I don't care if the result is a pink > umbrella. So, there's a bug in the program, an inadvertent overflow. But rather than help in discovering that bug (such as giving the wrong results) gcc (and its clone Clang) conveniently pretend that such bugs cannot exist, and use that to give their code an unfair advantage: #include int main(void) { int x,y,z; x=1000000000; z=0; for (int i=0; i<1000000000; ++i) { y=x*3/3; z+=y; ++x; } printf("%d\n",x); printf("%d\n",y); printf("%d\n",z); } Optimising compilers that don't take advantage of that undefined behaviour give timings here of 1.25 seconds (msvc) and 1.9 seconds (pelles c), with some taking much longer. The two that do, give timings of 0.22 seconds (gcc) and 0.05 seconds (clang). However, there are a couple of problems: (1) they give different results; (2) they cheated by not doing a billion multiplies and divides. Note this example also includes UB due to z+=y line, but I'm only interested in the bottom 32 bits, albeit signed, as a kind of checksum to compare with other compilers. For that purpose, I need the final z value to be -101627306, which will match the same 32-bit arithmetic across languages** and in assembly. I don't need it to be the mathematically correct 1499999999500000000, which seems to me what you'd like it to be. gcc/clang-O3 give me 1565039360 which is neither one nor the other. ------------------------------- (** This is the above program auto-translated from C to one of my languages, which is sort of interesting, this being a compiler group. Normally this is just for to help in viewing torturous C source code as the C semantics are not translated. But tweaked with the int32() cast to match C's intermediate calculations (usually 64-bit here), this actually works: import clib global function main()int32 = var int32 x var int32 y var int32 z var int32 i x := 1000000000 z := 0 i := 0 while i<1000000000 do y := int32(x*3)/3 z +:= y ++x ++i od printf("%d\n",x) printf("%d\n",y) printf("%d\n",z) return 0 end proc start = stop main() end The results match those of the non-gcc/non-clang C compilers (apart from speed which is poor).)