Index: llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1702,10 +1702,18 @@ auto &Context = Call->getContext(); auto &DL = Call->getModule()->getDataLayout(); auto GetBaseAndOffset = [&](Value *Derived) { - assert(PointerToBase.count(Derived)); + Value *Base = nullptr; + // Optimizations in unreachable code might substitute the real pointer + // with undef, poison or null-derived constant. + if (isa(Derived)) + Base = + ConstantPointerNull::get(cast(Derived->getType())); + else { + assert(PointerToBase.count(Derived)); + Base = PointerToBase.find(Derived)->second; + } unsigned AddressSpace = Derived->getType()->getPointerAddressSpace(); unsigned IntPtrSize = DL.getPointerSizeInBits(AddressSpace); - Value *Base = PointerToBase.find(Derived)->second; Value *Base_int = Builder.CreatePtrToInt( Base, Type::getIntNTy(Context, IntPtrSize)); Value *Derived_int = Builder.CreatePtrToInt( Index: llvm/test/Transforms/RewriteStatepointsForGC/pr56493.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/RewriteStatepointsForGC/pr56493.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=rewrite-statepoints-for-gc -S < %s | FileCheck %s + +; Make sure this doesn't crash. +define void @test() gc "statepoint-example" personality i32* ()* @zot { +; CHECK-LABEL: @test( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void (i32 addrspace(1)*, i64, i32 addrspace(1)*, i64, i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i32i64p1i32i64i64f(i64 2882400000, i32 0, void (i32 addrspace(1)*, i64, i32 addrspace(1)*, i64, i64)* elementtype(void (i32 addrspace(1)*, i64, i32 addrspace(1)*, i64, i64)) @__llvm_memcpy_element_unordered_atomic_safepoint_4, i32 5, i32 0, i32 addrspace(1)* null, i64 undef, i32 addrspace(1)* null, i64 ptrtoint (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 16) to i64), i64 undef, i32 0, i32 0) [ "deopt"() ] +; CHECK-NEXT: ret void +; +bb: + call void @llvm.memcpy.element.unordered.atomic.p1i32.p1i32.i64(i32 addrspace(1)* elementtype(i32) align 8 undef, i32 addrspace(1)* elementtype(i32) align 16 bitcast (i8 addrspace(1)* getelementptr inbounds (i8, i8 addrspace(1)* null, i64 16) to i32 addrspace(1)*), i64 undef, i32 4) #3 [ "deopt"() ] + ret void +} + +declare i32* @zot() + +declare void @llvm.memcpy.element.unordered.atomic.p1i32.p1i32.i64(i32 addrspace(1)* nocapture writeonly, i32 addrspace(1)* nocapture readonly, i64, i32 immarg)