Index: llvm/lib/IR/Instructions.cpp =================================================================== --- llvm/lib/IR/Instructions.cpp +++ llvm/lib/IR/Instructions.cpp @@ -2891,13 +2891,19 @@ "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()); + Type *SrcElemTy = + !SrcPtrTy->isOpaque() ? SrcPtrTy->getElementType() : nullptr; + Type *DstElemTy = + !DstPtrTy->isOpaque() ? DstPtrTy->getElementType() : nullptr; + if (SrcElemTy == DstElemTy) 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 Index: llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2798,9 +2798,11 @@ 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()); + Type *DestElemTy = !DestTy->isOpaque() ? DestTy->getElementType() : nullptr; + Type *SrcElemTy = !SrcTy->isOpaque() ? SrcTy->getElementType() : nullptr; + if (SrcElemTy != DestElemTy) { + Type *MidTy = + PointerType::getWithSamePointeeType(DestTy, SrcTy->getAddressSpace()); // Handle vectors of pointers. if (VectorType *VT = dyn_cast(CI.getType())) MidTy = VectorType::get(MidTy, VT->getElementCount()); Index: llvm/test/Transforms/InstCombine/opaque-ptr.ll =================================================================== --- llvm/test/Transforms/InstCombine/opaque-ptr.ll +++ llvm/test/Transforms/InstCombine/opaque-ptr.ll @@ -27,17 +27,41 @@ ret i8* %b } -;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 +}