Johannes Doerfert via llvm-dev
2021-Feb-24 00:18 UTC
[llvm-dev] How to recover function parameter Value* when -O2 active
On 2/23/21 6:08 PM, K Jelesnianski wrote:> Thank you so much for your reply! > > I want my pass to run as late as possible to not be messed up by any of the > regular internal optimizations. I need a reference of i32 %b (regularly we > see this in IR as i32* %b) so if I understand you I think I need an > indirection. > In that case is it safe to just create an AllocaInst ? Does adding the > AllocaInst effect the way the data flows between functions? > > The reason I am saying this is: Following my above example code, assuming I > am interested in the local variable "m" declared and set in main() (so a > memory slot dedicated for "m" is created in the stack, right?), "m" is > passed to foo(m), nothing is altered, "m" is further passed to bar(). > If I created the AllocaInst in bar and assign %b to it, will I be creating > a new stack memory slot for bar's Argument "b" and will then I be passing > in the memory address of "b" (context of bar()) and not "m" (context of > main()). > > I want to, if possible, pass the stack address of "m" (from the context of > main) to my profiling function call that is currently in the context of > bar().Your code *does not* pass the address of `m` in `main` to `foo`. It passes `m` by value to `foo`, thus the argument `b`is a copy of `m` if you want. You cannot recover the address of `m` in `foo` by any legal means. In fact, the optimizer will realize there is no need for stack allocations and put both `m` and `b` into (virtual) registers instead. If you want to trace a stack allocation, trace it early. If you "wait" and it is remove because it was not observed/ needed, it's gone for good. For your code, change it to: void foo(int *bptr) { int b = *bptr; ... } void main(...) { ... *m = ... ... foo(&m); } and then you can profile the `i32* %bptr` argument of foo which is the "stack" address of `m` in `main`. ~ Johannes> On Tue, Feb 23, 2021 at 6:19 PM Johannes Doerfert < > johannesdoerfert at gmail.com> wrote: > >> If you want to access the `llvm::AllocaInst` generated by Clang for >> the argument you should run your pass early in the pipeline. If you >> just want to see the value passed to `bar`, take the `llvm::Argument` >> and pass it to your profiling function. If you need indirection for >> some reason, create a new `llvm::AllocaInst`, store the `llvm::Argument` >> you are interested in in it, and pass the `llvm::AllocaInst` to your >> function. >> >> I hope this helps. >> >> ~ Johannes >> >> >> On 2/23/21 3:19 PM, K Jelesnianski via llvm-dev wrote: >>> Dear LLVM mailing list, >>> >>> I am currently having difficulty with figuring out how to get a function >>> parameter Value* when I am compiling with -O2. It seems -O2 performs an >>> optimization that optimizes out the local variable formed for the >> function >>> parameter. >>> I have a pass where I am inserting new function calls, and need to pass >> the >>> function parameters variable address. With -O0 this issue does not come >> up >>> as each function parameter when using -O0 gets its own AllocaInst and I >> can >>> leverage that Value* to pass to my new function call. I have tried to >>> leverage llvm.dbg information but it seems LLVM is not inserting >>> llvm.dbg.addr for me to use. >>> >>> Below is the code example I am working with: >>> /* example.c */ >>> int fd_in; >>> char* ut_addr; >>> >>> __attribute__((noinline)) void bar (int b){ >>> my_pass_function( &b ); // NEW (what I want to be done by my >> pass) >>> ut_addr = (char*) mmap( 0, b, my_prot, MAP_PRIVATE, fd_in, 0); >>> } >>> >>> __attribute__((noinline)) void foo (int f){ >>> bar( f ); >>> } >>> >>> int main(int argc, char** argv){ >>> int m; >>> struct stat statbuf; >>> char *input; >>> >>> if( (fd_in = open ( input, O_RDONLY)) < 0){ /* open the >>> input file */ >>> return 0; >>> } >>> if( fstat( fd_in , &statbuf ) < 0 ){ /* find size of >> input >>> file */ >>> return 0; >>> } >>> >>> m = statbuf.st_size; >>> foo( m ); >>> return 0; >>> } >>> ----------------------------------------------------------------- >>> The original IR I get for bar() is below, as you can see the function >>> parameter is the "raw" value "i32 %b" passed into the function and not a >>> variable that I can leverage, get its Value* . Hence when I run my newly >>> instrumented code, I get a segmentation fault. >>> >>> define void @bar(i32 %b) local_unnamed_addr #0 !dbg !35 { >>> entry: >>> call void @llvm.dbg.value(metadata i32 %b, metadata !39, metadata >>> !DIExpression()), !dbg !44 >>> call void @llvm.dbg.value(metadata i64 1000, metadata !40, metadata >>> !DIExpression()), !dbg !44 >>> call void @llvm.dbg.value(metadata i32 1, metadata !43, metadata >>> !DIExpression()), !dbg !44 >>> %conv = sext i32 %b to i64, !dbg !45 >>> %0 = load i32, i32* @fd_in, align 4, !dbg !46, !tbaa !47 >>> %call = tail call i8* @mmap(i8* null, i64 %conv, i32 1, i32 2, i32 %0, >>> i64 0) #7, !dbg !51 >>> store i8* %call, i8** @ut_addr, align 8, !dbg !52, !tbaa !53 >>> ret void, !dbg !55 >>> } >>> >>> >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
K Jelesnianski via llvm-dev
2021-Feb-24 00:33 UTC
[llvm-dev] How to recover function parameter Value* when -O2 active
Ah makes sense completely, I forgot about it being pass by value. Thanks again for clearing this up. Also unrelated but: I just discovered LLVM has its own discord and I posted my question there first, is it popular? Or is mailing list still more responsive? On Tue, Feb 23, 2021 at 7:18 PM Johannes Doerfert < johannesdoerfert at gmail.com> wrote:> > On 2/23/21 6:08 PM, K Jelesnianski wrote: > > Thank you so much for your reply! > > > > I want my pass to run as late as possible to not be messed up by any of > the > > regular internal optimizations. I need a reference of i32 %b (regularly > we > > see this in IR as i32* %b) so if I understand you I think I need an > > indirection. > > In that case is it safe to just create an AllocaInst ? Does adding the > > AllocaInst effect the way the data flows between functions? > > > > The reason I am saying this is: Following my above example code, > assuming I > > am interested in the local variable "m" declared and set in main() (so a > > memory slot dedicated for "m" is created in the stack, right?), "m" is > > passed to foo(m), nothing is altered, "m" is further passed to bar(). > > If I created the AllocaInst in bar and assign %b to it, will I be > creating > > a new stack memory slot for bar's Argument "b" and will then I be passing > > in the memory address of "b" (context of bar()) and not "m" (context of > > main()). > > > > I want to, if possible, pass the stack address of "m" (from the context > of > > main) to my profiling function call that is currently in the context of > > bar(). > > Your code *does not* pass the address of `m` in `main` to `foo`. > It passes `m` by value to `foo`, thus the argument `b`is a copy > of `m` if you want. You cannot recover the address of `m` in `foo` > by any legal means. In fact, the optimizer will realize there is > no need for stack allocations and put both `m` and `b` into (virtual) > registers instead. If you want to trace a stack allocation, trace > it early. If you "wait" and it is remove because it was not observed/ > needed, it's gone for good. > > For your code, change it to: > > void foo(int *bptr) { int b = *bptr; ... } > void main(...) { > ... > *m = ... > ... > foo(&m); > } > > and then you can profile the `i32* %bptr` argument of foo which is > the "stack" address of `m` in `main`. > > ~ Johannes > > > > > On Tue, Feb 23, 2021 at 6:19 PM Johannes Doerfert < > > johannesdoerfert at gmail.com> wrote: > > > >> If you want to access the `llvm::AllocaInst` generated by Clang for > >> the argument you should run your pass early in the pipeline. If you > >> just want to see the value passed to `bar`, take the `llvm::Argument` > >> and pass it to your profiling function. If you need indirection for > >> some reason, create a new `llvm::AllocaInst`, store the `llvm::Argument` > >> you are interested in in it, and pass the `llvm::AllocaInst` to your > >> function. > >> > >> I hope this helps. > >> > >> ~ Johannes > >> > >> > >> On 2/23/21 3:19 PM, K Jelesnianski via llvm-dev wrote: > >>> Dear LLVM mailing list, > >>> > >>> I am currently having difficulty with figuring out how to get a > function > >>> parameter Value* when I am compiling with -O2. It seems -O2 performs an > >>> optimization that optimizes out the local variable formed for the > >> function > >>> parameter. > >>> I have a pass where I am inserting new function calls, and need to pass > >> the > >>> function parameters variable address. With -O0 this issue does not come > >> up > >>> as each function parameter when using -O0 gets its own AllocaInst and I > >> can > >>> leverage that Value* to pass to my new function call. I have tried to > >>> leverage llvm.dbg information but it seems LLVM is not inserting > >>> llvm.dbg.addr for me to use. > >>> > >>> Below is the code example I am working with: > >>> /* example.c */ > >>> int fd_in; > >>> char* ut_addr; > >>> > >>> __attribute__((noinline)) void bar (int b){ > >>> my_pass_function( &b ); // NEW (what I want to be done by my > >> pass) > >>> ut_addr = (char*) mmap( 0, b, my_prot, MAP_PRIVATE, fd_in, 0); > >>> } > >>> > >>> __attribute__((noinline)) void foo (int f){ > >>> bar( f ); > >>> } > >>> > >>> int main(int argc, char** argv){ > >>> int m; > >>> struct stat statbuf; > >>> char *input; > >>> > >>> if( (fd_in = open ( input, O_RDONLY)) < 0){ /* open > the > >>> input file */ > >>> return 0; > >>> } > >>> if( fstat( fd_in , &statbuf ) < 0 ){ /* find size of > >> input > >>> file */ > >>> return 0; > >>> } > >>> > >>> m = statbuf.st_size; > >>> foo( m ); > >>> return 0; > >>> } > >>> ----------------------------------------------------------------- > >>> The original IR I get for bar() is below, as you can see the function > >>> parameter is the "raw" value "i32 %b" passed into the function and not > a > >>> variable that I can leverage, get its Value* . Hence when I run my > newly > >>> instrumented code, I get a segmentation fault. > >>> > >>> define void @bar(i32 %b) local_unnamed_addr #0 !dbg !35 { > >>> entry: > >>> call void @llvm.dbg.value(metadata i32 %b, metadata !39, metadata > >>> !DIExpression()), !dbg !44 > >>> call void @llvm.dbg.value(metadata i64 1000, metadata !40, metadata > >>> !DIExpression()), !dbg !44 > >>> call void @llvm.dbg.value(metadata i32 1, metadata !43, metadata > >>> !DIExpression()), !dbg !44 > >>> %conv = sext i32 %b to i64, !dbg !45 > >>> %0 = load i32, i32* @fd_in, align 4, !dbg !46, !tbaa !47 > >>> %call = tail call i8* @mmap(i8* null, i64 %conv, i32 1, i32 2, i32 > %0, > >>> i64 0) #7, !dbg !51 > >>> store i8* %call, i8** @ut_addr, align 8, !dbg !52, !tbaa !53 > >>> ret void, !dbg !55 > >>> } > >>> > >>> > >>> _______________________________________________ > >>> LLVM Developers mailing list > >>> llvm-dev at lists.llvm.org > >>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210223/71239394/attachment.html>