[PATCH] D108123: [MemoryBuiltins] Mark user defined delete as nobuiltin

guopeilin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 18 04:49:02 PDT 2021


guopeilin added a comment.

In D108123#2951595 <https://reviews.llvm.org/D108123#2951595>, @lebedev.ri wrote:

> 



> What if we are statically linking to the libc++ with LTO?
> Surely we'll have said definition available, even though it is not `nobuiltin`?

Thanks for reviewing. 
When I use the following command `clang++ -O0 test.cpp  -flto=full -fuse-ld=lld -Wl,-plugin-opt=save-temps -static -stdlib=libstdc++`, I can still only find the deletion function only have declaration without a definition in the file `*.preopt.bc` and file `*.internalize.bc`.
The test.cpp looks like this:

  int a = 0;
  int test() {
    int *p = new int(2);
    a = *p;
    delete p;
    return a;
  }
  
  int main(){
    a = test();
    return 1;
  }

The IR of looks like

  define dso_local i32 @_Z4testv() #0 {
  entry:
    %p = alloca i32*, align 8
    %call = call noalias nonnull i8* @_Znwm(i64 4) #4
    %0 = bitcast i8* %call to i32*
    store i32 2, i32* %0, align 4
    store i32* %0, i32** %p, align 8
    %1 = load i32*, i32** %p, align 8
    %2 = load i32, i32* %1, align 4
    store i32 %2, i32* @a, align 4
    %3 = load i32*, i32** %p, align 8
    %isnull = icmp eq i32* %3, null
    br i1 %isnull, label %delete.end, label %delete.notnull
  
  delete.notnull:                                   ; preds = %entry
    %4 = bitcast i32* %3 to i8*
    call void @_ZdlPv(i8* %4) #5
    br label %delete.end
  
  delete.end:                                       ; preds = %delete.notnull, %entry
    %5 = load i32, i32* @a, align 4
    ret i32 %5
  }
  
  ; Function Attrs: nobuiltin allocsize(0)
  declare dso_local nonnull i8* @_Znwm(i64) #1
  
  ; Function Attrs: nobuiltin nounwind
  declare dso_local void @_ZdlPv(i8*) #2
  
  ; Function Attrs: mustprogress noinline norecurse optnone uwtable
  define dso_local i32 @main() #3 {
  entry:
    %retval = alloca i32, align 4
    store i32 0, i32* %retval, align 4
    %call = call i32 @_Z4testv()
    store i32 %call, i32* @a, align 4
    ret i32 1
  }

The attribute of `#5` is `attributes #5 = { builtin nounwind }`. https://godbolt.org/z/14dPM9Yf7
So this patch may not have harm on the `statically linking` case cause we only take care of the function with an exact definition.
Please correct me if I get wrong.

> What if it is overloaded in another TU, or via `LD_PRELOAD`? We then won't think it's `nobuiltin`?

Yes, in such cases, we can not get the definition of the overloaded function.  This patch cannot cover this case. 
However, if we cannot find the definition of the deletion function, the `DeadArgumentElimination` won't change the argument into undef, thus we won't generate `free(undef)`  instruction,  which makes things become fine.

> I think this is a clang problem.

Yes, I agree with the point that clang has some bug. As far as I have investigated the IR that generated just after clang,  no matter whether we overload the delete function, clang will always add a `builtin` attribute to the instruction that calls the delete function. 
It seems that clang only takes the function name into consideration to decide whether a function is builtin or not.
And it would be a great appreciation if you can give any suggestion on clang debug.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108123/new/

https://reviews.llvm.org/D108123



More information about the llvm-commits mailing list