[llvm-dev] Problem with __builtin_object_size when it depends on a condition

George Burgess IV via llvm-dev llvm-dev at lists.llvm.org
Wed Mar 16 11:23:53 PDT 2016


>From your email, ISTM that you're proposing that we insert runtime checks
to determine the object size, which breaks our guarantee to always lower to
a constant. Is this correct? If not, can you please provide an example of
the new IR for the function you gave?

Either way, is there a reason that we can't just use the second flag to
objectsize here? That flag was designed with cases like this in mind:

int foo(int cond) {
  char small[10], large[30];
  void *what = cond ? small : large;
  // if X = 0 or 1, hand back 30 (max possible size), for 2 or 3, hand back
10 (minimum possible size)
  // if X = 0 or 1, this gets lowered to @llvm.objectsize(..., 0), if X = 2
or 3, it gets lowered to @llvm.objectsize(..., 1)
  return __builtin_object_size(what, X);
}

FWIW, If you're looking for something more accurate than this, and you're
willing to have calculations at runtime in exchange for the accuracy, I'd
recommend looking into the machinery involved with
the ObjectSizeOffsetEvaluator (if you haven't already). I'm not familiar
with any of it, but you may find it interesting. :)

On Wed, Mar 16, 2016 at 9:39 AM, Strahinja Petrovic <
strahinja.petrovic at rt-rk.com> 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. 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 ?
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160316/c48bafd2/attachment.html>


More information about the llvm-dev mailing list