Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1670,6 +1670,18 @@ if (!DL) return nullptr; + // addrspacecast between types is canonicalized as a bitcast, then an + // addrspacecast. To take advantage of the below bitcast + struct GEP, look + // through the addrspacecast. + if (AddrSpaceCastInst *ASC = dyn_cast(PtrOp)) { + /// X = bitcast A addrspace(1)* to B addrspace(1)* + /// Y = addrspacecast A addrspace(1)* to B addrspace(2)* + /// Z = gep Y, <...constant indices...> + /// Into an addrspacecasted GEP of the struct. + if (BitCastInst *BC = dyn_cast(ASC->getOperand(0))) + PtrOp = BC; + } + /// See if we can simplify: /// X = bitcast A* to B* /// Y = gep X, <...constant indices...> @@ -1678,11 +1690,10 @@ if (BitCastInst *BCI = dyn_cast(PtrOp)) { Value *Operand = BCI->getOperand(0); PointerType *OpType = cast(Operand->getType()); - unsigned OffsetBits = DL->getPointerTypeSizeInBits(OpType); + unsigned OffsetBits = DL->getPointerTypeSizeInBits(GEP.getType()); APInt Offset(OffsetBits, 0); if (!isa(Operand) && - GEP.accumulateConstantOffset(*DL, Offset) && - StrippedPtrTy->getAddressSpace() == GEP.getPointerAddressSpace()) { + GEP.accumulateConstantOffset(*DL, Offset)) { // If this GEP instruction doesn't move the pointer, just replace the GEP // with a bitcast of the real input to the dest type. @@ -1700,7 +1711,10 @@ return &GEP; } } - return new BitCastInst(Operand, GEP.getType()); + + if (Operand->getType()->getPointerAddressSpace() == GEP.getAddressSpace()) + return new BitCastInst(Operand, GEP.getType()); + return new AddrSpaceCastInst(Operand, GEP.getType()); } // Otherwise, if the offset is non-zero, we need to find out if there is a @@ -1715,7 +1729,10 @@ if (NGEP->getType() == GEP.getType()) return ReplaceInstUsesWith(GEP, NGEP); NGEP->takeName(&GEP); - return new BitCastInst(NGEP, GEP.getType()); + + if (NGEP->getType()->getPointerAddressSpace() == GEP.getAddressSpace()) + return new BitCastInst(NGEP, GEP.getType()); + return new AddrSpaceCastInst(NGEP, GEP.getType()); } } } Index: test/Transforms/InstCombine/cast.ll =================================================================== --- test/Transforms/InstCombine/cast.ll +++ test/Transforms/InstCombine/cast.ll @@ -354,6 +354,24 @@ ; CHECK: ret i32* %tmp1 } +define i32 addrspace(1)* @test41_addrspacecast_smaller(i32* %tmp1) { + %tmp64 = addrspacecast i32* %tmp1 to { i32 } addrspace(1)* + %tmp65 = getelementptr { i32 } addrspace(1)* %tmp64, i32 0, i32 0 + ret i32 addrspace(1)* %tmp65 +; CHECK-LABEL: @test41_addrspacecast_smaller( +; CHECK: addrspacecast i32* %tmp1 to i32 addrspace(1)* +; CHECK-NEXT: ret i32 addrspace(1)* +} + +define i32* @test41_addrspacecast_larger(i32 addrspace(1)* %tmp1) { + %tmp64 = addrspacecast i32 addrspace(1)* %tmp1 to { i32 }* + %tmp65 = getelementptr { i32 }* %tmp64, i32 0, i32 0 + ret i32* %tmp65 +; CHECK-LABEL: @test41_addrspacecast_larger( +; CHECK: addrspacecast i32 addrspace(1)* %tmp1 to i32* +; CHECK-NEXT: ret i32* +} + define i32 @test42(i32 %X) { %Y = trunc i32 %X to i8 ; [#uses=1] %Z = zext i8 %Y to i32 ; [#uses=1] Index: test/Transforms/InstCombine/getelementptr.ll =================================================================== --- test/Transforms/InstCombine/getelementptr.ll +++ test/Transforms/InstCombine/getelementptr.ll @@ -580,6 +580,16 @@ ret i32 addrspace(1)* %C } +define i32 addrspace(1)* @test33_addrspacecast(%struct.Key* %A) { +; CHECK-LABEL: @test33_addrspacecast( +; CHECK: %C = getelementptr %struct.Key* %A, i64 0, i32 0, i32 1 +; CHECK-NEXT: addrspacecast i32* %C to i32 addrspace(1)* +; CHECK-NEXT: ret + %B = addrspacecast %struct.Key* %A to %struct.anon addrspace(1)* + %C = getelementptr %struct.anon addrspace(1)* %B, i32 0, i32 2 + ret i32 addrspace(1)* %C +} + %T2 = type { i8*, i8 } define i8* @test34(i8* %Val, i64 %V) nounwind { entry: