Index: lib/Transforms/Scalar/SROA.cpp =================================================================== --- lib/Transforms/Scalar/SROA.cpp +++ lib/Transforms/Scalar/SROA.cpp @@ -1613,6 +1613,13 @@ return IRB.CreatePtrToInt(V, NewTy); } + // If both types are pointers in different address spaces use the pair + // ptrtoint+inttoptr to keep common bits of the value immutated. + if (OldTy->isPtrOrPtrVectorTy() && NewTy->isPtrOrPtrVectorTy() && + OldTy->getPointerAddressSpace() != NewTy->getPointerAddressSpace()) + return IRB.CreateIntToPtr(IRB.CreatePtrToInt(V, DL.getIntPtrType(OldTy)), + NewTy); + return IRB.CreateBitCast(V, NewTy); } Index: test/Transforms/SROA/union_ptr_as.ll =================================================================== --- test/Transforms/SROA/union_ptr_as.ll +++ test/Transforms/SROA/union_ptr_as.ll @@ -0,0 +1,32 @@ +; RUN: opt -S -sroa < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @union_cvt_float2(<2 x float> addrspace(1)* %p) { +; CHECK: @union_cvt_float2 +; CHECK: %[[int:.*]] = ptrtoint <2 x float> addrspace(1)* %p to i64 +; CHECK-NEXT: %[[nptr:.*]] = inttoptr i64 %[[int]] to <2 x float>* + + %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 +} + +define void @union_cvt_v2ptr(<2 x i8 addrspace(1)*> %p) { +; CHECK: union_cvt_v2ptr +; CHECK: %[[int:.*]] = ptrtoint <2 x i8 addrspace(1)*> %p to <2 x i64> +; CHECK-NEXT: %[[nptr:.*]] = inttoptr <2 x i64> %[[int]] to <2 x i8*> + + %p.addr = alloca <2 x i8 addrspace(1)*>, align 8 + store <2 x i8 addrspace(1)*> %p, <2 x i8 addrspace(1)*>* %p.addr + %1 = bitcast <2 x i8 addrspace(1)*>* %p.addr to <2 x i8*>* + %2 = load <2 x i8*>* %1, align 8 + call void @ext_call_v2ptr(<2 x i8*> %2) + ret void +} + +declare void @ext_call_float2(<2 x float>*) +declare void @ext_call_v2ptr(<2 x i8*>)