Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -998,6 +998,8 @@ // Fold the Instruction's operands. if (ConstantExpr *NewCE = dyn_cast(Op)) Op = ConstantFoldConstantExpression(NewCE, DL, TLI); + if (!Op) + return nullptr; Ops.push_back(Op); } @@ -1041,6 +1043,10 @@ if (FoldedOps.insert(NewCE).second) NewC = ConstantFoldConstantExpressionImpl(NewCE, DL, TLI, FoldedOps); } + + if (!NewC) + return nullptr; + Ops.push_back(NewC); } @@ -1222,8 +1228,22 @@ case Instruction::SIToFP: case Instruction::FPToUI: case Instruction::FPToSI: - case Instruction::AddrSpaceCast: return ConstantExpr::getCast(Opcode, C, DestTy); + case Instruction::AddrSpaceCast: { + if (isa(C)) + return UndefValue::get(DestTy); + + // It is up to the target for how to constant fold immediates. + if (ConstantExpr *CE = dyn_cast(C)) { + if (CE->getOpcode() == Instruction::IntToPtr) + return nullptr; + + if (auto *NewCE = ConstantFoldConstantExpression(CE, DL, nullptr)) + return ConstantExpr::getAddrSpaceCast(NewCE, DestTy); + } + + return nullptr; + } case Instruction::BitCast: return FoldBitCast(C, DestTy, DL); } Index: test/Transforms/InstCombine/addrspacecast.ll =================================================================== --- test/Transforms/InstCombine/addrspacecast.ll +++ test/Transforms/InstCombine/addrspacecast.ll @@ -145,3 +145,42 @@ ret i32 %sum.inc } +; CHECK-LABEL: @constant_fold_null( +; CHECK: addrspacecast i32 addrspace(3)* null to i32 addrspace(4)* +define void @constant_fold_null() #0 { + %cast = addrspacecast i32 addrspace(3)* null to i32 addrspace(4)* + store i32 7, i32 addrspace(4)* %cast + ret void +} + +; CHECK-LABEL: @constant_fold_undef( +; CHECK: ret i32 addrspace(4)* undef +define i32 addrspace(4)* @constant_fold_undef() #0 { + %cast = addrspacecast i32 addrspace(3)* undef to i32 addrspace(4)* + ret i32 addrspace(4)* %cast +} + +; CHECK-LABEL: @constant_fold_null_vector( + ; CHECK: addrspacecast <4 x i32 addrspace(3)*> zeroinitializer to <4 x i32 addrspace(4)*> +define <4 x i32 addrspace(4)*> @constant_fold_null_vector() #0 { + %cast = addrspacecast <4 x i32 addrspace(3)*> zeroinitializer to <4 x i32 addrspace(4)*> + ret <4 x i32 addrspace(4)*> %cast +} + +; CHECK-LABEL: @constant_fold_inttoptr( +; CHECK: addrspacecast i32 addrspace(3)* inttoptr (i32 -1 to i32 addrspace(3)*) to i32 addrspace(4)* +define void @constant_fold_inttoptr() #0 { + %cast = addrspacecast i32 addrspace(3)* inttoptr (i32 -1 to i32 addrspace(3)*) to i32 addrspace(4)* + store i32 7, i32 addrspace(4)* %cast + ret void +} + +; CHECK-LABEL: @constant_fold_gep_inttoptr( +; CHECK: addrspacecast i32 addrspace(3)* inttoptr (i64 1274 to i32 addrspace(3)*) to i32 addrspace(4)* +define void @constant_fold_gep_inttoptr() #0 { + %k = inttoptr i32 1234 to i32 addrspace(3)* + %gep = getelementptr i32, i32 addrspace(3)* %k, i32 10 + %cast = addrspacecast i32 addrspace(3)* %gep to i32 addrspace(4)* + store i32 7, i32 addrspace(4)* %cast + ret void +} Index: unittests/IR/ConstantsTest.cpp =================================================================== --- unittests/IR/ConstantsTest.cpp +++ unittests/IR/ConstantsTest.cpp @@ -155,6 +155,17 @@ EXPECT_EQ(Constant::getNullValue(Int32PtrVecTy), ConstantExpr::getPointerCast( Constant::getNullValue(Int8PtrVecTy), Int32PtrVecTy)); + + Type *Int32Ptr1Ty = Type::getInt32PtrTy(C, 1); + ConstantInt *K = ConstantInt::get(Type::getInt64Ty(C), 1234); + + // Make sure that addrspacecast of inttoptr is not folded away. + EXPECT_NE(K, + ConstantExpr::getAddrSpaceCast( + ConstantExpr::getIntToPtr(K, Int32PtrTy), Int32Ptr1Ty)); + EXPECT_NE(K, + ConstantExpr::getAddrSpaceCast( + ConstantExpr::getIntToPtr(K, Int32Ptr1Ty), Int32PtrTy)); } #define CHECK(x, y) { \