From bca8aba44a2f414a25b55a3ba37f718113315f5f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 21 May 2016 00:14:04 +0000 Subject: [PATCH] Fix constant folding of addrspacecast of null This should not be making assumptions on the value of the casted pointer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270293 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/ConstantFold.cpp | 3 +- test/Assembler/ConstantExprFoldCast.ll | 14 +++++-- test/Transforms/InstCombine/addrspacecast.ll | 39 ++++++++++++++++++++ unittests/IR/ConstantsTest.cpp | 21 +++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index a338d01a83d..623ce701b60 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -531,7 +531,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, 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 diff --git a/test/Assembler/ConstantExprFoldCast.ll b/test/Assembler/ConstantExprFoldCast.ll index dfe840cc37d..ed32b416744 100644 --- a/test/Assembler/ConstantExprFoldCast.ll +++ b/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*) diff --git a/test/Transforms/InstCombine/addrspacecast.ll b/test/Transforms/InstCombine/addrspacecast.ll index 27f6b720d66..e375a7aa34b 100644 --- a/test/Transforms/InstCombine/addrspacecast.ll +++ b/test/Transforms/InstCombine/addrspacecast.ll @@ -145,3 +145,42 @@ end: 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 +} diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 39ae18ca5e0..6959ac85e49 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -155,6 +155,27 @@ TEST(ConstantsTest, PointerCast) { 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) { \