diff --git a/llvm/include/llvm/IR/DerivedTypes.h b/llvm/include/llvm/IR/DerivedTypes.h --- a/llvm/include/llvm/IR/DerivedTypes.h +++ b/llvm/include/llvm/IR/DerivedTypes.h @@ -696,6 +696,14 @@ return isOpaque() || PointeeTy == Ty; } + /// Return true if both pointer types have the same element type. Two opaque + /// pointers are considered to have the same element type, while an opaque + /// and a non-opaque pointer have different element types. + /// TODO: Remove after opaque pointer transition is complete. + bool hasSameElementTypeAs(PointerType *Other) { + return PointeeTy == Other->PointeeTy; + } + /// Implement support type inquiry through isa, cast, and dyn_cast. static bool classof(const Type *T) { return T->getTypeID() == PointerTyID; diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2891,13 +2891,15 @@ "Illegal addrspacecast, bitcast sequence!"); // Allowed, use first cast's opcode return firstOp; - case 14: + case 14: { // bitcast, addrspacecast -> addrspacecast if the element type of // bitcast's source is the same as that of addrspacecast's destination. - if (SrcTy->getScalarType()->getPointerElementType() == - DstTy->getScalarType()->getPointerElementType()) + PointerType *SrcPtrTy = cast(SrcTy->getScalarType()); + PointerType *DstPtrTy = cast(DstTy->getScalarType()); + if (SrcPtrTy->hasSameElementTypeAs(DstPtrTy)) return Instruction::AddrSpaceCast; return 0; + } case 15: // FIXME: this state can be merged with (1), but the following assert // is useful to check the correcteness of the sequence due to semantic diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2798,9 +2798,9 @@ PointerType *SrcTy = cast(Src->getType()->getScalarType()); PointerType *DestTy = cast(CI.getType()->getScalarType()); - Type *DestElemTy = DestTy->getElementType(); - if (SrcTy->getElementType() != DestElemTy) { - Type *MidTy = PointerType::get(DestElemTy, SrcTy->getAddressSpace()); + if (!SrcTy->hasSameElementTypeAs(DestTy)) { + Type *MidTy = + PointerType::getWithSamePointeeType(DestTy, SrcTy->getAddressSpace()); // Handle vectors of pointers. if (VectorType *VT = dyn_cast(CI.getType())) MidTy = VectorType::get(MidTy, VT->getElementCount()); diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll --- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll +++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll @@ -35,20 +35,44 @@ ret ptr bitcast (i8* @g to ptr) } -;define ptr @addrspacecast_opaque_to_opaque(ptr addrspace(1) %a) { -; %b = addrspacecast ptr addrspace(1) %a to ptr -; ret ptr %b -;} +define ptr @addrspacecast_opaque_to_opaque(ptr addrspace(1) %a) { +; CHECK-LABEL: @addrspacecast_opaque_to_opaque( +; CHECK-NEXT: [[B:%.*]] = addrspacecast ptr addrspace(1) [[A:%.*]] to ptr +; CHECK-NEXT: ret ptr [[B]] +; + %b = addrspacecast ptr addrspace(1) %a to ptr + ret ptr %b +} + +define ptr @addrspacecast_typed_to_opaque(i8 addrspace(1)* %a) { +; CHECK-LABEL: @addrspacecast_typed_to_opaque( +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8 addrspace(1)* [[A:%.*]] to ptr addrspace(1) +; CHECK-NEXT: [[B:%.*]] = addrspacecast ptr addrspace(1) [[TMP1]] to ptr +; CHECK-NEXT: ret ptr [[B]] +; + %b = addrspacecast i8 addrspace(1)* %a to ptr + ret ptr %b +} -;define ptr @addrspacecast_typed_to_opaque(i8 addrspace(1)* %a) { -; %b = addrspacecast i8 addrspace(1)* %a to ptr -; ret ptr %b -;} +define i8* @addrspacecast_opaque_to_typed(ptr addrspace(1) %a) { +; CHECK-LABEL: @addrspacecast_opaque_to_typed( +; CHECK-NEXT: [[TMP1:%.*]] = bitcast ptr addrspace(1) [[A:%.*]] to i8 addrspace(1)* +; CHECK-NEXT: [[B:%.*]] = addrspacecast i8 addrspace(1)* [[TMP1]] to i8* +; CHECK-NEXT: ret i8* [[B]] +; + %b = addrspacecast ptr addrspace(1) %a to i8* + ret i8* %b +} -;define i8* @addrspacecast_opaque_to_typed(ptr addrspace(1) %a) { -; %b = addrspacecast ptr addrspace(1) %a to i8* -; ret i8* %b -;} +define ptr addrspace(1) @bitcast_and_addrspacecast_eliminable(ptr %a) { +; CHECK-LABEL: @bitcast_and_addrspacecast_eliminable( +; CHECK-NEXT: [[C:%.*]] = addrspacecast ptr [[A:%.*]] to ptr addrspace(1) +; CHECK-NEXT: ret ptr addrspace(1) [[C]] +; + %b = bitcast ptr %a to i8* + %c = addrspacecast i8* %b to ptr addrspace(1) + ret ptr addrspace(1) %c +} define ptr @gep_constexpr_1(ptr %a) { ; CHECK-LABEL: @gep_constexpr_1(