diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -315,6 +315,7 @@ CE->getType()->isPointerTy()) || CE->getOpcode() == Instruction::AddrSpaceCast) { // Pointer cast, delete any stores and memsets to the global. + // TODO: We should try to cast the Init value to the new type. Changed |= CleanupConstantGlobalUsers(CE, nullptr, DL, GetTLI); } @@ -322,6 +323,15 @@ CE->destroyConstant(); Changed = true; } + } else if (CastInst *CI = dyn_cast(U)) { + assert(CI->getType()->isPointerTy() && "Expected a pointer cast!"); + // Pointer cast, delete any stores and memsets to the global. + // TODO: We should try to cast the Init value to the new type. + Changed |= CleanupConstantGlobalUsers(CI, nullptr, DL, GetTLI); + if (CI->use_empty()) { + CI->eraseFromParent(); + Changed = true; + } } else if (GetElementPtrInst *GEP = dyn_cast(U)) { // Do not transform "gepinst (gep constexpr (GV))" here, because forming // "gepconstexpr (gep constexpr (GV))" will cause the two gep's to fold diff --git a/llvm/test/Transforms/GlobalOpt/writeonly-internal-bitcast.ll b/llvm/test/Transforms/GlobalOpt/writeonly-internal-bitcast.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/writeonly-internal-bitcast.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -globalopt %s -S -o - | FileCheck %s + +%struct.S = type { i32, [2048 x i8] } + +@DirectAccess = internal global %struct.S undef, align 4 +@CastAccess = internal global %struct.S undef, align 4 +@CastAccessConst = internal global %struct.S undef, align 4 +@ASCastAccess = internal addrspace(3) global %struct.S undef, align 4 + +define dso_local void @f(i32 %I32) { +; CHECK-LABEL: @f( +; CHECK-NEXT: ret void +; + %g0 = getelementptr inbounds %struct.S, %struct.S* @DirectAccess, i32 0, i32 1, i32 %I32 + store i8 0, i8* %g0, align 4 + %g1 = getelementptr inbounds %struct.S, %struct.S* @CastAccess, i32 0, i32 1, i32 %I32 + %bc1 = bitcast i8* %g1 to i32* + store i32 0, i32* %bc1, align 4 + %g2 = getelementptr inbounds %struct.S, %struct.S* @CastAccessConst, i32 0, i32 1, i32 42 + %bc2 = bitcast i8* %g2 to i32* + store i32 0, i32* %bc2, align 4 + %as3 = addrspacecast %struct.S addrspace(3)* @ASCastAccess to %struct.S* + %g3 = getelementptr inbounds %struct.S, %struct.S* %as3, i32 0, i32 1, i32 %I32 + %bc3 = bitcast i8* %g3 to i32* + store i32 0, i32* %bc3, align 4 + ret void +}