Strahinja Petrovic via llvm-dev
2016-Mar-17 11:10 UTC
[llvm-dev] Problem with __builtin_object_size when it depends on a condition
I made a mistake here, I get zero same as you. I want to fix it to get correct value. On 16.03.2016. 19:28, Duncan P. N. Exon Smith wrote:>> On 2016-Mar-16, at 09:39, Strahinja Petrovic via llvm-dev <llvm-dev at lists.llvm.org> wrote: >> >> Optimizer doesn't know how to calculate the object size when it finds condition that cannot be eliminated. There is example: >> >> ----------------------------------------------- >> #include<stdlib.h> >> #define STATIC_BUF_SIZE 10 >> #define LARGER_BUF_SIZE 30 >> >> size_t foo(int flag) { >> char *cptr; >> char chararray[LARGER_BUF_SIZE]; >> char chararray2[STATIC_BUF_SIZE]; >> if(flag) >> cptr = chararray2; >> else >> cptr = chararray; >> >> return __builtin_object_size(cptr, 2); >> } >> >> int main() { >> size_t ret; >> ret = foo(0); >> printf("\n%d\n", ret); >> return 0; >> } >> ---------------------------------------------- >> If you try to compile this example with clang (trunk version) with option -fno-inline the result will be -1. > I get `0` when I run this, which is correct because you're asking > for type "2". `-1` would be a fairly major bug. Was this a typo > on your part, or can you somehow reproduce `-1`? > >> Without option -fno-inline result will be correct (30). When foo function is inlined into main, condition is eliminated and compiler knows to calculate correct object size. Compiler should be able to calculate object size in both cases (with/without inlining foo function). In case when condition can't be eliminated compiler should calculate object size depending on second argument of __builtin_object_size function (taking minimum or maximum value from condition). In this example, the result should be 10 with -fno-inline. >> >> If I replace the llvm.objectsize with the constant in foo() depending on the second argument, the result will be correct with -fno-inline (10), but incorrect without the flag. This is because foo() is inlined, the condition can be eliminated, and the result should be 30. >> >> I resolved this problem by adding third argument in llvm.objectsize intrinsic. When I calculate the result based on condition, I put it in the third argument. If there is no inlining, condition will not get eliminated, and this will be the final result. When there is inlining, condition will be eliminated after inlining and the llvm.objectsize will be replaced with a constant. >> With this approach, I get the correct result in both cases (with and without -fno-inline). >> >> I would like to have a discussion about this approach because I am changing the IR (because of adding third argument to __builtin_object_size function). Do you have some comments ? >> >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Duncan P. N. Exon Smith via llvm-dev
2016-Mar-17 17:01 UTC
[llvm-dev] Problem with __builtin_object_size when it depends on a condition
Okay, good. FTR, 0 *is* a correct value. You want to fix it to get a more accurate number, but 0 is always correct for type 2.> On 2016-Mar-17, at 04:10, Strahinja Petrovic <strahinja.petrovic at rt-rk.com> wrote: > > I made a mistake here, I get zero same as you. I want to fix it to get correct value. > > On 16.03.2016. 19:28, Duncan P. N. Exon Smith wrote: >>> On 2016-Mar-16, at 09:39, Strahinja Petrovic via llvm-dev <llvm-dev at lists.llvm.org> wrote: >>> >>> Optimizer doesn't know how to calculate the object size when it finds condition that cannot be eliminated. There is example: >>> >>> ----------------------------------------------- >>> #include<stdlib.h> >>> #define STATIC_BUF_SIZE 10 >>> #define LARGER_BUF_SIZE 30 >>> >>> size_t foo(int flag) { >>> char *cptr; >>> char chararray[LARGER_BUF_SIZE]; >>> char chararray2[STATIC_BUF_SIZE]; >>> if(flag) >>> cptr = chararray2; >>> else >>> cptr = chararray; >>> >>> return __builtin_object_size(cptr, 2); >>> } >>> >>> int main() { >>> size_t ret; >>> ret = foo(0); >>> printf("\n%d\n", ret); >>> return 0; >>> } >>> ---------------------------------------------- >>> If you try to compile this example with clang (trunk version) with option -fno-inline the result will be -1. >> I get `0` when I run this, which is correct because you're asking >> for type "2". `-1` would be a fairly major bug. Was this a typo >> on your part, or can you somehow reproduce `-1`? >> >>> Without option -fno-inline result will be correct (30). When foo function is inlined into main, condition is eliminated and compiler knows to calculate correct object size. Compiler should be able to calculate object size in both cases (with/without inlining foo function). In case when condition can't be eliminated compiler should calculate object size depending on second argument of __builtin_object_size function (taking minimum or maximum value from condition). In this example, the result should be 10 with -fno-inline. >>> >>> If I replace the llvm.objectsize with the constant in foo() depending on the second argument, the result will be correct with -fno-inline (10), but incorrect without the flag. This is because foo() is inlined, the condition can be eliminated, and the result should be 30. >>> >>> I resolved this problem by adding third argument in llvm.objectsize intrinsic. When I calculate the result based on condition, I put it in the third argument. If there is no inlining, condition will not get eliminated, and this will be the final result. When there is inlining, condition will be eliminated after inlining and the llvm.objectsize will be replaced with a constant. >>> With this approach, I get the correct result in both cases (with and without -fno-inline). >>> >>> I would like to have a discussion about this approach because I am changing the IR (because of adding third argument to __builtin_object_size function). Do you have some comments ? >>> >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >
George Burgess IV via llvm-dev
2016-Mar-17 21:59 UTC
[llvm-dev] Problem with __builtin_object_size when it depends on a condition
Ahh, that makes much more sense then; thanks for the detailed illustration. :) Though, in your example: *** IR Dump After Partially inline calls to library functions *** ; Function Attrs: nounwind readnone uwtable define i64 @foo(i32 %flag) #0 { entry: %chararray = alloca [30 x i8], align 16 %chararray2 = alloca [10 x i8], align 1 %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64 0, i64 0 call void @llvm.lifetime.start(i64 30, i8* %0) #5 %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64 0, i64 0 call void @llvm.lifetime.start(i64 10, i8* %1) #5 %tobool = icmp eq i32 %flag, 0 %cptr.0 = select i1 %tobool, i8* %0, i8* %1 %2 = call i64 @llvm.objectsize.i64.p0i8.i32(i8* %cptr.0, i1 true, i32 10) call void @llvm.lifetime.end(i64 10, i8* %1) #5 call void @llvm.lifetime.end(i64 30, i8* %0) #5 ret i64 %2 } Why is the third argument to @llvm.objectsize necessary? It seems that we have enough information to just compute "10" during CGP. Are there cases where we wouldn't be able to do this? On Thu, Mar 17, 2016 at 10:01 AM, Duncan P. N. Exon Smith via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Okay, good. > > FTR, 0 *is* a correct value. You want to fix it to get a more accurate > number, but 0 is always correct for type 2. > > > On 2016-Mar-17, at 04:10, Strahinja Petrovic < > strahinja.petrovic at rt-rk.com> wrote: > > > > I made a mistake here, I get zero same as you. I want to fix it to get > correct value. > > > > On 16.03.2016. 19:28, Duncan P. N. Exon Smith wrote: > >>> On 2016-Mar-16, at 09:39, Strahinja Petrovic via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >>> > >>> Optimizer doesn't know how to calculate the object size when it finds > condition that cannot be eliminated. There is example: > >>> > >>> ----------------------------------------------- > >>> #include<stdlib.h> > >>> #define STATIC_BUF_SIZE 10 > >>> #define LARGER_BUF_SIZE 30 > >>> > >>> size_t foo(int flag) { > >>> char *cptr; > >>> char chararray[LARGER_BUF_SIZE]; > >>> char chararray2[STATIC_BUF_SIZE]; > >>> if(flag) > >>> cptr = chararray2; > >>> else > >>> cptr = chararray; > >>> > >>> return __builtin_object_size(cptr, 2); > >>> } > >>> > >>> int main() { > >>> size_t ret; > >>> ret = foo(0); > >>> printf("\n%d\n", ret); > >>> return 0; > >>> } > >>> ---------------------------------------------- > >>> If you try to compile this example with clang (trunk version) with > option -fno-inline the result will be -1. > >> I get `0` when I run this, which is correct because you're asking > >> for type "2". `-1` would be a fairly major bug. Was this a typo > >> on your part, or can you somehow reproduce `-1`? > >> > >>> Without option -fno-inline result will be correct (30). When foo > function is inlined into main, condition is eliminated and compiler knows > to calculate correct object size. Compiler should be able to calculate > object size in both cases (with/without inlining foo function). In case > when condition can't be eliminated compiler should calculate object size > depending on second argument of __builtin_object_size function (taking > minimum or maximum value from condition). In this example, the result > should be 10 with -fno-inline. > >>> > >>> If I replace the llvm.objectsize with the constant in foo() depending > on the second argument, the result will be correct with -fno-inline (10), > but incorrect without the flag. This is because foo() is inlined, the > condition can be eliminated, and the result should be 30. > >>> > >>> I resolved this problem by adding third argument in llvm.objectsize > intrinsic. When I calculate the result based on condition, I put it in the > third argument. If there is no inlining, condition will not get eliminated, > and this will be the final result. When there is inlining, condition will > be eliminated after inlining and the llvm.objectsize will be replaced with > a constant. > >>> With this approach, I get the correct result in both cases (with and > without -fno-inline). > >>> > >>> I would like to have a discussion about this approach because I am > changing the IR (because of adding third argument to __builtin_object_size > function). Do you have some comments ? > >>> > >>> _______________________________________________ > >>> LLVM Developers mailing list > >>> llvm-dev at lists.llvm.org > >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://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/20160317/d233eefc/attachment.html>
Strahinja Petrovic via llvm-dev
2016-Mar-18 17:52 UTC
[llvm-dev] Problem with __builtin_object_size when it depends on a condition
Well, I think I can do that part how you said (calculate "10" during CGP). When I finish the patch I will post it on phabricator. Thanks for comments. On 17.03.2016. 22:59, George Burgess IV wrote: Ahh, that makes much more sense then; thanks for the detailed illustration. :/) / Though, in your example: *** IR Dump After Partially inline calls to library functions *** ; Function Attrs: nounwind readnone uwtable define i64 @foo(i32 %flag) #0 { entry: %chararray = alloca [30 x i8], align 16 %chararray2 = alloca [10 x i8], align 1 %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64 0, i64 0 call void @llvm.lifetime.start(i64 30, i8* %0) #5 %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64 0, i64 0 call void @llvm.lifetime.start(i64 10, i8* %1) #5 %tobool = icmp eq i32 %flag, 0 %cptr.0 = select i1 %tobool, i8* %0, i8* %1 %2 = call i64 @llvm.objectsize.i64.p0i8.i32(i8* %cptr.0, i1 true, i32 10) call void @llvm.lifetime.end(i64 10, i8* %1) #5 call void @llvm.lifetime.end(i64 30, i8* %0) #5 ret i64 %2 } Why is the third argument to @llvm.objectsize necessary? It seems that we have enough information to just compute "10" during CGP. Are there cases where we wouldn't be able to do this? On 17.03.2016. 18:01, Duncan P. N. Exon Smith wrote:> Okay, good. > > FTR, 0 *is* a correct value. You want to fix it to get a more accurate > number, but 0 is always correct for type 2. > >> On 2016-Mar-17, at 04:10, Strahinja Petrovic <strahinja.petrovic at rt-rk.com> wrote: >> >> I made a mistake here, I get zero same as you. I want to fix it to get correct value. >> >> On 16.03.2016. 19:28, Duncan P. N. Exon Smith wrote: >>>> On 2016-Mar-16, at 09:39, Strahinja Petrovic via llvm-dev <llvm-dev at lists.llvm.org> wrote: >>>> >>>> Optimizer doesn't know how to calculate the object size when it finds condition that cannot be eliminated. There is example: >>>> >>>> ----------------------------------------------- >>>> #include<stdlib.h> >>>> #define STATIC_BUF_SIZE 10 >>>> #define LARGER_BUF_SIZE 30 >>>> >>>> size_t foo(int flag) { >>>> char *cptr; >>>> char chararray[LARGER_BUF_SIZE]; >>>> char chararray2[STATIC_BUF_SIZE]; >>>> if(flag) >>>> cptr = chararray2; >>>> else >>>> cptr = chararray; >>>> >>>> return __builtin_object_size(cptr, 2); >>>> } >>>> >>>> int main() { >>>> size_t ret; >>>> ret = foo(0); >>>> printf("\n%d\n", ret); >>>> return 0; >>>> } >>>> ---------------------------------------------- >>>> If you try to compile this example with clang (trunk version) with option -fno-inline the result will be -1. >>> I get `0` when I run this, which is correct because you're asking >>> for type "2". `-1` would be a fairly major bug. Was this a typo >>> on your part, or can you somehow reproduce `-1`? >>> >>>> Without option -fno-inline result will be correct (30). When foo function is inlined into main, condition is eliminated and compiler knows to calculate correct object size. Compiler should be able to calculate object size in both cases (with/without inlining foo function). In case when condition can't be eliminated compiler should calculate object size depending on second argument of __builtin_object_size function (taking minimum or maximum value from condition). In this example, the result should be 10 with -fno-inline. >>>> >>>> If I replace the llvm.objectsize with the constant in foo() depending on the second argument, the result will be correct with -fno-inline (10), but incorrect without the flag. This is because foo() is inlined, the condition can be eliminated, and the result should be 30. >>>> >>>> I resolved this problem by adding third argument in llvm.objectsize intrinsic. When I calculate the result based on condition, I put it in the third argument. If there is no inlining, condition will not get eliminated, and this will be the final result. When there is inlining, condition will be eliminated after inlining and the llvm.objectsize will be replaced with a constant. >>>> With this approach, I get the correct result in both cases (with and without -fno-inline). >>>> >>>> I would like to have a discussion about this approach because I am changing the IR (because of adding third argument to __builtin_object_size function). Do you have some comments ? >>>> >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> llvm-dev at lists.llvm.org >>>> http://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/20160318/7a9ef6ef/attachment.html>