<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <br>
    I'm not trying to add runtime checks, I want to transform
    llvm.objectsize into constant in a different place.<br>
    <br>
    <br>
    Here is the .ll prints that might explain better what I'm doing.
    This is for example with inlining enabled. In case <br>
    that inlining is disabled, the same transformations happen except
    for main. Main only has a call to foo().<br>
    <br>
    <br>
    <br>
    Combine redundant instruction for function foo() will calculate
    minimum or maximum value depends on second argument,<br>
    and put it in third argument. We must save this value to third
    argument so that inliner has a chance to eliminate <br>
    the condition. If we replace with constant in foo() then we get
    wrong value once inlined in main.<br>
    <br>
    *** IR Dump After Simplify the CFG ***<br>
    ; Function Attrs: nounwind readnone uwtable<br>
    define i64 @foo(i32 %flag) #0 {<br>
    entry:<br>
      %chararray = alloca [30 x i8], align 16<br>
      %chararray2 = alloca [10 x i8], align 1<br>
      %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64
    0, i64 0<br>
      call void @llvm.lifetime.start(i64 30, i8* %0) #5<br>
      %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64
    0, i64 0<br>
      call void @llvm.lifetime.start(i64 10, i8* %1) #5<br>
      %tobool = icmp eq i32 %flag, 0<br>
      %cptr.0 = select i1 %tobool, i8* %0, i8* %1<br>
      %2 = call i64 @llvm.objectsize.i64.p0i8.i32(i8* %cptr.0, i1 true,
    i32 0)<br>
      call void @llvm.lifetime.end(i64 10, i8* %1) #5<br>
      call void @llvm.lifetime.end(i64 30, i8* %0) #5<br>
      ret i64 %2<br>
    }<br>
    *** IR Dump After Combine redundant instructions ***<br>
    ; Function Attrs: nounwind readnone uwtable<br>
    define i64 @foo(i32 %flag) #0 {<br>
    entry:<br>
      %chararray = alloca [30 x i8], align 16<br>
      %chararray2 = alloca [10 x i8], align 1<br>
      %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64
    0, i64 0<br>
      call void @llvm.lifetime.start(i64 30, i8* %0) #5<br>
      %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64
    0, i64 0<br>
      call void @llvm.lifetime.start(i64 10, i8* %1) #5<br>
      %tobool = icmp eq i32 %flag, 0<br>
      %cptr.0 = select i1 %tobool, i8* %0, i8* %1<br>
      %2 = call i64 @llvm.objectsize.i64.p0i8.i32(i8* %cptr.0, i1 true,
    i32 10)<br>
      call void @llvm.lifetime.end(i64 10, i8* %1) #5<br>
      call void @llvm.lifetime.end(i64 30, i8* %0) #5<br>
      ret i64 %2<br>
    }<br>
    <br>
    Combining redundant instructions for main calculates correct value
    (30) because foo() is inlined and now  the condition is<br>
    eliminated. If we didn't leave the object size in foo(), the value
    would be 10.<br>
    <br>
    *** IR Dump After Simplify the CFG ***<br>
    ; Function Attrs: nounwind uwtable<br>
    define i32 @main() #3 {<br>
    entry:<br>
      %chararray.i = alloca [30 x i8], align 16<br>
      %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray.i,
    i64 0, i64 0<br>
      call void @llvm.lifetime.start(i64 30, i8* %0) #5<br>
      %1 = call i64 @llvm.objectsize.i64.p0i8.i32(i8* %0, i1 true, i32
    10) #5<br>
      call void @llvm.lifetime.end(i64 30, i8* %0) #5<br>
      %call1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds
    ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i64 %1)<br>
      ret i32 0<br>
    }<br>
    *** IR Dump After Combine redundant instructions ***<br>
    ; Function Attrs: nounwind uwtable<br>
    define i32 @main() #3 {<br>
    entry:<br>
      %call1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds
    ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i64 30)<br>
      ret i32 0<br>
    }<br>
    <br>
    Codegen prepare will finaly replace the llvm.object size with
    constant in function foo.<br>
    <br>
    *** IR Dump After Partially inline calls to library functions ***<br>
    ; Function Attrs: nounwind readnone uwtable<br>
    define i64 @foo(i32 %flag) #0 {<br>
    entry:<br>
      %chararray = alloca [30 x i8], align 16<br>
      %chararray2 = alloca [10 x i8], align 1<br>
      %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64
    0, i64 0<br>
      call void @llvm.lifetime.start(i64 30, i8* %0) #5<br>
      %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64
    0, i64 0<br>
      call void @llvm.lifetime.start(i64 10, i8* %1) #5<br>
      %tobool = icmp eq i32 %flag, 0<br>
      %cptr.0 = select i1 %tobool, i8* %0, i8* %1<br>
      %2 = call i64 @llvm.objectsize.i64.p0i8.i32(i8* %cptr.0, i1 true,
    i32 10)<br>
      call void @llvm.lifetime.end(i64 10, i8* %1) #5<br>
      call void @llvm.lifetime.end(i64 30, i8* %0) #5<br>
      ret i64 %2<br>
    }<br>
    *** IR Dump After CodeGen Prepare ***<br>
    ; Function Attrs: nounwind readnone uwtable<br>
    define i64 @foo(i32 %flag) #0 {<br>
    entry:<br>
      %chararray = alloca [30 x i8], align 16<br>
      %chararray2 = alloca [10 x i8], align 1<br>
      %0 = bitcast [30 x i8]* %chararray to i8*<br>
      call void @llvm.lifetime.start(i64 30, i8* %0) #5<br>
      %1 = bitcast [10 x i8]* %chararray2 to i8*<br>
      call void @llvm.lifetime.start(i64 10, i8* %1) #5<br>
      %tobool = icmp eq i32 %flag, 0<br>
      %cptr.0 = select i1 %tobool, i8* %0, i8* %1<br>
      call void @llvm.lifetime.end(i64 10, i8* %1) #5<br>
      call void @llvm.lifetime.end(i64 30, i8* %0) #5<br>
      ret i64 10<br>
    }<br>
    <br>
    <div class="moz-cite-prefix">On 16.03.2016. 19:23, George Burgess IV
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAKh6zBFvsEL6uZenwhqLCWDs0XkP0545qgvrvK5oUOS3BUDwgA@mail.gmail.com"
      type="cite">
      <div dir="ltr">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?</div>
    </blockquote>
    <blockquote
cite="mid:CAKh6zBFvsEL6uZenwhqLCWDs0XkP0545qgvrvK5oUOS3BUDwgA@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div><br>
        </div>
        <div>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:</div>
        <div>
          <div><br>
            int foo(int cond) {</div>
          <div>  char small[10], large[30];</div>
          <div>  void *what = cond ? small : large;</div>
          <div>  // if X = 0 or 1, hand back 30 (max possible size), for
            2 or 3, hand back 10 (minimum possible size)</div>
          <div>  // if X = 0 or 1, this gets lowered to
            @llvm.objectsize(..., 0), if X = 2 or 3, it gets lowered to
            @llvm.objectsize(..., 1)</div>
          <div>  return __builtin_object_size(what, X);</div>
          <div>}</div>
        </div>
        <div><br>
        </div>
        <div>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. :)</div>
        <div class="gmail_extra"><br>
          <div class="gmail_quote">On Wed, Mar 16, 2016 at 9:39 AM,
            Strahinja Petrovic <span dir="ltr"><<a
                moz-do-not-send="true"
                href="mailto:strahinja.petrovic@rt-rk.com"
                target="_blank">strahinja.petrovic@rt-rk.com</a>></span>
            wrote:<br>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">Optimizer
              doesn't know how to calculate the object size when it
              finds condition that cannot be eliminated. There is
              example:<br>
              <br>
              -----------------------------------------------<br>
              #include<stdlib.h><br>
              #define STATIC_BUF_SIZE 10<br>
              #define LARGER_BUF_SIZE 30<br>
              <br>
              size_t foo(int flag) {<br>
                char *cptr;<br>
                char chararray[LARGER_BUF_SIZE];<br>
                char chararray2[STATIC_BUF_SIZE];<br>
                if(flag)<br>
                  cptr = chararray2;<br>
                 else<br>
                  cptr = chararray;<br>
              <br>
                return  __builtin_object_size(cptr, 2);<br>
              }<br>
              <br>
              int main() {<br>
                size_t ret;<br>
                ret = foo(0);<br>
                printf("\n%d\n", ret);<br>
                return 0;<br>
              }<br>
              ----------------------------------------------<br>
               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.<br>
              <br>
               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.<br>
              <br>
               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.<br>
               With this approach, I get the correct result in both
              cases (with and without -fno-inline).<br>
              <br>
               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 ?<br>
              <br>
            </blockquote>
          </div>
          <br>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>