Hello,
I have an issue with the llvm optimizations. I need to create object codes.
the -ON PURPOSE poor && useless- code :
---------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int ci(int a){
	return 23;
}
int flop(int a, char ** c){
	
	a += 71;
	int b = 0;
	if (a == 56){
		b = 69;
		b += ci(a);
	}
	puts("ok");
	return a + b;
}
--------------------------------------
Compiled that way (using the versions I downloaded and eventually compiled) :
clang_custom -std=c11 -O3 -march=native -c app2.c -S
against gcc:
gcc_custom -std=c11 -O3 -march=native -c app2.c -S
Versions (latest for each, downloaded just a few days ago):
gcc : 5.1
clang/llvm: clang+llvm-3.6.1-x86_64-apple-darwin
Host:
osx yosemite.
The assembly (cut to the essential):
LLVM:
	pushq	%rbp
	movq	%rsp, %rbp
	pushq	%r14
	pushq	%rbx
	movl	%edi, %r14d
	leal	71(%r14), %eax
	xorl	%ecx, %ecx
	cmpl	$56, %eax
	movl	$92, %ebx
	cmovnel	%ecx, %ebx
	leaq	L_.str(%rip), %rdi
	callq	_puts
	leal	71(%rbx,%r14), %eax
	popq	%rbx
	popq	%r14
	popq	%rbp
	retq
and the gcc one:
        pushq %rbp
	movl	$0, %eax
	movl	$92, %ebp
	pushq	%rbx
	leal	71(%rdi), %ebx
	leaq	LC1(%rip), %rdi
	subq	$8, %rsp
	cmpl	$56, %ebx
	cmovne	%eax, %ebp
	call	_puts
	addq	$8, %rsp
	leal	0(%rbp,%rbx), %eax
	popq	%rbx
	popq	%rbp
	ret
As we can see, llvm makes poor register allocations (ecx and r14), leading to
more instructions for the same result.
Are there some optimizations I can bring on the table to avoid this ?
-- 
Jog
> On Jul 13, 2015, at 10:03 AM, deco33000 at yandex.com wrote: > > Hello, > > I have an issue with the llvm optimizations. I need to create object codes. > > the -ON PURPOSE poor && useless- code : > --------------------------------------------------- > #include <stdio.h> > #include <stdlib.h> > > int ci(int a){ > > return 23; > > } > int flop(int a, char ** c){ > > a += 71; > > int b = 0; > > if (a == 56){ > > b = 69; > b += ci(a); > } > > puts("ok"); > return a + b; > } > -------------------------------------- > > Compiled that way (using the versions I downloaded and eventually compiled) : > clang_custom -std=c11 -O3 -march=native -c app2.c -S > > against gcc: > gcc_custom -std=c11 -O3 -march=native -c app2.c -S > > Versions (latest for each, downloaded just a few days ago): > gcc : 5.1 > clang/llvm: clang+llvm-3.6.1-x86_64-apple-darwin > > Host: > osx yosemite. > > The assembly (cut to the essential): > > LLVM: > pushq %rbp > movq %rsp, %rbp > pushq %r14 > pushq %rbx > movl %edi, %r14d > leal 71(%r14), %eax > xorl %ecx, %ecx > cmpl $56, %eax > movl $92, %ebx > cmovnel %ecx, %ebx > leaq L_.str(%rip), %rdi > callq _puts > leal 71(%rbx,%r14), %eax > popq %rbx > popq %r14 > popq %rbp > retq > > and the gcc one: > > pushq %rbp > movl $0, %eax > movl $92, %ebp > pushq %rbx > leal 71(%rdi), %ebx > leaq LC1(%rip), %rdi > subq $8, %rsp > cmpl $56, %ebx > cmovne %eax, %ebp > call _puts > addq $8, %rsp > leal 0(%rbp,%rbx), %eax > popq %rbx > popq %rbp > ret > > As we can see, llvm makes poor register allocations (ecx and r14), leading to more instructions for the same result. > > Are there some optimizations I can bring on the table to avoid this ?As far as I know clang on OS X always sets up a frame pointer unless you explicitely use -fomit-frame-pointer. I think the reasoning being that dtrace and others rely on frame pointers being present. I don't see why using %ecx would be a problem, there are no extra spill/reloads produced because of that. - Matthias
<br />Hello, <br />Ecx is a problem because you have to xor it.
Which is avoided in the gcc compilation. Fomit-pointer-frame helps.<br
/><br />Now llvm is one instruction from gcc. If ecx was not used, it
would be as fast.<br />-- <br />Sent from Yandex.Mail for
mobile<br /><br />20:03, 13 July 2015, Matthias Braun
<mbraun@apple.com>:<br /><blockquote><br /><br
/><blockquote>šOn Jul 13, 2015, at 10:03 AM, deco33000@yandex.com
wrote:<br /><br />šHello,<br /><br />šI have an issue
with the llvm optimizations. I need to create object codes.<br /><br
/>šthe -ON PURPOSE poor && useless- code :<br
/>š---------------------------------------------------<br />š#include
<stdio.h><br />š#include <stdlib.h><br /><br
/>šint ci(int a){<br /><br />šššššššššreturn 23;<br
/><br />š}<br />šint flop(int a, char ** c){<br /><br
/>ššššššššša += 71;<br /><br />šššššššššint b = 0;<br
/><br />šššššššššif (a == 56){<br /><br
/>šššššššššššššššššb = 69;<br />šššššššššššššššššb += ci(a);<br
/>ššššššššš}<br /><br />šššššššššputs("ok");<br
/>šššššššššreturn a + b;<br />š}<br
/>š--------------------------------------<br /><br />šCompiled
that way (using the versions I downloaded and eventually compiled) :<br
/>šclang_custom -std=c11 -O3 -march=native -c app2.c -S<br /><br
/>šagainst gcc:<br />šgcc_custom -std=c11 -O3 -march=native -c app2.c
-S<br /><br />šVersions (latest for each, downloaded just a few days
ago):<br />šgcc : 5.1<br />šclang/llvm:
clang+llvm-3.6.1-x86_64-apple-darwin<br /><br />šHost:<br
/>šosx yosemite.<br /><br />šThe assembly (cut to the
essential):<br /><br />šLLVM:<br />šššššššššpushq %rbp<br
/>šššššššššmovq %rsp, %rbp<br />šššššššššpushq %r14<br
/>šššššššššpushq %rbx<br />šššššššššmovl %edi, %r14d<br
/>šššššššššleal 71(%r14), %eax<br />šššššššššxorl %ecx, %ecx<br
/>šššššššššcmpl $56, %eax<br />šššššššššmovl $92, %ebx<br
/>šššššššššcmovnel %ecx, %ebx<br />šššššššššleaq L_.str(%rip),
%rdi<br />šššššššššcallq _puts<br />šššššššššleal 71(%rbx,%r14),
%eax<br />šššššššššpopq %rbx<br />šššššššššpopq %r14<br
/>šššššššššpopq %rbp<br />šššššššššretq<br /><br />šand the
gcc one:<br /><br />ššššššššpushq %rbp<br />šššššššššmovl $0,
%eax<br />šššššššššmovl $92, %ebp<br />šššššššššpushq %rbx<br
/>šššššššššleal 71(%rdi), %ebx<br />šššššššššleaq LC1(%rip), %rdi<br
/>šššššššššsubq $8, %rsp<br />šššššššššcmpl $56, %ebx<br
/>šššššššššcmovne %eax, %ebp<br />šššššššššcall _puts<br
/>šššššššššaddq $8, %rsp<br />šššššššššleal 0(%rbp,%rbx), %eax<br
/>šššššššššpopq %rbx<br />šššššššššpopq %rbp<br
/>šššššššššret<br /><br />šAs we can see, llvm makes poor
register allocations (ecx and r14), leading to more instructions for the same
result.<br /><br />šAre there some optimizations I can bring on the
table to avoid this ?<br /></blockquote><br />As far as I know
clang on OS X always sets up a frame pointer unless you explicitely use
-fomit-frame-pointer. I think the reasoning being that dtrace and others rely on
frame pointers being present.<br /><br />I don't see why using
%ecx would be a problem, there are no extra spill/reloads produced because of
that.<br /><br />- Matthias<br /><br
/></blockquote>
Hi Jog,
This look like a scheduling problem to me.
The main difference here is that in GCC the final “a + b” is scheduled before
the call, whereas in LLVM case, this is scheduled after the call.
Because of that, %rdi cannot be used in the final add and it has to be saved
somewhere else.
You can see that in effect by replacing:
	puts("ok");
	return a + b;
By
        b += a;
	puts("ok");
	return b;
That being said, you shouldn’t have to do that to have the nice code.
Could you file a PR for the scheduling problem?
Thanks,
-Quentin> On Jul 13, 2015, at 10:03 AM, deco33000 at yandex.com wrote:
> 
> Hello,
> 
> I have an issue with the llvm optimizations. I need to create object codes.
> 
> the -ON PURPOSE poor && useless- code :
> ---------------------------------------------------
> #include <stdio.h>
> #include <stdlib.h>
> 
> int ci(int a){
> 
> 	return 23;
> 
> }
> int flop(int a, char ** c){
> 	
> 	a += 71;
> 
> 	int b = 0;
> 
> 	if (a == 56){
> 
> 		b = 69;
> 		b += ci(a);
> 	}
> 
> 	puts("ok");
> 	return a + b;
> }
> --------------------------------------
> 
> Compiled that way (using the versions I downloaded and eventually compiled)
:
> clang_custom -std=c11 -O3 -march=native -c app2.c -S
> 
> against gcc:
> gcc_custom -std=c11 -O3 -march=native -c app2.c -S
> 
> Versions (latest for each, downloaded just a few days ago):
> gcc : 5.1
> clang/llvm: clang+llvm-3.6.1-x86_64-apple-darwin
> 
> Host:
> osx yosemite.
> 
> The assembly (cut to the essential):
> 
> LLVM:
> 	pushq	%rbp
> 	movq	%rsp, %rbp
> 	pushq	%r14
> 	pushq	%rbx
> 	movl	%edi, %r14d
> 	leal	71(%r14), %eax
> 	xorl	%ecx, %ecx
> 	cmpl	$56, %eax
> 	movl	$92, %ebx
> 	cmovnel	%ecx, %ebx
> 	leaq	L_.str(%rip), %rdi
> 	callq	_puts
> 	leal	71(%rbx,%r14), %eax
> 	popq	%rbx
> 	popq	%r14
> 	popq	%rbp
> 	retq
> 
> and the gcc one:
> 
>        pushq %rbp
> 	movl	$0, %eax
> 	movl	$92, %ebp
> 	pushq	%rbx
> 	leal	71(%rdi), %ebx
> 	leaq	LC1(%rip), %rdi
> 	subq	$8, %rsp
> 	cmpl	$56, %ebx
> 	cmovne	%eax, %ebp
> 	call	_puts
> 	addq	$8, %rsp
> 	leal	0(%rbp,%rbx), %eax
> 	popq	%rbx
> 	popq	%rbp
> 	ret
> 
> As we can see, llvm makes poor register allocations (ecx and r14), leading
to more instructions for the same result.
> 
> Are there some optimizations I can bring on the table to avoid this ?
> -- 
> Jog
> 
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
<br />Hi, <br />I certainly will Quentin!<br /><br
/>Thanks<br />-- <br />Sent from Yandex.Mail for mobile<br
/><br />20:10, 13 July 2015, Quentin Colombet
<qcolombet@apple.com>:<br /><blockquote>Hi Jog,<br
/><br />This look like a scheduling problem to me.<br /><br
/>The main difference here is that in GCC the final “a + b” is scheduled
before the call, whereas in LLVM case, this is scheduled after the call.<br
/>Because of that, %rdi cannot be used in the final add and it has to be
saved somewhere else.<br /><br />You can see that in effect by
replacing:<br />        puts("ok");<br />        return a
+ b;<br /><br />By<br /><br />        b += a;<br
/>        puts("ok");<br />        return b;<br
/><br />That being said, you shouldn’t have to do that to have the nice
code.<br /><br />Could you file a PR for the scheduling
problem?<br /><br />Thanks,<br />-Quentin<br /><br
/><blockquote> On Jul 13, 2015, at 10:03 AM, deco33000@yandex.com
wrote:<br /><br /> Hello,<br /><br /> I have an issue
with the llvm optimizations. I need to create object codes.<br /><br
/> the -ON PURPOSE poor && useless- code :<br
/> ---------------------------------------------------<br /> #include
<stdio.h><br /> #include <stdlib.h><br /><br
/> int ci(int a){<br /><br />         return 23;<br
/><br /> }<br /> int flop(int a, char ** c){<br /><br
/>         a += 71;<br /><br />         int b = 0;<br
/><br />         if (a == 56){<br /><br
/>                 b = 69;<br />                 b += ci(a);<br
/>         }<br /><br />         puts("ok");<br
/>         return a + b;<br /> }<br
/> --------------------------------------<br /><br /> Compiled
that way (using the versions I downloaded and eventually compiled) :<br
/> clang_custom -std=c11 -O3 -march=native -c app2.c -S<br /><br
/> against gcc:<br /> gcc_custom -std=c11 -O3 -march=native -c app2.c
-S<br /><br /> Versions (latest for each, downloaded just a few days
ago):<br /> gcc : 5.1<br /> clang/llvm:
clang+llvm-3.6.1-x86_64-apple-darwin<br /><br /> Host:<br
/> osx yosemite.<br /><br /> The assembly (cut to the
essential):<br /><br /> LLVM:<br />         pushq %rbp<br
/>         movq %rsp, %rbp<br />         pushq %r14<br
/>         pushq %rbx<br />         movl %edi, %r14d<br
/>         leal 71(%r14), %eax<br />         xorl %ecx, %ecx<br
/>         cmpl $56, %eax<br />         movl $92, %ebx<br
/>         cmovnel %ecx, %ebx<br />         leaq L_.str(%rip),
%rdi<br />         callq _puts<br />         leal 71(%rbx,%r14),
%eax<br />         popq %rbx<br />         popq %r14<br
/>         popq %rbp<br />         retq<br /><br /> and the
gcc one:<br /><br />        pushq %rbp<br />         movl $0,
%eax<br />         movl $92, %ebp<br />         pushq %rbx<br
/>         leal 71(%rdi), %ebx<br />         leaq LC1(%rip), %rdi<br
/>         subq $8, %rsp<br />         cmpl $56, %ebx<br
/>         cmovne %eax, %ebp<br />         call _puts<br
/>         addq $8, %rsp<br />         leal 0(%rbp,%rbx), %eax<br
/>         popq %rbx<br />         popq %rbp<br
/>         ret<br /><br /> As we can see, llvm makes poor
register allocations (ecx and r14), leading to more instructions for the same
result.<br /><br /> Are there some optimizations I can bring on the
table to avoid this ?<br /> -- <br /> Jog<br /><br
/> _______________________________________________<br /> LLVM
Developers mailing list<br /> LLVMdev@cs.uiuc.edu
http://llvm.cs.uiuc.edu<br
/> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev<br
/></blockquote><br /><br /></blockquote>
By the way Quentin, Your modification makes llvm much faster than gcc (12 ops vs 15 ops): less pushq/popq, better use of the registers.. This code is silly at best but thanks to you I could learn something on llvm. Thanks a lot :) -- Jog