[llvm-dev] How to remove memcpy

667 views
Skip to first unread message

Wolfgang McSneed via llvm-dev

unread,
Oct 15, 2016, 6:56:08 PM10/15/16
to llvm...@lists.llvm.org
Hi,

I am hoping that someone can help me figure out how to prevent the insertion of "memcpy" from the assembly source. 

My target is an instruction set simulator that doesn't support this.

Thank you for your valuable time.

Wolf

Here are my compile commands:
$ clang -emit-llvm -fno-builtin -o3 --target=mips -S matrix_float.c -o vl_matrix_float.ll
$ llc vl_matrix_float.ll 

IR File Snip:
  %0 = bitcast [10 x [10 x float]]* %a to i8*
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast ([10 x [10 x float]]* @main.a to i8*), i32 400, i32 4, i1 false)
  %1 = bitcast [10 x [10 x float]]* %b to i8*
  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* bitcast ([10 x [10 x float]]* @main.b to i8*), i32 400, i32 4, i1 false)
  store i32 0, i32* %sum, align 4

Assembly File Snip:

# BB#0:                                 # %entry
lui $2, %hi(_gp_disp)
addiu $2, $2, %lo(_gp_disp)
addiu $sp, $sp, -1664
sw $ra, 1660($sp)          # 4-byte Folded Spill
sw $fp, 1656($sp)          # 4-byte Folded Spill
sw $17, 1652($sp)          # 4-byte Folded Spill
sw $16, 1648($sp)          # 4-byte Folded Spill
move $fp, $sp
addu $17, $2, $25
lw $1, %got($main.a)($17)
addiu $5, $1, %lo($main.a)
lw $25, %call16(memcpy)($17)
addiu $16, $fp, 1248
move $4, $16
addiu $6, $zero, 400
jalr $25
move $gp, $17
lw $1, %got($main.b)($17)
addiu $5, $1, %lo($main.b)
lw $25, %call16(memcpy)($17)
addiu $17, $fp, 848
move $4, $17
jalr $25
addiu $6, $zero, 400
sw $zero, 820($fp)
sw $zero, 844($fp)
addiu $2, $fp, 420
b $BB0_2
addiu $3, $fp, 20
$BB0_1:

Mehdi Amini via llvm-dev

unread,
Oct 15, 2016, 7:01:41 PM10/15/16
to Wolfgang McSneed, llvm...@lists.llvm.org
On Oct 15, 2016, at 3:56 PM, Wolfgang McSneed via llvm-dev <llvm...@lists.llvm.org> wrote:

Hi,

I am hoping that someone can help me figure out how to prevent the insertion of "memcpy" from the assembly source. 

My target is an instruction set simulator that doesn't support this.

Thank you for your valuable time.

Wolf

Here are my compile commands:
$ clang -emit-llvm -fno-builtin -o3 --target=mips -S matrix_float.c -o vl_matrix_float.ll

Technically  -fno-bultin prevents the compiler from understand the memset in the original code. The right option to prevent the compiler from insert libc calls “out-of-the-blue” is -ffreestanding.

However I thought that right now clang does not differentiate these, so your result is somehow strange.
Can you include the matrix_float.c source code?

— 
Mehdi


_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

Joerg Sonnenberger via llvm-dev

unread,
Oct 15, 2016, 7:04:48 PM10/15/16
to llvm...@lists.llvm.org
On Sat, Oct 15, 2016 at 05:56:02PM -0500, Wolfgang McSneed via llvm-dev wrote:
> I am hoping that someone can help me figure out how to prevent the
> insertion of "memcpy" from the assembly source.

Unless your backend explicitly always inlines memcpy, this is expected.
In a lot of situation, creating a libcall for non-trivial sizes is far
preferable than an inlined loop.

Joerg

Joerg Sonnenberger via llvm-dev

unread,
Oct 15, 2016, 7:07:38 PM10/15/16
to llvm...@lists.llvm.org
On Sat, Oct 15, 2016 at 04:01:36PM -0700, Mehdi Amini via llvm-dev wrote:
>
> > On Oct 15, 2016, at 3:56 PM, Wolfgang McSneed via llvm-dev <llvm...@lists.llvm.org> wrote:
> >
> > Hi,
> >
> > I am hoping that someone can help me figure out how to prevent the insertion of "memcpy" from the assembly source.
> >
> > My target is an instruction set simulator that doesn't support this.
> >
> > Thank you for your valuable time.
> >
> > Wolf
> >
> > Here are my compile commands:
> > $ clang -emit-llvm -fno-builtin -o3 --target=mips -S matrix_float.c -o vl_matrix_float.ll
>
> Technically -fno-bultin prevents the compiler from understand the
> memset in the original code. The right option to prevent the compiler
> from insert libc calls “out-of-the-blue” is -ffreestanding.

Huh? The -fno-builtin is not the problem. The compiler is *expected* to
call certain functions even for -ffreestanding. memcpy and memset are
two of those. It is certainly perfectly valid target lowering for
llvm.memcpy to be turned back into a libcall.

Joerg

Wolfgang McSneed via llvm-dev

unread,
Oct 15, 2016, 7:10:10 PM10/15/16
to Joerg Sonnenberger, llvm...@lists.llvm.org
Hi Mehdi and Joerg,

Thanks for your fast response! attached is the matrix_float.c file.

Also - I should point out that I am using MIPS ISS.

Thanks,

Wolf

Kind Regards,

Wolf
matrix_float.c

Flamedoge via llvm-dev

unread,
Oct 15, 2016, 7:12:20 PM10/15/16
to Wolfgang McSneed, llvm-dev
Even with -ffreestanding LLVM generates memcpy/memset? Does this mean some passes do not honor this flag? If you really wanted to prevent libcalls, you could technically translate those memcpy/memset to loops in lowering.
Kevin

Joerg Sonnenberger via llvm-dev

unread,
Oct 15, 2016, 7:12:46 PM10/15/16
to llvm...@lists.llvm.org
On Sat, Oct 15, 2016 at 06:10:05PM -0500, Wolfgang McSneed wrote:
> Thanks for your fast response! attached is the matrix_float.c file.

Are you intentionally not using static (& const) arrays? The compiler has
to use a copy to initialize a & b, given the size, it will use a memcpy
from a read-only section for that.

Mehdi Amini via llvm-dev

unread,
Oct 15, 2016, 7:16:31 PM10/15/16
to Joerg Sonnenberger, llvm...@lists.llvm.org
On Oct 15, 2016, at 4:07 PM, Joerg Sonnenberger via llvm-dev <llvm...@lists.llvm.org> wrote:

On Sat, Oct 15, 2016 at 04:01:36PM -0700, Mehdi Amini via llvm-dev wrote:

On Oct 15, 2016, at 3:56 PM, Wolfgang McSneed via llvm-dev <llvm...@lists.llvm.org> wrote:

Hi,

I am hoping that someone can help me figure out how to prevent the insertion of "memcpy" from the assembly source. 

My target is an instruction set simulator that doesn't support this.

Thank you for your valuable time.

Wolf

Here are my compile commands:
$ clang -emit-llvm -fno-builtin -o3 --target=mips -S matrix_float.c -o vl_matrix_float.ll

Technically  -fno-bultin prevents the compiler from understand the
memset in the original code. The right option to prevent the compiler
from insert libc calls “out-of-the-blue” is -ffreestanding.

Huh? The -fno-builtin is not the problem.

I’m not sure what you mean by “it is not the problem” or how it relate to what I wrote.

Many people use -fno-builtin thinking it’ll prevent the compiler from calling memset. I’m pointing this isn’t true (the command line he posted includes -fno-builtin).


The compiler is *expected* to
call certain functions even for -ffreestanding. memcpy and memset are
two of those. It is certainly perfectly valid target lowering for
llvm.memcpy to be turned back into a libcall.

Source?
AFAICT this is GCC behavior, but not the standard: https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Standards


— 
Mehdi



Joerg Sonnenberger via llvm-dev

unread,
Oct 15, 2016, 7:17:50 PM10/15/16
to llvm-dev
On Sat, Oct 15, 2016 at 04:12:15PM -0700, Flamedoge wrote:
> Even with -ffreestanding LLVM generates memcpy/memset? Does this mean some
> passes do not honor this flag? If you really wanted to prevent libcalls,
> you could technically translate those memcpy/memset to loops in lowering.
> Kevin

Yes, LLVM follows the same rules as GCC here:

GCC requires the freestanding environment provide `memcpy', `memmove',
`memset' and `memcmp'.

As I said, target lowering may decide to inline all the llvm.mem*
intrinsics, but it is typically wasteful to do so. Exceptions are e.g.
on x86 when optimising for size, since the function call overhead is
large than the "rep stosb" sequence would be for memset or "rep movsb"
or memcpy.

Wolfgang McSneed via llvm-dev

unread,
Oct 15, 2016, 7:18:53 PM10/15/16
to Joerg Sonnenberger, llvm...@lists.llvm.org
No, there is no reason that can't be static. How do you recommend that I define them?

THanks!

Kind Regards,

Wolf

Wolfgang McSneed via llvm-dev

unread,
Oct 15, 2016, 7:20:24 PM10/15/16
to Joerg Sonnenberger, llvm-dev
Also - I tried both -fno-builtin and  -ffreestanding and code with memcpy was still produced.



Kind Regards,

Wolf

Joerg Sonnenberger via llvm-dev

unread,
Oct 15, 2016, 7:22:28 PM10/15/16
to llvm...@lists.llvm.org
On Sat, Oct 15, 2016 at 06:18:48PM -0500, Wolfgang McSneed wrote:
> No, there is no reason that can't be static. How do you recommend that I
> define them?

Just make them static const, so that a & b are effectively read-only
global variables. That way, the function doesn't have to reinitialize
them all the time.

Wolfgang McSneed via llvm-dev

unread,
Oct 15, 2016, 7:25:26 PM10/15/16
to Joerg Sonnenberger, llvm-dev
That worked!

Thank you for your time!

Kind Regards,

Wolf

Joerg Sonnenberger via llvm-dev

unread,
Oct 15, 2016, 7:26:37 PM10/15/16
to llvm...@lists.llvm.org
On Sat, Oct 15, 2016 at 04:16:25PM -0700, Mehdi Amini wrote:
> >> Technically -fno-bultin prevents the compiler from understand the
> >> memset in the original code. The right option to prevent the compiler
> >> from insert libc calls “out-of-the-blue” is -ffreestanding.
> >
> > Huh? The -fno-builtin is not the problem.
>
> I’m not sure what you mean by “it is not the problem” or how it relate to what I wrote.
>
> Many people use -fno-builtin thinking it’ll prevent the compiler from
> calling memset. I’m pointing this isn’t true (the command line he
> posted includes -fno-builtin).

The original code contains no memset (nor memcpy). As such, -fno-builtin
does not change the interpretation of the program as far as lowering to
IR goes. The backend using memset internally is a completely unrelated
problem.


> > The compiler is *expected* to
> > call certain functions even for -ffreestanding. memcpy and memset are
> > two of those. It is certainly perfectly valid target lowering for
> > llvm.memcpy to be turned back into a libcall.
>
> Source?
> AFAICT this is GCC behavior, but not the standard:
> https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Standards

The standard has almost nothing to say about how freestanding really
works. It has a few requirements on what must be working in freestanding
environments, but the precise contract of what the compiler expects as
part of the ABI is outside the scope of the standard. Helper functions
for implementing division in software certainly fall into this scope as
well. The second-to-last paragraph are the lines about requirements GCC
puts on the environment, the same essentially applies to LLVM.

Reply all
Reply to author
Forward
0 new messages