Hi,
is there a way to disable loop idiom recognizer in clang?
I have a problem with compiling early stage code for ARM architecture which should not be linked to external libraries but clang replaces loop with memset call in the code.
Thanks,
Damjan
Yep, build with -fno-builtin or -ffreestanding.
-Chris
It doesn't work. According to gcc docs (which clang probably follows):
"GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp."
Did you try it? I'm aware of the requirements for a freestanding implementation.
-Chris
Yes, I tried both. Here is output:
# bin/clang -mcpu=arm926ej-s -Wa,-mcpu=arm926ej-s -ccc-host-triple arm-unknown-freebsd -mfloat-abi=soft -O2 -DKZIP -I. -I/Volumes/data/src/freebsd/sys -ffreestanding -fno-builtin -c /Volumes/data/src/freebsd/sys/kern/inflate.c -o inflate-tramp.o -g
# arm-none-eabi-objdump -S inflate-tramp.o | grep -B 5 -A 2 memset
b58: 85900400 ldrhi r0, [r0, #1024] ; 0x400
b5c: e58d104c str r1, [sp, #76] ; 0x4c
b60: e3a01000 mov r1, #0
b64: 858d0030 strhi r0, [sp, #48] ; 0x30
b68: e24b0064 sub r0, fp, #100 ; 0x64
b6c: ebfffffe bl 0 <memset>
for (i = 0; i < BMAX+1; i++) c [i] = 0;
Hi,
is there a way to disable loop idiom recognizer in clang?
I have a problem with compiling early stage code for ARM architecture which should not be linked to external libraries but clang replaces loop with memset call in the code.
If it is just the loop you care about make the pointer volatile.
Yep, build with -fno-builtin or -ffreestanding.
It doesn't work. According to gcc docs (which clang probably follows):
"GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp."
It works great, you just need your own copies of the functions. That is what we did for ARM EFI firmware, for gcc, clang, and RVCT. https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/ArmPkg/Library/CompilerIntrinsicsLib/Arm/. Sorry no makefiles as they get auto-generated from ../ CompilerIntrinsicsLib.inf. No floating point, but no external libraries means well no external libraries!
Thanks,
Andrew
In my case writing my own functions is slightly overkill for just avoiding clang to convert "for (i = 0; i <17; i++) c [i] = 0;" to memset. Must be a way to tell him not to mess with my loop 
Hi,
is there a way to disable loop idiom recognizer in clang?
I have a problem with compiling early stage code for ARM architecture which should not be linked to external libraries but clang replaces loop with memset call in the code.
If it is just the loop you care about make the pointer volatile.
Yep, build with -fno-builtin or -ffreestanding.
It doesn't work. According to gcc docs (which clang probably follows):
"GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp."
It works great, you just need your own copies of the functions. That is what we did for ARM EFI firmware, for gcc, clang, and RVCT. https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/ArmPkg/Library/CompilerIntrinsicsLib/Arm/. Sorry no makefiles as they get auto-generated from ../ CompilerIntrinsicsLib.inf. No floating point, but no external libraries means well no external libraries!
In my case writing my own functions is slightly overkill for just avoiding clang to convert "for (i = 0; i <17; i++) c [i] = 0;" to memset. Must be a way to tell him not to mess with my loop 
Can you write it in a way that memset conversion logic does not recognize it; such as i =0; for (; i <17; i++) c [i] = 0;
- fariborz
It is too smart 
# arm-none-eabi-objdump -S inflate-tramp.o | grep -B 2 -A 2 memset
b64: 858d0030 strhi r0, [sp, #48] ; 0x30
b68: e24b0064 sub r0, fp, #100 ; 0x64
b6c: ebfffffe bl 0 <memset>
i=0; for (; i < BMAX+1; i++) c [i] = 0;
I would think that should be the case as then similar while-loop constructions would not be optimized either.
Should I fill bug for this or this is just not supported?
# arm-none-eabi-objdump -S inflate-tramp.o | grep -B 5 -A 2 memset
b58: 85900400 ldrhi r0, [r0, #1024] ; 0x400
b5c: e58d104c str r1, [sp, #76] ; 0x4c
b60: e3a01000 mov r1, #0
b64: 858d0030 strhi r0, [sp, #48] ; 0x30
b68: e24b0064 sub r0, fp, #100 ; 0x64
b6c: ebfffffe bl 0 <memset>
for (i = 0; i < BMAX+1; i++) c [i] = 0;
Should I fill bug for this or this is just not supported?
Damjan,
If you think it is a bug write a small example program that shows the problem. Post it to the mailing list and describe how you compiled the test program. Then describe the issue. Also it is good to mention the version of clang you are using. objdump greps are not bug reports folks can act on.
Also you can just clang -S to generate assembler, so you don't need objdump.
Thanks,
Andrew
# arm-none-eabi-objdump -S inflate-tramp.o | grep -B 5 -A 2 memset
b58: 85900400 ldrhi r0, [r0, #1024] ; 0x400
b5c: e58d104c str r1, [sp, #76] ; 0x4c
b60: e3a01000 mov r1, #0
b64: 858d0030 strhi r0, [sp, #48] ; 0x30
b68: e24b0064 sub r0, fp, #100 ; 0x64
b6c: ebfffffe bl 0 <memset>
for (i = 0; i < BMAX+1; i++) c [i] = 0;
Should I fill bug for this or this is just not supported?
Damjan,
If you think it is a bug write a small example program that shows the problem. Post it to the mailing list and describe how you compiled the test program. Then describe the issue. Also it is good to mention the version of clang you are using. objdump greps are not bug reports folks can act on.
I tried to write small c program and -ffreestanding works well. After applying -ffreestanding memset disappears from S.
Unfortunately this is not true for "my" code. I created -E version of my code and uploaded it at [1].
clang version is trunk 129857. Command line is:
# clang -ccc-host-triple arm-unknown-freebsd -O2 -ffreestanding -g -c inflate.c -o inflate.o
Also you can just clang -S to generate assembler, so you don't need objdump.
AFAIK clang -S doesn't intermix source code with assembly.
Thanks,
Andrew
Thanks,
Damjan
[1] http://web.me.com/dmarion/inflate/inflate.c
Use delta to automatically reduce it. You'll need to write a custom
test script, but shouldn't take too long
http://delta.tigris.org/
Here it is:
# clang -ccc-host-triple arm-unknown-freebsd -O2 -ffreestanding -g -c i.c -o i.o
void func1(unsigned *b)
{
unsigned c[17];
unsigned i;
for (i=0; i < 17; i++) c[i] = 0;
do { c[*b]++; b++; } while (--i);
}
will produce memset call even with -ffreestanding.
Ah... that isn't -loop-idiom triggering; that's the loop getting
unrolled and the stores getting merged into a memset by -memcpyopt.
-Eli
Is this expected behavior? If yes how it can be disabled?
Thanks for the testcase, fixed in r130661.
-Chris