[LLVMdev] possible addrspacecast problem

David Chisnall David.Chisnall at cl.cam.ac.uk
Wed Mar 18 00:44:19 PDT 2015


On 17 Mar 2015, at 20:06, Junjie Gu <jgu222 at gmail.com> wrote:

>> I've just been debugging a related issue with regard to commutativity of address space casts with respect to other operations.  One of the optimisers is turning an add after an address space cast into an add before the address space cast.  On our architecture, this results in different bounds information being available on the pointer and a run-time crash.  We could represent casts with a target-specific intrinsic, but we'd rather avoid that if possible. This is not fixed by changing isSafeToSpeculativelyExecute to return false for AddrSpaceCast, so I'll need to dig a bit more to understand exactly when and why it happens.
> 
> Like to know what is causing this.

I should start with a disclaimer that I haven't pulled in upstream LLVM for a couple of months, so this might already be fixed...

After SROA, we're left with this:

; Function Attrs: nounwind
define i32 @main() #0 {
entry:
  %call = call i8* @malloc(i64 zeroext 168)
  %0 = bitcast i8* %call to i32*
  %1 = addrspacecast i32* %0 to i32 addrspace(200)*
  call void @set(i32 addrspace(200)* %1)
  %add.ptr = getelementptr inbounds i32 addrspace(200)* %1, i64 41
  call void @test(i32 addrspace(200)* %add.ptr)
  ret i32 0
}

This is correct and semantically valid for our architecture.  The cast to AS200 is creating a fat pointer with base and bounds information, the GEP is constructing a new fat pointer with the same base and bounds but a different offset within the object.  This survives for a bit, but then:

*** IR Dump After Combine redundant instructions ***
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
  %call = call i8* @malloc(i64 zeroext 168) #2
  %0 = bitcast i8* %call to i32*
  %1 = addrspacecast i32* %0 to i32 addrspace(200)*
  call void @set(i32 addrspace(200)* %1) #2
  %add.ptr = getelementptr inbounds i8* %call, i64 164
  %2 = bitcast i8* %add.ptr to i32*
  %3 = addrspacecast i32* %2 to i32 addrspace(200)*
  call void @test(i32 addrspace(200)* %3) #2
  ret i32 0
}

So it looks as if InstCombine is deciding that it can hoist the GEP above the addrspacecast.  Unfortunately, narrowing it down to InstCombine doesn't actually narrow it down very much - I'll keep looking...

David





More information about the llvm-dev mailing list