Page 1 of 2
Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 6:47 am
by Casm
Anybody who thinks optimising compilers produce wonderfully efficient code should take a look at this master piece. It was produced by the Visual C compiler:
Code: Select all
video_attribute proc
mov byte ptr [rsp+8], cl
movzx eax, byte ptr [rsp + 8]
mov byte ptr vattrib, al
ret 0
video_attribute endp
Naturally, if I was writing inefficient assembly code by hand, it might look something like:
Code: Select all
video_attribute proc
mov byte ptr vattrib, cl
ret
video_attribute endp
Which is exactly what the original C code does say.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 7:10 am
by Casm
berkus wrote:What optimization level?
/Ot
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 7:59 am
by mitikoro
You don't use C because it's fast; you use C because it's maintainable, flexible and portable. Besides, when you are coding an OS you want to create good code, and then fast code (in that order).
When C isn't fast enough, assembly has its place.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 8:52 am
by Casm
mitikoro wrote:You don't use C because it's fast; you use C because it's maintainable, flexible and portable. Besides, when you are coding an OS you want to create good code, and then fast code (in that order).
When C isn't fast enough, assembly has its place.
I wouldn't describe that as either good or fast. Another thing: We hear that modern compilers pass arguments in registers, rather than on the stack, because it is "faster". And what is the very first thing they seem to do after a function has been called? Store the parameters on the stack - after first making room for them. Presumably the old "slow" method would have been faster.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 9:13 am
by mitikoro
I wouldn't describe that as either good or fast.
I agree. But I am talking about the source code, not about the generated code. Good structure design and fast algorithms make programs fast. IMHO it's easier to design portable and efficient structures in C.
(I think) that code works fine, but if it is a big bottleneck, you can always rewrite it in assembler. And I think the term "optimising compiler" is just marketing
Besides, everybody here profiles his code to find bottlenecks and doesn't trust the compiler.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 9:21 am
by shikhin
Hi,
I'm not sure if I understood the assembly dump correctly, but to me it looks like it is a procedure, video_attribute, which writes a value at vattrib.
If I do the same in gcc, with optimization level 2, it inlines the function, and handles it all in one single assembly instruction. So, I suggest you replace your compiler, or play around with the optimization flags a bit (not sure what whatever flag you chose does).
Regards,
Shikhin
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 9:29 am
by davidv1992
/Ot is only one of a number of options that VC takes for optimizing, and it on it's own seems a little pointless. Furthermore, since you didn't provide context about the function you tried to compile there is really no way of knowing why the compiler would do that. It looks to me like there is some room for improvements in it's register allocater, but it could all just be a weird playing together of factors.
Besides, Microsoft hasn't the best reputation for software performance, so judging all compilers by looking just at theirs may be flawed.
Compiling the following (not particularly efficient) implementation of a function to compute greatest common divisor:
Code: Select all
int gcd(int a, int b)
{
if (a == 0)
return b;
else
return gcd(b%a, a);
}
Gcc given the -O2 flag produces the following code:
Code: Select all
.file "test.c"
.text
.p2align 4,,15
.globl gcd
.type gcd, @function
gcd:
.LFB0:
.cfi_startproc
testl %edi, %edi
movl %esi, %eax
jne .L5
jmp .L8
.p2align 4,,10
.p2align 3
.L4:
movl %edi, %eax
movl %edx, %edi
.L5:
movl %eax, %edx
sarl $31, %edx
idivl %edi
testl %edx, %edx
jne .L4
movl %edi, %eax
ret
.L8:
rep
ret
.cfi_endproc
.LFE0:
.size gcd, .-gcd
.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
.section .note.GNU-stack,"",@progbits
Going over this we immediatly see that it has optimized out all stack access except for the mandatory ret. Giving it a closer look also makes it obvious that it optimized out the tail call into a loop, which is also good for performance, all in all it didn't do that bad, and I for one know that it would take me an awful lot of time to really improve on this.
In almost every practical situation I would choose C/C++ over assembly, you might not be able to reach the same level of efficiency in C as you would in Assembly, but it takes a considerable ammount of skill and time to outperform, and most of us won't have neither the skill nor time required to do it.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 9:34 am
by JAAman
well... first of all, i would have to ask, why you are using invalid switches... that might have something to do with it
... according to MSDN, /Ot is useless without also specifying /Og... which is depreciated -- instead you should be using /O2
WOW... 2 people beat me to the post
edit:
unfortunately, like the previous poster said, we know nothing of the C code used to produce this, nor of the calling code, which would make reasoning hard to do, further, since i am using VCexpress, i cannot test 64bit code generation, so i really cant tell what it would do with valid optimizing switches
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 10:10 am
by bluemoon
Casm wrote:It was produced by the Visual C compiler:
Code: Select all
video_attribute proc
mov byte ptr [rsp+8], cl
movzx eax, byte ptr [rsp + 8]
mov byte ptr vattrib, al
ret 0
video_attribute endp
Naturally, if I was writing inefficient assembly code by hand, it might look something like:
Code: Select all
video_attribute proc
mov byte ptr vattrib, cl
ret
video_attribute endp
So, how often you need the video attribute? If it's so often that it need optimized, vattrib should be a dword but the compiler just cannot change that since you told it to use a byte.
And by the way, nice to save a few trillion-th seconds by scarifying code maintainability.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 11:34 am
by Casm
JAAman wrote:well... first of all, i would have to ask, why you are using invalid switches... that might have something to do with it
... according to MSDN, /Ot is useless without also specifying /Og... which is depreciated -- instead you should be using /O2
WOW... 2 people beat me to the post
edit:
unfortunately, like the previous poster said, we know nothing of the C code used to produce this, nor of the calling code, which would make reasoning hard to do, further, since i am using VCexpress, i cannot test 64bit code generation, so i really cant tell what it would do with valid optimizing switches
The code could hardly be simpler. It provides limited access to a variable which is otherwise only visible within the file:
Code: Select all
void video_attribute(unsigned char attrib)
{
vattrib = attrib;
return;
}
I tried using /O2, but then it started trying to access a static variable through the stack, so I gave up and rewrote part of it in assembly language. It took about ten minutes.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 2:24 pm
by qw
I don't see the point. Why not make "vattrib" public? What variable may be set but not read?
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 3:19 pm
by Casm
Hobbes wrote:I don't see the point. Why not make "vattrib" public? What variable may be set but not read?
An operating system is a large program. To use a geographicl analogy, if something goes wrong in London, it is preferable to be able to assume that the miscreant is to be found in London, or at most Britain, rather than having somebody up to no good remotely, and possibly situated in any part of the world.
Variables should be available to different parts of the operating system on a need to know basis, and in this case that means procedures involved in text output to the screen, and all living within a single file.
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 5:02 pm
by gerryg400
Code: Select all
video_attribute proc
mov byte ptr [rsp+8], cl
movzx eax, byte ptr [rsp + 8]
mov byte ptr vattrib, al
ret 0
video_attribute endp
I don't do much assembly but isn't
overwriting something in the calling function's stack frame ?
Re: Optimising compilers "efficient"?
Posted: Tue Nov 01, 2011 5:45 pm
by Casm
gerryg400 wrote:Code: Select all
video_attribute proc
mov byte ptr [rsp+8], cl
movzx eax, byte ptr [rsp + 8]
mov byte ptr vattrib, al
ret 0
video_attribute endp
I don't do much assembly but isn't
overwriting something in the calling function's stack frame ?
I hadn't thought of that, but at first glance it does look that way. There is no sign of it making room on the stack for anything.
I spent this evening rewriting that entire file in assembler, and guess what - it works now.
Re: Optimising compilers "efficient"?
Posted: Wed Nov 02, 2011 12:52 am
by Solar
If your code doesn't work, it's the fault of your code, not the fault of the language or your toolchain. (Freak chances in the 0.01-per-mille range nonwithstanding.)