disabling loop idiom recognizer in clang

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 :slight_smile:

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 :slight_smile:

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 :slight_smile:

# 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