Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -2282,38 +2282,25 @@ return 0; } case 12: { - // addrspacecast, addrspacecast -> bitcast, if SrcAS == DstAS // addrspacecast, addrspacecast -> addrspacecast, if SrcAS != DstAS if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace()) return Instruction::AddrSpaceCast; - return Instruction::BitCast; + return 0; } case 13: - // FIXME: this state can be merged with (1), but the following assert - // is useful to check the correcteness of the sequence due to semantic - // change of bitcast. - assert( - SrcTy->isPtrOrPtrVectorTy() && - MidTy->isPtrOrPtrVectorTy() && - DstTy->isPtrOrPtrVectorTy() && - SrcTy->getPointerAddressSpace() != MidTy->getPointerAddressSpace() && - MidTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace() && - "Illegal addrspacecast, bitcast sequence!"); - // Allowed, use first cast's opcode - return firstOp; + // addrspacecast, bitcast -> addrspacecast if the pointer element types + // are the same. + if (SrcTy->getPointerElementType() == DstTy->getPointerElementType()) + return Instruction::AddrSpaceCast; + return 0; + case 14: - // FIXME: this state can be merged with (2), but the following assert - // is useful to check the correcteness of the sequence due to semantic - // change of bitcast. - assert( - SrcTy->isPtrOrPtrVectorTy() && - MidTy->isPtrOrPtrVectorTy() && - DstTy->isPtrOrPtrVectorTy() && - SrcTy->getPointerAddressSpace() == MidTy->getPointerAddressSpace() && - MidTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace() && - "Illegal bitcast, addrspacecast sequence!"); - // Allowed, use second cast's opcode - return secondOp; + // bitcast, addrspacecast -> addrspacecast if the pointer element types + // are the same. + if (MidTy->getPointerElementType() == DstTy->getPointerElementType()) + 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: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1853,5 +1853,22 @@ } Instruction *InstCombiner::visitAddrSpaceCast(AddrSpaceCastInst &CI) { - return commonCastTransforms(CI); + // If the destination pointer element type is not the the same as the source's + // do the addrspacecast to the same type, and then the bitcast in the new + // address space. This allows the cast to be exposed to other transforms. + Value *Src = CI.getOperand(0); + PointerType *SrcTy = cast(Src->getType()->getScalarType()); + PointerType *DestTy = cast(CI.getType()->getScalarType()); + + Type *SrcElemTy = SrcTy->getElementType(); + if (SrcElemTy != DestTy->getElementType()) { + Type *MidTy = PointerType::get(SrcElemTy, DestTy->getAddressSpace()); + if (CI.getType()->isVectorTy()) // Handle vectors of pointers. + MidTy = VectorType::get(MidTy, CI.getType()->getVectorNumElements()); + + Value *NewASCast = Builder->CreateAddrSpaceCast(Src, MidTy); + return new BitCastInst(NewASCast, CI.getType()); + } + + return commonPointerCastTransforms(CI); } Index: test/Transforms/InstCombine/addrspacecast.ll =================================================================== --- test/Transforms/InstCombine/addrspacecast.ll +++ test/Transforms/InstCombine/addrspacecast.ll @@ -22,10 +22,77 @@ define float* @combine_redundant_addrspacecast_types(i32 addrspace(1)* %x) nounwind { ; CHECK-LABEL: @combine_redundant_addrspacecast_types( -; CHECK: addrspacecast i32 addrspace(1)* %x to float* +; CHECK-NEXT: addrspacecast i32 addrspace(1)* %x to i32* +; CHECK-NEXT: bitcast i32* %1 to float* ; CHECK-NEXT: ret %y = addrspacecast i32 addrspace(1)* %x to i32 addrspace(3)* %z = addrspacecast i32 addrspace(3)* %y to float* ret float* %z } +define <4 x float*> @combine_redundant_addrspacecast_types_vector(<4 x i32 addrspace(1)*> %x) nounwind { +; CHECK-LABEL: @combine_redundant_addrspacecast_types_vector( +; CHECK-NEXT: addrspacecast <4 x i32 addrspace(1)*> %x to <4 x i32*> +; CHECK-NEXT: bitcast <4 x i32*> %1 to <4 x float*> +; CHECK-NEXT: ret + %y = addrspacecast <4 x i32 addrspace(1)*> %x to <4 x i32 addrspace(3)*> + %z = addrspacecast <4 x i32 addrspace(3)*> %y to <4 x float*> + ret <4 x float*> %z +} + +define float addrspace(2)* @combine_addrspacecast_bitcast_1(i32 addrspace(1)* %x) nounwind { +; CHECK-LABEL: @combine_addrspacecast_bitcast_1( +; CHECK-NEXT: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)* +; CHECK-NEXT: bitcast i32 addrspace(2)* %y to float addrspace(2)* +; CHECK-NEXT: ret + %y = addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)* + %z = bitcast i32 addrspace(2)* %y to float addrspace(2)* + ret float addrspace(2)* %z +} + +define i32 addrspace(2)* @combine_addrspacecast_bitcast_2(i32 addrspace(1)* %x) nounwind { +; CHECK-LABEL: @combine_addrspacecast_bitcast_2( +; CHECK: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)* +; CHECK-NEXT: ret + %y = addrspacecast i32 addrspace(1)* %x to float addrspace(2)* + %z = bitcast float addrspace(2)* %y to i32 addrspace(2)* + ret i32 addrspace(2)* %z +} + +define i32 addrspace(2)* @combine_bitcast_addrspacecast_1(i32 addrspace(1)* %x) nounwind { +; CHECK-LABEL: @combine_bitcast_addrspacecast_1( +; CHECK: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)* +; CHECK-NEXT: ret + %y = bitcast i32 addrspace(1)* %x to i8 addrspace(1)* + %z = addrspacecast i8 addrspace(1)* %y to i32 addrspace(2)* + ret i32 addrspace(2)* %z +} + +define float addrspace(2)* @combine_bitcast_addrspacecast_2(i32 addrspace(1)* %x) nounwind { +; CHECK-LABEL: @combine_bitcast_addrspacecast_2( +; CHECK: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)* +; CHECK: bitcast i32 addrspace(2)* %1 to float addrspace(2)* +; CHECK-NEXT: ret + %y = bitcast i32 addrspace(1)* %x to i8 addrspace(1)* + %z = addrspacecast i8 addrspace(1)* %y to float addrspace(2)* + ret float addrspace(2)* %z +} + +define float addrspace(2)* @combine_addrspacecast_types(i32 addrspace(1)* %x) nounwind { +; CHECK-LABEL: @combine_addrspacecast_types( +; CHECK-NEXT: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)* +; CHECK-NEXT: bitcast i32 addrspace(2)* %1 to float addrspace(2)* +; CHECK-NEXT: ret + %y = addrspacecast i32 addrspace(1)* %x to float addrspace(2)* + ret float addrspace(2)* %y +} + +define <4 x float addrspace(2)*> @combine_addrspacecast_types_vector(<4 x i32 addrspace(1)*> %x) nounwind { +; CHECK-LABEL: @combine_addrspacecast_types_vector( +; CHECK-NEXT: addrspacecast <4 x i32 addrspace(1)*> %x to <4 x i32 addrspace(2)*> +; CHECK-NEXT: bitcast <4 x i32 addrspace(2)*> %1 to <4 x float addrspace(2)*> +; CHECK-NEXT: ret + %y = addrspacecast <4 x i32 addrspace(1)*> %x to <4 x float addrspace(2)*> + ret <4 x float addrspace(2)*> %y +} +