Index: lib/IR/ConstantFold.cpp =================================================================== --- lib/IR/ConstantFold.cpp +++ lib/IR/ConstantFold.cpp @@ -531,7 +531,8 @@ return UndefValue::get(DestTy); } - if (V->isNullValue() && !DestTy->isX86_MMXTy()) + if (V->isNullValue() && !DestTy->isX86_MMXTy() && + opc != Instruction::AddrSpaceCast) return Constant::getNullValue(DestTy); // If the cast operand is a constant expression, there's a few things we can Index: test/Assembler/ConstantExprFoldCast.ll =================================================================== --- test/Assembler/ConstantExprFoldCast.ll +++ test/Assembler/ConstantExprFoldCast.ll @@ -1,8 +1,13 @@ ; This test checks to make sure that constant exprs fold in some simple situations -; RUN: llvm-as < %s | llvm-dis | not grep cast +; RUN: llvm-as < %s | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s +; CHECK-NOT: bitcast +; CHECK-NOT: trunc +; CHECK: addrspacecast +; CHECK: addrspacecast + @A = global i32* bitcast (i8* null to i32*) ; Cast null -> fold @B = global i32** bitcast (i32** @A to i32**) ; Cast to same type -> fold @C = global i32 trunc (i64 42 to i32) ; Integral casts @@ -16,6 +21,9 @@ ; Address space cast AS0 null-> AS1 null @H = global i32 addrspace(1)* addrspacecast(i32* null to i32 addrspace(1)*) +; Address space cast AS1 null-> AS0 null +@I = global i32* addrspacecast(i32 addrspace(1)* null to i32*) + ; Bitcast -> GEP -@I = external global { i32 } -@J = global i32* bitcast ({ i32 }* @I to i32*) +@J = external global { i32 } +@K = global i32* bitcast ({ i32 }* @J to i32*) 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: 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,27 @@ 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)); + + Constant *NullInt32Ptr0 = Constant::getNullValue(Int32PtrTy); + Constant *NullInt32Ptr1 = Constant::getNullValue(Int32Ptr1Ty); + + // Make sure that addrspacecast of null is not folded away. + EXPECT_NE(Constant::getNullValue(Int32PtrTy), + ConstantExpr::getAddrSpaceCast(NullInt32Ptr0, Int32Ptr1Ty)); + + EXPECT_NE(Constant::getNullValue(Int32Ptr1Ty), + ConstantExpr::getAddrSpaceCast(NullInt32Ptr1, Int32PtrTy)); } #define CHECK(x, y) { \