This is an archive of the discontinued LLVM Phabricator instance.

SROA fix to avoid invalid bitcast generation when converting a load from a double pointer bitcasted with an address space change of the pointee pointee
AbandonedPublic

Authored by michele.scandale on Mar 7 2014, 2:42 AM.

Details

Reviewers
arsenm
Summary

Here's a fix for SROA to avoid the generation of invalid bitcast between pointers in different address spaces.
The case is the following:

%p.addr = alloca <2 x float> addrspace(1)*, align 8
; ...
%p.new = bitcast <2 x float> addrspace(1)** %p.addr to <2 x float>**
%val = load <2 x float>** %p.new, align 8

SROA identifies an AllocaSlice of %p.addr and %val and tries to rewrite it removing the load. The problem is that the source type of the loaded value is <2 x float> addrspace(1)* and the destination type is <2 x float>*, thus a bitcast between those types is invalid.
The proposed fix catches these cases generating a ptrtoint+inttoptr pair instead of an addrspacecast to keep the common bits of the value immutated.

Diff Detail

Event Timeline

arsenm added a comment.Mar 7 2014, 9:48 AM

My initial thought is you should not be introducing an ptrtoint if one doesn't already exist, and the problem is really the address space was not specified when necessary somewhere else.

arsenm added a comment.Mar 7 2014, 9:59 AM

Actually I don't see the problem. I just tried your testcase with current trunk, and SROA makes no change to the IR. The testcase also involves bitcasts between pointers to pointers with an address space, which should be fine.

I tested it at commit 122a970111b8ec66ae330f2c218ae951dddaf75b, and still I have an assertion on "castIsValid": the problem is exactly on pointer of pointer where the bitcast changes the address space of the pointee pointee.

define void @union_cvt_float2(<2 x float> addrspace(1)* %p) {
 %p.addr = alloca <2 x float> addrspace(1)*, align 8
 store <2 x float> addrspace(1)* %p, <2 x float> addrspace(1)** %p.addr, align 8
 %1 = bitcast <2 x float> addrspace(1)** %p.addr to <2 x float>**
 %2 = load <2 x float>** %1, align 8
 call void @ext_call_float2(<2 x float>* %2)
 ret void
}

In this example SROA wants to replace %2 = load <2 x float>** %1, align 8 with %2 = bitcast <2 x float> addrspace(1)* %p to <2 x float>*, but this is an invalid instruction!
The input IR does the following:

  • bitcast the address of the stack location associated to the parameter (<2 x float> addrspace(1)*) to an address pointing to another type (<2 x float>*)
  • load a <2 x float>* from the bitcasted address

The conservative assumption is that sizeof(<2 x float> addrspace(1)*) != <2 x float>*: in this case only the bits in the overlapped region are the same, thus IMHO the right transformation to preserve the semantic is to use ptrtoint+inttoptr using as middle type an integer type that can fully contains the original value.

This same problem was reported here recently and this patch fixes it:

https://github.com/HSAFoundation/HLC-HSAIL-Development-LLVM/issues/17

The pointer sizes and formats are incompatible so there isn't really anything sensible to do other than to do this ptrtoint / inttoptr pair, so this makes sense to me.

michele.scandale abandoned this revision.Mar 22 2017, 1:11 PM