Index: lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -399,15 +399,37 @@ return true; } +static bool isCallPromotable(CallInst *CI) { + // TODO: We might be able to handle some cases where the callee is a + // constantexpr bitcast of a function. + if (!CI->getCalledFunction()) + return false; + + IntrinsicInst *II = dyn_cast(CI); + if (!II) + return false; + + switch (II->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memset: + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + case Intrinsic::invariant_group_barrier: + return true; + default: + return false; + } +} + static bool collectUsesWithPtrTypes(Value *Val, std::vector &WorkList) { - bool Success = true; for (User *User : Val->users()) { - if(std::find(WorkList.begin(), WorkList.end(), User) != WorkList.end()) + if (std::find(WorkList.begin(), WorkList.end(), User) != WorkList.end()) continue; + if (CallInst *CI = dyn_cast(User)) { - // TODO: We might be able to handle some cases where the callee is a - // constantexpr bitcast of a function. - if (!CI->getCalledFunction()) + if (!isCallPromotable(CI)) return false; WorkList.push_back(User); @@ -429,10 +451,11 @@ continue; WorkList.push_back(User); - - Success &= collectUsesWithPtrTypes(User, WorkList); + if (!collectUsesWithPtrTypes(User, WorkList)) + return false; } - return Success; + + return true; } void AMDGPUPromoteAlloca::visitAlloca(AllocaInst &I) { @@ -521,6 +544,11 @@ IntrinsicInst *Intr = dyn_cast(Call); if (!Intr) { + // FIXME: What is this for? It doesn't make sense to promote arbitrary + // function calls. If the call is to a defined function that can also be + // promoted, we should be able to do this once that function is also + // rewritten. + std::vector ArgTypes; for (unsigned ArgIdx = 0, ArgEnd = Call->getNumArgOperands(); ArgIdx != ArgEnd; ++ArgIdx) { Index: test/CodeGen/AMDGPU/promote-alloca-unhandled-intrinsic.ll =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/promote-alloca-unhandled-intrinsic.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -mtriple=amdgcn-unknown-amdhsa < %s | FileCheck %s + +; This is just an arbitrary intrinisic that shouldn't ever need to be +; handled to ensure it doesn't crash. + +declare i32 @llvm.setjmp(i8*) #2 +declare void @eh.sjlj.functioncontext(i8*) #2 + +; CHECK-LABEL: @try_promote_unhandled_intrinsic( +; CHECK: alloca +; CHECK: call void @eh.sjlj.functioncontext(i8* %tmp1) +define void @try_promote_unhandled_intrinsic(i32 addrspace(1)* %arg) #2 { +bb: + %tmp = alloca i32, align 4 + %tmp1 = bitcast i32* %tmp to i8* + %tmp2 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i64 1 + %tmp3 = load i32, i32 addrspace(1)* %tmp2 + store i32 %tmp3, i32* %tmp + call void @eh.sjlj.functioncontext(i8* %tmp1) + ret void +} + +attributes #0 = { argmemonly nounwind } +attributes #1 = { nounwind readnone } +attributes #2 = { nounwind }