[llvm-dev] Placement new and TBAA

Mehdi Amini via llvm-dev llvm-dev at lists.llvm.org
Fri Nov 25 20:23:10 PST 2016


> On Nov 25, 2016, at 4:17 PM, Daniel Berlin via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> 
> 
> On Fri, Nov 25, 2016 at 6:10 AM, Hubert Tong <hubert.reinterpretcast at gmail.com <mailto:hubert.reinterpretcast at gmail.com>> wrote:
> On Fri, Nov 25, 2016 at 1:42 AM, Daniel Berlin <dberlin at dberlin.org <mailto:dberlin at dberlin.org>> wrote:
> What is the purpose of the union there?
> The purpose of the union is to increase portability by ensuring that the placement new is not being performed on insufficiently sized or aligned memory.
> Gotcha
>  
>  
> I ask because pretty much no compiler will respecting the unioning without visible accesses  in all cases, because it would ruin most optimization[1]
> 
> But i'm also not sure it's required in this testcase to make your testcase fail.
> It isn't. The program should be valid, without the union, on platforms where int and float have the same size an alignment.
> 
> Right, so you need to debug that first, and see what's going wrong.
> Without TBAA info in the .ll file, this should just work.
>  
>  
> 
> In practice, handling placement new properly in gcc required the equivalent of a new intrinsic (in gcc, it required adding CHANGE_DYNAMIC_TYPE_EXPR).
> Sure; my question is whether or not there is already a solution in the works for LLVM. If not, then I'll try to work with some folks to propose an intrinsic.
> 
> I would first focus on understanding why the testcase fails without any TBAA info at all.
> In that case, i would expect it to work.


The PR says "passes with -fno-strict-aliasing”, my understanding is that it is failing only with the TBAA indeed.

You don’t need the main and the union to reproduce, extracting foo() alone in its single own file is enough:

void *operator new(decltype(sizeof 0), void *) noexcept;
float *qq;
void foo(int *p, int *q, long unk) {
   for (long i = 0; i < unk; ++i) {
      ++*p;
      qq = new (static_cast<void *>(&q[i])) float(42);
   }
}

LICM will get the store to p out of the loop, conceptually turning it into:

void foo(int *p, int *q, long unk) {
   for (long i = 0; i < unk; ++i) {
      qq = new (static_cast<void *>(&q[i])) float(42);
   }
   ++*p;
}


Now I don’t know if the use of placement new in this example is legal in the first place. I thought calling delete before using placement new was mandatory.

CC Sanjoy, since he looked into TBAA recently and it reminds me a similar test case he mentioned, not with placement new but with a call to a function taking int * and float *, and passing the same address (call site was union).


— 
Mehdi

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161125/2592a7e6/attachment.html>


More information about the llvm-dev mailing list