Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #105743 > unrolled thread
| Started by | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| First post | 2017-03-10 11:57 -0800 |
| Last post | 2017-03-15 13:39 -0700 |
| Articles | 20 on this page of 107 — 23 participants |
Back to article view | Back to comp.lang.c
va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 11:57 -0800
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 12:04 -0800
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-10 12:32 -0800
Re: va_start without the first argument? "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2017-03-10 15:51 -0500
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 14:36 -0800
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 14:53 -0800
Re: va_start without the first argument? Robert Wessel <robertwessel2@yahoo.com> - 2017-03-10 17:14 -0600
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 15:37 -0800
Re: va_start without the first argument? Robert Wessel <robertwessel2@yahoo.com> - 2017-03-10 23:12 -0600
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 10:29 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 11:31 -0700
Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-13 18:40 +0000
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 12:31 -0700
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-11 19:53 +0100
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-11 19:05 +0000
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-11 11:56 -0800
Re: va_start without the first argument? antispam@math.uni.wroc.pl - 2017-03-12 05:41 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 13:52 +0100
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-12 14:40 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 18:13 +0100
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-12 18:04 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 21:04 +0100
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-12 21:02 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-12 22:40 +0100
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-12 15:51 -0700
Re: va_start without the first argument? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-03-12 16:52 -0700
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-13 00:56 +0100
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-13 09:17 -0700
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 17:54 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-13 22:12 +0100
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 22:48 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 13:46 +0100
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-14 13:37 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 15:24 +0100
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 08:25 -0700
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 17:02 +0100
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 09:45 -0700
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 09:15 -0700
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 10:02 -0700
Re: va_start without the first argument? jt@toerring.de (Jens Thoms Toerring) - 2017-03-14 20:32 +0000
Re: va_start without the first argument? raltbos@xs4all.nl (Richard Bos) - 2017-03-14 07:44 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 13:38 +0100
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 08:57 -0700
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-13 11:21 -0700
Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-13 18:33 +0000
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-13 22:08 +0100
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-13 15:23 -0700
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 13:58 +0100
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 09:18 -0700
Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 16:52 +0000
Re: va_start without the first argument? Keith Thompson <kst-u@mib.org> - 2017-03-14 11:34 -0700
Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 18:54 +0000
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 13:30 -0700
Re: va_start without the first argument? Ike Naar <ike@iceland.freeshell.org> - 2017-03-15 21:55 +0000
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-15 15:16 -0700
Re: va_start without the first argument? Philip Lantz <prl@canterey.us> - 2017-03-23 21:04 -0700
Re: va_start without the first argument? David Brown <david.brown@hesbynett.no> - 2017-03-14 21:48 +0100
Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 14:01 +0000
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-14 07:42 -0700
Re: va_start without the first argument? scott@slp53.sl.home (Scott Lurndal) - 2017-03-14 12:38 +0000
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-13 01:11 +0100
Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-13 15:43 +1300
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 10:36 +0000
Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-14 07:33 +1300
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 19:00 +0000
Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-14 08:05 +1300
Re: va_start without the first argument? BartC <bc@freeuk.com> - 2017-03-13 23:10 +0000
Re: va_start without the first argument? Ian Collins <ian-news@hotmail.com> - 2017-03-14 17:38 +1300
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-14 05:48 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 12:12 -0700
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-12 19:39 +0100
Re: va_start without the first argument? jt@toerring.de (Jens Thoms Toerring) - 2017-03-10 20:49 +0000
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-10 14:41 -0800
Re: va_start without the first argument? John Bode <jfbode1029@gmail.com> - 2017-03-10 16:05 -0800
Re: va_start without the first argument? jacob navia <jacob@jacob.remcomp.fr> - 2017-03-11 21:47 +0100
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-11 13:07 -0800
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-11 22:24 +0100
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 05:44 -0700
Re: va_start without the first argument? Jerry Stuckle <jstucklex@attglobal.net> - 2017-03-13 08:59 -0400
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 06:17 -0700
Re: va_start without the first argument? Jerry Stuckle <jstucklex@attglobal.net> - 2017-03-13 13:27 -0400
Re: va_start without the first argument? Jerry Stuckle <jstucklex@attglobal.net> - 2017-03-13 13:30 -0400
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 11:00 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 10:34 -0700
Re: va_start without the first argument? antispam@math.uni.wroc.pl - 2017-03-12 06:00 +0000
Re: va_start without the first argument? gordonb.gas5o@burditt.org (Gordon Burditt) - 2017-03-17 09:46 -0500
Re: va_start without the first argument? supercat@casperkitty.com - 2017-03-17 09:07 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 05:39 -0700
Re: va_start without the first argument? John Bode <jfbode1029@gmail.com> - 2017-03-13 11:40 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 12:01 -0700
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-13 23:17 +0100
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 16:15 -0700
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-14 00:26 +0100
Re: va_start without the first argument? kikiins@gmail.com - 2017-03-13 16:51 -0700
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-14 01:12 +0100
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 18:24 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-13 18:57 -0700
Re: va_start without the first argument? raltbos@xs4all.nl (Richard Bos) - 2017-03-14 07:59 +0000
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-14 06:45 -0700
Re: va_start without the first argument? Robert Wessel <robertwessel2@yahoo.com> - 2017-03-13 18:20 -0500
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-14 00:31 +0100
Re: va_start without the first argument? raltbos@xs4all.nl (Richard Bos) - 2017-03-13 16:51 +0000
Re: va_start without the first argument? jacobnavia <jacob@jacob.remcomp.fr> - 2017-03-11 19:29 +0100
Re: va_start without the first argument? Siri Cruise <chine.bleu@yahoo.com> - 2017-03-11 12:12 -0800
Re: va_start without the first argument? luser droog <luser.droog@gmail.com> - 2017-03-13 05:37 -0700
Re: va_start without the first argument? luser droog <luser.droog@gmail.com> - 2017-03-15 11:45 -0700
Re: va_start without the first argument? Thiago Adams <thiago.adams@gmail.com> - 2017-03-15 13:39 -0700
Page 2 of 6 — ← Prev page 1 [2] 3 4 5 6 Next page →
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-03-12 18:04 +0000 |
| Message-ID | <oa42ej$dms$1@dont-email.me> |
| In reply to | #105872 |
On 12/03/2017 17:13, David Brown wrote: > On 12/03/17 15:40, BartC wrote: >> I've done this and was hoping to use the same approach for compiling C >> (for x64). But it won't work because there is now no distinction between >> C functions which are compiled here, and C functions compiled elsewhere >> by another compiler. > > Sure there is - if your compiler is the one compiling a function, and > you know that all uses of the function are through code that you > compile, then you can do what you want. This is usually the case for > static functions (unless you take their address and pass it outside the > current translation unit). Yeah, maybe. But when 99% of calls could be your own call convention, then it would be worth doing (and with the 1% using the ABI, the efficiency of those wouldn't matter). But if it's only static functions, and only those you can be sure can't be called by any other means ... Even then, sometimes you want to take the address of a static function. Then when you call via a pointer, it's not going to be easy to determine if an arbitrary pointer points to a static function, or a global one, or can be either during the course of the program. For example, you pass a function pointer to a function; that function won't know its provenance. Of course an implementation can choose to generate two copies of static functions, one of which is used only for direct internal calls. But this is way past the point where it would just be easier to use the official ABI. >> (Not that this ABI makes things that much faster, if at all. If I take >> my current project and compile with gcc -O0, then the 32-bit version is >> 8% faster than the 64-bit, despite the latter passing parameters in >> registers for most functions.) >> > > Speed comparisons without optimisation are /always/ pointless. No, it makes it easier to compare how long things take to execute (rather than how long it takes /not/ to execute them as often happens with gcc). Anyway, if I use -O3 for both, then the 32-bit version is 12% faster! Despite having fewer and narrower registers. > And there are a variety of things that can affect the difference in > speed between 32-bit and 64-bit versions (even when you have allowed the > compiler to generate decent code by using at least -O1). Pointers in > 64-bit mode are 64-bit wide - that means more cache is needed, meaning > more cache misses, and more memory bandwidth is needed. For some > applications, the difference here can be significant. And in Windows, > the aforementioned idiotic requirement of allocating stack space for the > arguments passed in registers means wasted time and wasted cache space > on every function call in 64-bit mode. The pointer one I know about (I think it cost me 5% loss of performance when I switched an old x64 compiler from 32- to 64-bit pointers). But how much would allocating those 32 bytes of stack cost? Bear in mind that probably nothing will be written to them. (It'll reduce cache capacity to a certain extent, but only as far as the maximum call-nesting depth, which usually isn't very much. If the maximum level is 30 calls deep, then we're talking 1KB in total.) -- bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-12 21:04 +0100 |
| Message-ID | <oa49f0$79d$1@dont-email.me> |
| In reply to | #105879 |
On 12/03/17 19:04, BartC wrote: > On 12/03/2017 17:13, David Brown wrote: >> On 12/03/17 15:40, BartC wrote: > >>> I've done this and was hoping to use the same approach for compiling C >>> (for x64). But it won't work because there is now no distinction between >>> C functions which are compiled here, and C functions compiled elsewhere >>> by another compiler. >> >> Sure there is - if your compiler is the one compiling a function, and >> you know that all uses of the function are through code that you >> compile, then you can do what you want. This is usually the case for >> static functions (unless you take their address and pass it outside the >> current translation unit). > > Yeah, maybe. But when 99% of calls could be your own call convention, > then it would be worth doing (and with the 1% using the ABI, the > efficiency of those wouldn't matter). But if it's only static functions, > and only those you can be sure can't be called by any other means ... > > Even then, sometimes you want to take the address of a static function. > Then when you call via a pointer, it's not going to be easy to determine > if an arbitrary pointer points to a static function, or a global one, or > can be either during the course of the program. For example, you pass a > function pointer to a function; that function won't know its provenance. > > Of course an implementation can choose to generate two copies of static > functions, one of which is used only for direct internal calls. But this > is way past the point where it would just be easier to use the official > ABI. This is all a matter of quality of implementation - /you/ choose. Using more efficient calling conventions for local calls (static calls whose address is not taken) should be relatively easy. Dealing with other calls is going to be a lot harder - you will likely need some sort of whole program optimisation or link-time code generation. > >>> (Not that this ABI makes things that much faster, if at all. If I take >>> my current project and compile with gcc -O0, then the 32-bit version is >>> 8% faster than the 64-bit, despite the latter passing parameters in >>> registers for most functions.) >>> >> >> Speed comparisons without optimisation are /always/ pointless. > > No, it makes it easier to compare how long things take to execute > (rather than how long it takes /not/ to execute them as often happens > with gcc). Yes, speed comparisons without optimisation are /always/ pointless. You can't compare the speed of two cars if you insist that they both stay in first gear - even if they are two models from the same manufacturer. > > Anyway, if I use -O3 for both, then the 32-bit version is 12% faster! > Despite having fewer and narrower registers. And there you have an interesting comparison. This is Windows, I take it? Different programs will see different gains or loses in speed here. You will want to test quite a few different programs to get more general results. > > >> And there are a variety of things that can affect the difference in >> speed between 32-bit and 64-bit versions (even when you have allowed the >> compiler to generate decent code by using at least -O1). Pointers in >> 64-bit mode are 64-bit wide - that means more cache is needed, meaning >> more cache misses, and more memory bandwidth is needed. For some >> applications, the difference here can be significant. And in Windows, >> the aforementioned idiotic requirement of allocating stack space for the >> arguments passed in registers means wasted time and wasted cache space >> on every function call in 64-bit mode. > > The pointer one I know about (I think it cost me 5% loss of performance > when I switched an old x64 compiler from 32- to 64-bit pointers). > > But how much would allocating those 32 bytes of stack cost? Bear in mind > that probably nothing will be written to them. Leaf functions are often quite short, and often would not need a stack frame at all if it were not for this extra allocation. So you have extra instructions to modify the stack pointer and restore it afterwards, perhaps also with a frame pointer there somewhere. > > (It'll reduce cache capacity to a certain extent, but only as far as the > maximum call-nesting depth, which usually isn't very much. If the > maximum level is 30 calls deep, then we're talking 1KB in total.) > It all adds up. I expect it is not a particularly big cost, but it is a pointless one.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-03-12 21:02 +0000 |
| Message-ID | <oa4csk$jd4$1@dont-email.me> |
| In reply to | #105886 |
On 12/03/2017 20:04, David Brown wrote: > On 12/03/17 19:04, BartC wrote: >> No, it makes it easier to compare how long things take to execute >> (rather than how long it takes /not/ to execute them as often happens >> with gcc). > > Yes, speed comparisons without optimisation are /always/ pointless. You > can't compare the speed of two cars if you insist that they both stay in > first gear - even if they are two models from the same manufacturer. I would have to disagree. Comparing with optimisation on is like timing two cars along a route from A to B, but one decides to take a short cut. Or, if A and B are the same point and the route is circular, it doesn't bother to go anywhere at all. Yes, that will give a faster time. But it is totally useless for finding out exactly how long it /would/ have taken the car to drive the official route. (Imagine if you are testing two buses; they /have/ to use a certain route, otherwise passengers won't be happy either if the bus never turns up, or it's late because they chose the slower vehicle based on misleading tests.) With gcc, I very often find it gives an extremely fast time for a task, but only because it hasn't bothered to do it at all, if it there's no point! >> Anyway, if I use -O3 for both, then the 32-bit version is 12% faster! >> Despite having fewer and narrower registers. > > And there you have an interesting comparison. This is Windows, I take it? Yes. The only Linux I have where I can test 32- and 64-bit programs together is a virtual one. And there, 64-bit code is 5-6% faster than 32-bit. (But both seem to run about 1/3 slower than Windows on the same machine on the same task. The Linux gcc is 6.x while the Windows one 5.x) > Different programs will see different gains or loses in speed here. You > will want to test quite a few different programs to get more general > results. All of my language-related programs (all computationally intensive with little use of external libraries) show the same pattern. Only where there a lot of actual 64-bit arithmetic going on, does a 64-bit build show an obvious difference. > Leaf functions are often quite short, and often would not need a stack > frame at all if it were not for this extra allocation. Possibly, with a leaf function taking no more than 4 parameters, and not doing stuff with variable arguments or taking addresses of the parameters, you can get away without those 32 bytes allocated by the caller. So it can be called with or without. -- bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-12 22:40 +0100 |
| Message-ID | <oa4f3e$r2v$1@dont-email.me> |
| In reply to | #105888 |
On 12/03/17 22:02, BartC wrote:
> On 12/03/2017 20:04, David Brown wrote:
>> On 12/03/17 19:04, BartC wrote:
>
>>> No, it makes it easier to compare how long things take to execute
>>> (rather than how long it takes /not/ to execute them as often happens
>>> with gcc).
>>
>> Yes, speed comparisons without optimisation are /always/ pointless. You
>> can't compare the speed of two cars if you insist that they both stay in
>> first gear - even if they are two models from the same manufacturer.
>
> I would have to disagree. Comparing with optimisation on is like timing
> two cars along a route from A to B, but one decides to take a short cut.
> Or, if A and B are the same point and the route is circular, it doesn't
> bother to go anywhere at all.
>
> Yes, that will give a faster time. But it is totally useless for finding
> out exactly how long it /would/ have taken the car to drive the official
> route. (Imagine if you are testing two buses; they /have/ to use a
> certain route, otherwise passengers won't be happy either if the bus
> never turns up, or it's late because they chose the slower vehicle based
> on misleading tests.)
That analogy is now stretched well beyond breaking point...
>
> With gcc, I very often find it gives an extremely fast time for a task,
> but only because it hasn't bothered to do it at all, if it there's no
> point!
Of course the compiler will skip code that is not needed. That is an
important function of a compiler - it makes it easier to write more
generic code, knowing that the compiler will handle the details.
If you want to time how long the code takes to do something, you need to
understand how C works and write code that actually does something, at
least according to the rules of C.
So if you want to time the results of "bigCalculation()" and write code
like:
static int bigCalculation(int n) {
...
}
double test(void) {
time_t startTime = time(0);
int x = bigCalculation(100);
time_t endTime = time(0);
return difftime(startTime, endTime);
}
the compiler can see that bigCalculation is being called with a known
constant argument, and the return value is unused - it is very likely
that it can be omitted altogether.
Instead, write:
volatile int n;
volatile int x;
double test(void) {
time_t startTime = time(0);
n = 100;
x = bigCalculation(n);
time_t endTime = time(0);
return difftime(startTime, endTime);
}
By making "n" volatile, the compiler will not assume it is a
compile-time constant, and it will write it then read it. Similarly, by
making "x" volatile, the compiler is obliged to write the correct value
to it. Unless it can figure out a fixed value for bigCalculation
independent of the argument, it is going to have to carry out the
calculation.
And now you can do your compilation with optimisation enabled so that
the compiler can generate sensible code.
>
>>> Anyway, if I use -O3 for both, then the 32-bit version is 12% faster!
>>> Despite having fewer and narrower registers.
>>
>> And there you have an interesting comparison. This is Windows, I take
>> it?
>
> Yes. The only Linux I have where I can test 32- and 64-bit programs
> together is a virtual one. And there, 64-bit code is 5-6% faster than
> 32-bit. (But both seem to run about 1/3 slower than Windows on the same
> machine on the same task. The Linux gcc is 6.x while the Windows one 5.x)
Virtualisation makes it hard to compare results, especially if it is an
older cpu with limited hardware support for virtualisation. And of
course, I have no idea what your programs are - there can be many
reasons for performance differences.
>
>> Different programs will see different gains or loses in speed here. You
>> will want to test quite a few different programs to get more general
>> results.
>
> All of my language-related programs (all computationally intensive with
> little use of external libraries) show the same pattern.
>
> Only where there a lot of actual 64-bit arithmetic going on, does a
> 64-bit build show an obvious difference.
>
>> Leaf functions are often quite short, and often would not need a stack
>> frame at all if it were not for this extra allocation.
>
> Possibly, with a leaf function taking no more than 4 parameters, and not
> doing stuff with variable arguments or taking addresses of the
> parameters, you can get away without those 32 bytes allocated by the
> caller. So it can be called with or without.
>
Few functions take more than four parameters, and even fewer functions
take variable arguments - so that applies to most functions.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-03-12 15:51 -0700 |
| Message-ID | <7fda2e02-9a6a-411f-9d91-1ad9030ec778@googlegroups.com> |
| In reply to | #105891 |
On Sunday, March 12, 2017 at 4:40:46 PM UTC-5, David Brown wrote: > Of course the compiler will skip code that is not needed. That is an > important function of a compiler - it makes it easier to write more > generic code, knowing that the compiler will handle the details. In some application fields, worst-case execution time is more important than average time. In such fields, some kinds of optimizer can make it hard to judge whether a piece of code should be expected to reliably meet its timing objectives. Writing unnecessary code and hoping a compiler will eliminate it doesn't seem like a very robust approach, compared with writing code which only does what's actually necssary.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2017-03-12 16:52 -0700 |
| Message-ID | <bd5761f5-6c6a-4b35-ac70-074e29bc2ab4@googlegroups.com> |
| In reply to | #105892 |
On Sunday, March 12, 2017 at 10:51:18 PM UTC, supe...@casperkitty.com wrote: > > In some application fields, worst-case execution time is more > important than average time. In such fields, some kinds of optimizer > can make it hard to judge whether a piece of code should be expected > to reliably meet its timing objectives. Writing unnecessary code and > hoping a compiler will eliminate it doesn't seem like a very robust > approach, compared with writing code which only does what's actually > necssary. > It's often far more readable to call discrete functions which throw away intermediate results rather than try to recycle those intermediate results. But you hope that if the functions are inlined then the compiler will at least make a good stab at eliminating the common sub-expressions.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-13 00:56 +0100 |
| Message-ID | <oa4n2f$nq6$1@dont-email.me> |
| In reply to | #105892 |
On 12/03/17 23:51, supercat@casperkitty.com wrote: > On Sunday, March 12, 2017 at 4:40:46 PM UTC-5, David Brown wrote: >> Of course the compiler will skip code that is not needed. That is an >> important function of a compiler - it makes it easier to write more >> generic code, knowing that the compiler will handle the details. > > In some application fields, worst-case execution time is more important than > average time. In such fields, some kinds of optimizer can make it hard to > judge whether a piece of code should be expected to reliably meet its timing > objectives. Writing unnecessary code and hoping a compiler will eliminate it > doesn't seem like a very robust approach, compared with writing code which > only does what's actually necssary. > No one suggested writing /unnecessary/ code. The point is to write code in the way that is clearest, most useful, and most maintainable. It is not uncommon for well-written code to have parts that can be eliminated by the compiler, perhaps due to inlining, constant propagation, etc. But if you think that you can make the compiler generate /exactly/ the code you want, with no extra code and no code skipped, then the code you write certainly cannot be called "robust". You might make it work with a particular compiler, a particular set of flags, and particular circumstances for calling the code - but that is the best you can hope for.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-03-13 09:17 -0700 |
| Message-ID | <a6aade9b-b090-4e38-a131-11f15f25261c@googlegroups.com> |
| In reply to | #105897 |
On Sunday, March 12, 2017 at 6:56:48 PM UTC-5, David Brown wrote:
> On 12/03/17 23:51, supercat wrote:
> >> Of course the compiler will skip code that is not needed. That is an
> >> important function of a compiler - it makes it easier to write more
> >> generic code, knowing that the compiler will handle the details.
> >
> > In some application fields, worst-case execution time is more important than
> > average time. In such fields, some kinds of optimizer can make it hard to
> > judge whether a piece of code should be expected to reliably meet its timing
> > objectives. Writing unnecessary code and hoping a compiler will eliminate it
> > doesn't seem like a very robust approach, compared with writing code which
> > only does what's actually necssary.
>
> No one suggested writing /unnecessary/ code. The point is to write code
> in the way that is clearest, most useful, and most maintainable. It is
> not uncommon for well-written code to have parts that can be eliminated
> by the compiler, perhaps due to inlining, constant propagation, etc.
The main compiler I use supports an extension which I think debuted in gcc,
which doesn't actually execute anything but returns 1 if an expression can
be evaluated as a compile-time constant and zero if it cannot. This makes
it practical to have a macro which does an action one of two ways depending
upon which is more efficient. Being able to express such concepts more
elegantly than via preprocessor macros would be nice, but the macros do work
and the code is readable on the incocation side at least.
> But if you think that you can make the compiler generate /exactly/ the
> code you want, with no extra code and no code skipped, then the code you
> write certainly cannot be called "robust". You might make it work with
> a particular compiler, a particular set of flags, and particular
> circumstances for calling the code - but that is the best you can hope for.
The authors of the C Standard did not mandate that every implementation be
suitable for all purposes. No code to accomplish any particular purpose
should be expected to run on a compiler which is not suitable for that
purpose.
Differing application fields require differing amounts of control over
generated code, and different compilers provide differing amounts of control.
In many cases, there will be multiple ways by which various tasks can be
performed and performance will fall into three categories:
1. Fast enough that additional improvements are meaningless
2. Slow enough that improvements would be nice, but not essential.
3. Sufficiently slow that performance is unacceptable.
In many cases, if trying to decide between a simpler but slower data
structure and a more complicated one, I'll start by writing the part of
the code which would most likely be a bottleneck when using the simpler
data structure and see how it performs. If it comes out in category #1,
I'll write the rest of the code that uses that data structure. I would
be rather annoyed if it turned out the data structure would only perform
well if the compiler applied optimizations to my test code which would
not be applicable in the real world.
Rarely will I expect a compiler to give precise instruction-level control.
On something like a PIC18x platforms there will be one clear best way of
coding something, and if I code something like:
unsigned char i=8;
do
{
LATB3 = 1;
LATB3 = 0;
} while(--i);
I will expect that the loop would take exactly 5 cycles (the bit-set and
bit-clear take one cycle each, and a loop-until-zero construct takes 3).
On something like an ARM, where the I/O writes would require preparatory
steps (rather than simply being one instruction each) I would hope that a
compiler would hoist such preparation out of the loop, but would neither
rely upon upon it doing so nor rely upon its failure to do so. I might
assume that a quality compiler should be able to cache some registers in
memory, writing the code as:
register __io_port_type volatile *gpio = GPIOD;
register int i=8;
register uint32_t port_val = 0x00010000;
do
{
gpio->bsrr = port_val;
gpio->bcrr = port_val;
} while(--i);
if I want to be confident that a compiler will eliminate redundant loads
within the loop [TCC doesn't do ARM, but even the most basic TCC-style
single-pass compiler should be able to generate optimal code from the
above]. Since big part of the reason C exists is to allow low-level
concepts to be expressed *without* assembly language, I would suggest
that such ability is part of what would make a particular implementation
suitable for low-level programming.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-03-13 17:54 +0000 |
| Message-ID | <oa6m89$e06$1@dont-email.me> |
| In reply to | #105913 |
On 13/03/2017 16:17, supercat@casperkitty.com wrote:
> Differing application fields require differing amounts of control over
> generated code, and different compilers provide differing amounts of control.
> In many cases, there will be multiple ways by which various tasks can be
> performed and performance will fall into three categories:
>
> 1. Fast enough that additional improvements are meaningless
>
> 2. Slow enough that improvements would be nice, but not essential.
>
> 3. Sufficiently slow that performance is unacceptable.
In the case of gcc, my experience suggests that the difference between
-O0 and -O3 is only about 2:1 at most (up to 100% faster). Unless you
test on unrepresentative microbenchmarks where anything is possible
(half the time, the -O3 timing is 0 msec).
Tested on my current compiler project compiled with gcc, the difference
is about 45% faster for -m64, and 50% for -m32; even optimisation can't
fix the hit due to the wider pointers.
On a more typical application which isn't so processor intensive, the
difference will narrow further. (And the same machine will be running
hopelessly slow interpreted scripts at the same time.)
> In many cases, if trying to decide between a simpler but slower data
> structure and a more complicated one, I'll start by writing the part of
> the code which would most likely be a bottleneck when using the simpler
> data structure and see how it performs. If it comes out in category #1,
> I'll write the rest of the code that uses that data structure. I would
> be rather annoyed if it turned out the data structure would only perform
> well if the compiler applied optimizations to my test code which would
> not be applicable in the real world.
If you want to do this sort of testing, which might depends on things
such as cache usage, alignment, and block copying efficiency, the last
thing you want is the compiler getting in the way of the test by
eliminating the very code that you are attempting to measure!
(Just yesterday, I had to need to wait a second or so before proceeding
in a bit of code. I couldn't just use a loop counting to a billion, as
this was gcc on Linux (so no alternatives), and it would just disregard
the loop. Things such as sleep() were not practical, I ended up using
getchar() then waiting for someone to press Enter.
It gets silly when you have to fight the compiler to stop it ignoring
your intentions.)
> unsigned char i=8;
> do
> {
> LATB3 = 1;
> LATB3 = 0;
> } while(--i);
> if I want to be confident that a compiler will eliminate redundant loads
> within the loop [TCC doesn't do ARM, but even the most basic TCC-style
> single-pass compiler should be able to generate optimal code from the
> above].
Tiny C? The optimal form of such a loop would keep the loop counter in a
register; I doubt it does that.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-13 22:12 +0100 |
| Message-ID | <oa71q1$snq$1@dont-email.me> |
| In reply to | #105923 |
On 13/03/17 18:54, BartC wrote: > (Just yesterday, I had to need to wait a second or so before proceeding > in a bit of code. I couldn't just use a loop counting to a billion, as > this was gcc on Linux (so no alternatives), and it would just disregard > the loop. Things such as sleep() were not practical, I ended up using > getchar() then waiting for someone to press Enter. > > It gets silly when you have to fight the compiler to stop it ignoring > your intentions.) > <http://en.cppreference.com/w/c/language/volatile> It gets silly when you complain about how many problems you have with a compiler when you simply need to learn the language you are using. Failing that, learn to use Google - you would have found the answer pretty quickly.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-03-13 22:48 +0000 |
| Message-ID | <oa77et$gq6$1@dont-email.me> |
| In reply to | #105937 |
On 13/03/2017 21:12, David Brown wrote: > On 13/03/17 18:54, BartC wrote: > >> (Just yesterday, I had to need to wait a second or so before proceeding >> in a bit of code. I couldn't just use a loop counting to a billion, as >> this was gcc on Linux (so no alternatives), and it would just disregard >> the loop. Things such as sleep() were not practical, I ended up using >> getchar() then waiting for someone to press Enter. >> >> It gets silly when you have to fight the compiler to stop it ignoring >> your intentions.) >> > > <http://en.cppreference.com/w/c/language/volatile> > > It gets silly when you complain about how many problems you have with a > compiler when you simply need to learn the language you are using. > Failing that, learn to use Google - you would have found the answer > pretty quickly. I know about 'volatile' but it is one of the ways that you have to battle the compiler. I'm sure that wasn't its original purpose, to to persuade the compiler that 'this bit of code really does do something useful guv, honest!' /You're/ the one who should be calling the shots. With a more elaborate bit of code, how can you even be sure that 'volatile' takes care of all the possible ways in a which a compiler could sneakily avoid running a crucial or significant bit of code? You also don't want mess around cluttering up code for might be a temporary test. (Besides, this C code was was auto-generated from my language where the 'volatile' attribute doesn't exist; it is an artefact only of the C language. My language tends to do what the programmer tells it to. Well until that aim is undermined when is has to make use of intermediate C code.) (For all its capabilities, on my current project [and at its current stage], gcc -O3 used for my generated C, only gives me 15% better performance than my compiler's own native code output, despite the latter's code generation being rubbish. And I admit that myself. [When both target x64]) -- bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-14 13:46 +0100 |
| Message-ID | <oa8oid$ktt$1@dont-email.me> |
| In reply to | #105951 |
On 13/03/17 23:48, BartC wrote: > On 13/03/2017 21:12, David Brown wrote: >> On 13/03/17 18:54, BartC wrote: >> >>> (Just yesterday, I had to need to wait a second or so before proceeding >>> in a bit of code. I couldn't just use a loop counting to a billion, as >>> this was gcc on Linux (so no alternatives), and it would just disregard >>> the loop. Things such as sleep() were not practical, I ended up using >>> getchar() then waiting for someone to press Enter. >>> >>> It gets silly when you have to fight the compiler to stop it ignoring >>> your intentions.) >>> >> >> <http://en.cppreference.com/w/c/language/volatile> >> >> It gets silly when you complain about how many problems you have with a >> compiler when you simply need to learn the language you are using. >> Failing that, learn to use Google - you would have found the answer >> pretty quickly. > > I know about 'volatile' but it is one of the ways that you have to > battle the compiler. Personally, I consider it "working /with/ the compiler", not "battling" it. But then, I don't view gcc as evil, nor do I feel the need to find new ways to make it appear bad so that I can persuade myself that my own toy compiler is better. > I'm sure that wasn't its original purpose, to > to persuade the compiler that 'this bit of code really does do something > useful guv, honest!' /You're/ the one who should be calling the shots. The programmer /is/ the one calling the shots - but they need to be called in the C language. In C, an empty loop does nothing - the compiler knows that, and the programmer should know that. volatile accesses exist explicitly to create "side effects" - they can be used to make the otherwise empty loop /do/ something. > > With a more elaborate bit of code, how can you even be sure that > 'volatile' takes care of all the possible ways in a which a compiler > could sneakily avoid running a crucial or significant bit of code? Basically, it's called "knowing what I am doing". Compilers are not sneaky - they follow rules. /Programmers/ are sometimes sneaky - and a key point in writing correct code is not to out-smart yourself. > > You also don't want mess around cluttering up code for might be a > temporary test. Your code here exists /only/ for a temporary test! Or do you think an empty loop like this is a sensible idea in PC code? > > (Besides, this C code was was auto-generated from my language where the > 'volatile' attribute doesn't exist; it is an artefact only of the C > language. You mean your language is to limited? > > My language tends to do what the programmer tells it to. Well until that > aim is undermined when is has to make use of intermediate C code.) You mean your translator is broken? Your language attempts to give guarantees about what it will do with the program code it is given, but the C code it generates does not provide that guarantee. This is not a fault of C, or the compiler - it is the fault of the person writing the translator. > > (For all its capabilities, on my current project [and at its current > stage], gcc -O3 used for my generated C, only gives me 15% better > performance than my compiler's own native code output, despite the > latter's code generation being rubbish. And I admit that myself. [When > both target x64]) > >
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-03-14 13:37 +0000 |
| Message-ID | <oa8rhm$v8t$1@dont-email.me> |
| In reply to | #106008 |
On 14/03/2017 12:46, David Brown wrote: > On 13/03/17 23:48, BartC wrote: > The programmer /is/ the one calling the shots - but they need to be > called in the C language. In C, an empty loop does nothing Even an non-empty loop can be eliminated; I've found that out plenty of times when trying to benchmark something by simple repetition. >> (Besides, this C code was was auto-generated from my language where the >> 'volatile' attribute doesn't exist; it is an artefact only of the C >> language. > > You mean your language is to limited? It doesn't have 'volatile' because in the decades I was using it (or earlier incarnations) the need never came up. (I believe earlier versions had special means to access hardware i/o ports.) > Apparently things like "sleep" were not practical. I don't know what > the problem might have been, but I assume it also applies to the > functions in <time.h> and and OS-specific functions for timing. sleep() would have been accessed via a wrapper function os_sleep() residing in a module that is specialised for each OS. In this case I was using a 'no-OS' OS-neutral module where os_sleep() would be a no-op. Yes I could have switched things around, but that's making too much of my example: the file was in the editor, I needed a quick way of putting in a delay, and for-loops could have been optimised out. The whole issue is that you have to do something special to ensure that code you write is actually executed. It's not enough just to write code; you have to, perversely, write extra code. > You mean your translator is broken? Your language attempts to give > guarantees about what it will do with the program code it is given, but > the C code it generates does not provide that guarantee. This is not a > fault of C, or the compiler - it is the fault of the person writing the > translator. Imagine a human translator of a novel deciding to omit a chapter because it added nothing to the plot! That is not their role. If I translate my original source to native ASM, then it will do exactly as I intend. But if I write it as C source first, and a C compiler does the translation to native code, then I don't know what bits it's going to chop out. Look at my post in the last hour of issues [C Compilers QoI] compiling a very simple, but large source file. gcc bails out after 30 seconds. But if I run it as gcc -O3, it finishes the job, and in only 7 seconds; fantastic! Then I look at the output .obj file, and it's only 649 bytes, for a 1Mloc source file; something is not right. And that something is that gcc managed to get such a fast timing by shirking the work. (Admittedly it is impressive that it managed to figure out so quickly that it /could/ shirk it! Nevertheless, it is not generating the million multiplies, adds and stores, nor the three million loads, that were intended.) -- bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-14 15:24 +0100 |
| Message-ID | <oa8u8m$8tj$1@dont-email.me> |
| In reply to | #106013 |
On 14/03/17 14:37, BartC wrote: > On 14/03/2017 12:46, David Brown wrote: >> On 13/03/17 23:48, BartC wrote: > >> The programmer /is/ the one calling the shots - but they need to be >> called in the C language. In C, an empty loop does nothing > > Even an non-empty loop can be eliminated; I've found that out plenty of > times when trying to benchmark something by simple repetition. Do you understand about "side effects", "observable behaviour", and the "C abstract machine" ? If not, please read about the terms, or ask questions about them. > >>> (Besides, this C code was was auto-generated from my language where the >>> 'volatile' attribute doesn't exist; it is an artefact only of the C >>> language. >> >> You mean your language is to limited? > > It doesn't have 'volatile' because in the decades I was using it (or > earlier incarnations) the need never came up. > > (I believe earlier versions had special means to access hardware i/o > ports.) > >> Apparently things like "sleep" were not practical. I don't know what >> the problem might have been, but I assume it also applies to the >> functions in <time.h> and and OS-specific functions for timing. > > sleep() would have been accessed via a wrapper function os_sleep() > residing in a module that is specialised for each OS. In this case I was > using a 'no-OS' OS-neutral module where os_sleep() would be a no-op. If there is any point to your language at all, and any reason for supporting more than one OS, then surely it should abstract such functions into an OS-neutral library where such calls actually do what they are supposed to do, and what the user expects them to do, regardless of the OS? When you call "time.sleep()" in Python, you expect the program to sleep for a bit. You - the programmer - don't care whether it calls an OS "sleep" function, or uses functions from <time.h>, or uses six different methods in a row. > > Yes I could have switched things around, but that's making too much of > my example: the file was in the editor, I needed a quick way of putting > in a delay, and for-loops could have been optimised out. > > The whole issue is that you have to do something special to ensure that > code you write is actually executed. It's not enough just to write code; > you have to, perversely, write extra code. Yes - and that "special thing" is "understand how C works". This is /your/ job, as the writer of the translation program. You need to understand how your own language works, and how C works, so that you can generate C code that does what programmer of your own language expects. You cannot do that if you don't know C! As things stand, your translator is about as reliable as Pedro Carolino's famous book: <https://en.wikipedia.org/wiki/English_As_She_Is_Spoke> > >> You mean your translator is broken? Your language attempts to give >> guarantees about what it will do with the program code it is given, but >> the C code it generates does not provide that guarantee. This is not a >> fault of C, or the compiler - it is the fault of the person writing the >> translator. > > Imagine a human translator of a novel deciding to omit a chapter because > it added nothing to the plot! That is not their role. Imagine a human translator who does not understand the target language. > > If I translate my original source to native ASM, then it will do exactly > as I intend. But if I write it as C source first, and a C compiler does > the translation to native code, then I don't know what bits it's going > to chop out. Look, if you understand assembly, translate to assembly. You manage to write /some/ C code - enough to get by for some kinds of programs. But you don't really "get" C - you don't understand how the language works. That is essential for using it as a target language here. > > Look at my post in the last hour of issues [C Compilers QoI] compiling a > very simple, but large source file. gcc bails out after 30 seconds. > > But if I run it as gcc -O3, it finishes the job, and in only 7 seconds; > fantastic! Then I look at the output .obj file, and it's only 649 bytes, > for a 1Mloc source file; something is not right. Something /is/ right - garbage in, garbage out. As I say, you don't understand C. > > And that something is that gcc managed to get such a fast timing by > shirking the work. (Admittedly it is impressive that it managed to > figure out so quickly that it /could/ shirk it! Nevertheless, it is not > generating the million multiplies, adds and stores, nor the three > million loads, that were intended.) > If you intended to do millions of loads and stores, then you have to write C code that expresses it. You did not - you wrote C code that did /nothing/. Worse, it was undefined behaviour.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-03-14 08:25 -0700 |
| Message-ID | <c9ea4a4d-a014-4f67-91da-886f45b68307@googlegroups.com> |
| In reply to | #106023 |
On Tuesday, March 14, 2017 at 9:24:09 AM UTC-5, David Brown wrote: > Look, if you understand assembly, translate to assembly. You manage to > write /some/ C code - enough to get by for some kinds of programs. But > you don't really "get" C - you don't understand how the language works. > That is essential for using it as a target language here. The authors of the C Standard deliberately refrained from mandating that all implementations be suitable for all purposes. Some purposes are best served by mindless translators; others are better served implementations which behave semantically like relatively mindless translators but attempt to do so as efficiently as possible while providing such semantics. Other purposes are better served by more sophisticated compilers which don't support the same low-level semantics which are naturally offered by mindless translators, but can offer better performance for programs that don't require such semantics. It's unfortunate that there is no standard convention by which implementations can report what kinds of semantics they support, but that doesn't mean that "the language" is nothing more than what's described by the Standard. While there isn't a standard for how "mindless translators" should behave, that's largely because it's pretty clear on most platforms how a mindless translators should expose low-level semantics in cases where the Standard imposes no requirements. Nothing in the Standard requires that a compiler for a linear- address machine process "*(uint8_t volatile*)0x12346 = 0x67;" as a byte store of value 0x67 to address 0x12345, but that's because on platforms where there would be only one sensible interpretation the writers of mindless translators are prone to do it whether or not the Standard requires it.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-03-14 17:02 +0100 |
| Message-ID | <oa940v$u27$1@dont-email.me> |
| In reply to | #106034 |
On 14/03/17 16:25, supercat@casperkitty.com wrote: > On Tuesday, March 14, 2017 at 9:24:09 AM UTC-5, David Brown wrote: >> Look, if you understand assembly, translate to assembly. You manage to >> write /some/ C code - enough to get by for some kinds of programs. But >> you don't really "get" C - you don't understand how the language works. >> That is essential for using it as a target language here. > > The authors of the C Standard deliberately refrained from mandating that all > implementations be suitable for all purposes. Some purposes are best served > by mindless translators; others are better served implementations which > behave semantically like relatively mindless translators but attempt to do > so as efficiently as possible while providing such semantics. Other purposes > are better served by more sophisticated compilers which don't support the > same low-level semantics which are naturally offered by mindless translators, > but can offer better performance for programs that don't require such > semantics. Yes, we know you think this - anyone who wasn't paying attention the first few hundred times you said this probably read the last hundred times. Bart is trying to generate C code as the output of his translator for portability purposes. He has to rely on what the C standards say, and how real-life compilers handle the code - he can't rely on mindless translators (which are /never/ the best choice unless the C programmer is mindless). He is under the mistaken impression that avoiding compiler optimisation is a good thing, that it is fast, predictable, and gives correct output for incorrect input.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-03-14 09:45 -0700 |
| Message-ID | <b85ed181-90a6-4ec9-a4a9-7c4c3ea04671@googlegroups.com> |
| In reply to | #106046 |
On Tuesday, March 14, 2017 at 11:02:28 AM UTC-5, David Brown wrote: > Bart is trying to generate C code as the output of his translator for > portability purposes. He has to rely on what the C standards say, and > how real-life compilers handle the code - he can't rely on mindless > translators (which are /never/ the best choice unless the C programmer > is mindless). He is under the mistaken impression that avoiding > compiler optimisation is a good thing, that it is fast, predictable, and > gives correct output for incorrect input. Almost any platform is going to have available a mindless translator or a compiler that can be configured to support the same semantics as one. There isn't any official standard for "mindless translator C", but even in cases where no standard would mandate their behavior, such implementations will almost always do one of a small number of things. If x is a uint32_t and y is 32, even a compiler that behaves as a mindless translator might not behave completely predictably when evaluating x>>y, but if such a compiler is targeting a platform it will do one of two things: yield 0 or yield x. The choice might be made in arbitrary and unpredictable fashion, but in cases where either result would meet requirements, there would be no need to prevent a compiler from making it. If a platform has a mindless translator available, a program that generates source code suitable for use with such a translator will be usable to produce code for that platform, subject to resource constraints. The code might not be suitable for use with some other C compilers targeting that platform, but all that's necessary for C code to be portable to a platform is that it work with one implementation on that platform--not that it work with all of them.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-03-14 09:15 -0700 |
| Message-ID | <lnlgs7kf6h.fsf@kst-u.example.com> |
| In reply to | #106013 |
BartC <bc@freeuk.com> writes:
> On 14/03/2017 12:46, David Brown wrote:
>> On 13/03/17 23:48, BartC wrote:
>> The programmer /is/ the one calling the shots - but they need to be
>> called in the C language. In C, an empty loop does nothing
>
> Even an non-empty loop can be eliminated; I've found that out plenty of
> times when trying to benchmark something by simple repetition.
That's why real-world benchmark programs are carefully written so their
output depends on the result of the computation, so it can't be
optimized away.
If you write:
#include <stdio.h>
int main(void) {
printf("hello");
for (long i = 0; i < 1000000000; i ++) {
}
printf(", world\n");
}
you've specified a loop that iterates a billion times *in
the abstract machine*, but that loop has no visible behavior.
The implementation is free to map the behavior of the abstract
machine to an actual program that simply prints "hello, world\n".
There may be languages that guarantee that a program like this will
take longer to run than a similar program without the loop. C is not
such a language. (Perhaps your language is, or is intended to be.
That's fine, but it means it will take some extra work to map your
language onto C.)
>>> (Besides, this C code was was auto-generated from my language where the
>>> 'volatile' attribute doesn't exist; it is an artefact only of the C
>>> language.
>>
>> You mean your language is to limited?
>
> It doesn't have 'volatile' because in the decades I was using it (or
> earlier incarnations) the need never came up.
I suspect that's because your language effectively treates all objects
as volatile. C doesn't.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-03-14 10:02 -0700 |
| Message-ID | <d71a0025-fc1f-4b38-abf1-2c51c476dd9d@googlegroups.com> |
| In reply to | #106048 |
On Tuesday, March 14, 2017 at 11:15:42 AM UTC-5, Keith Thompson wrote: > That's why real-world benchmark programs are carefully written so their > output depends on the result of the computation, so it can't be > optimized away. If the output doesn't depend upon the values that are input, a compiler could perform all the computations itself and just generate code that outputs the correct answer. Even if the output depends upon the input, a compiler might still be able to recognize that it could replace an algorithm with a more efficient one. For example, if a function is supposed to iterate a 32-bit linear feedback shift register N times, a compiler could calculate a set of 1024 coefficients that would allow the computation to be performed for any N in less than 1,000 steps. If a compiler happens to know how to optimize a linear feedback shift register with some particular polynomial, but not others, then changing a polynomial (which shouldn't have much effect on LFSR performance) could make a program slower by orders of magnitude.
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2017-03-14 20:32 +0000 |
| Message-ID | <eir2amFi6pvU1@mid.uni-berlin.de> |
| In reply to | #106048 |
Keith Thompson <kst-u@mib.org> wrote:
> BartC <bc@freeuk.com> writes:
> >
> > It doesn't have 'volatile' because in the decades I was using it (or
> > earlier incarnations) the need never came up.
> I suspect that's because your language effectively treates all objects
> as volatile. C doesn't.
And the obvious remedy would be to define all variables in the
C code generated by his translator to be volatile qualified.
If he does that, though, we'll have another thread where he'll
whine endlessly about the generated code being much too slow
and that C is a bad language for writing fast programs.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
Page 2 of 6 — ← Prev page 1 [2] 3 4 5 6 Next page →
Back to top | Article view | comp.lang.c
csiph-web