Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVM 14: optimizer regression wrt. noalias attribute for return value #54740

Closed
kinke opened this issue Apr 4, 2022 · 3 comments
Closed

LLVM 14: optimizer regression wrt. noalias attribute for return value #54740

kinke opened this issue Apr 4, 2022 · 3 comments

Comments

@kinke
Copy link

kinke commented Apr 4, 2022

Input IR: current3.txt

With LLVM 13 (opt -O3), the _Dmain function is perfectly optimized to:

define i32 @_Dmain({ i64, { i64, i8* }* } %unnamed) #5 {
  %.frame.i = tail call noalias i8* @_d_allocmemory(i64 4) #1
  %x.i = bitcast i8* %.frame.i to i32*
  store i32 0, i32* %x.i, align 4
  %.gc_struct.i.i = tail call noalias i8* @_d_newitemT(%object.TypeInfo* bitcast (%object.TypeInfo_Struct* @_D28TypeInfo_S3mod9test14846FZ1S6__initZ to %object.TypeInfo*)) #1
  %.vthis.i.i = bitcast i8* %.gc_struct.i.i to i8**
  store i8* %.frame.i, i8** %.vthis.i.i, align 8
  store i32 1, i32* %x.i, align 4
  ret i32 0
}

With LLVM 14.0.0, it's a meager and invalid:

define i32 @_Dmain({ i64, { i64, i8* }* } %unnamed) #5 {
  %.frame.i = tail call noalias i8* @_d_allocmemory(i64 4) #1
  %.gc_struct.i.i = tail call noalias i8* @_d_newitemT(%object.TypeInfo* bitcast (%object.TypeInfo_Struct* @_D28TypeInfo_S3mod9test14846FZ1S6__initZ to %object.TypeInfo*)) #1
  ret i32 0
}

The thing is that _d_newitemT allocates garbage-collected memory, which is cleaned up at program termination, incl. destructing %.gc_struct.i.i, so the store to %.vthis.i.i etc. cannot be elided.

Removing the noalias function attribute from _d_newitemT 'fixes' the testcase. I haven't found anything related in the LLVM 14 changelog.

@nikic
Copy link
Contributor

nikic commented Apr 4, 2022

Dropping the noalias attribute is indeed the right thing to do here. _d_newitemT does not satisfy the noalias return contract, because the object is also accessible to whatever is invoking the destructor on the object storage.

@kinke
Copy link
Author

kinke commented Apr 4, 2022

Thx @nikic. _d_newitemT keeps track of its allocations, so the returned pointer escapes from the callee. From the spec:

On function return values, the noalias attribute indicates that the function acts like a system memory allocation function, returning a pointer to allocated storage disjoint from the storage for any other object accessible to the caller.

I guess there are hardly any allocators satisfying noalias return then?

@nikic
Copy link
Contributor

nikic commented Apr 4, 2022

Normal allocators like malloc can and do use noreturn return values.

kinke added a commit to kinke/ldc that referenced this issue Apr 4, 2022
…n prototypes

As that's invalid according to
llvm/llvm-project#54740, and a problem
since LLVM 14 at least.
@kinke kinke closed this as completed Apr 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants