AMDGPU: Whitelist handled intrinsics
We shouldn't crash on unhandled intrinsics. Also simplify failure handling in loop. llvm-svn: 259546
This commit is contained in:
parent
853a1fc6d9
commit
ad1348459f
|
@ -399,15 +399,37 @@ static bool tryPromoteAllocaToVector(AllocaInst *Alloca) {
|
||||||
return true;
|
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<IntrinsicInst>(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<Value*> &WorkList) {
|
static bool collectUsesWithPtrTypes(Value *Val, std::vector<Value*> &WorkList) {
|
||||||
bool Success = true;
|
|
||||||
for (User *User : Val->users()) {
|
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;
|
continue;
|
||||||
|
|
||||||
if (CallInst *CI = dyn_cast<CallInst>(User)) {
|
if (CallInst *CI = dyn_cast<CallInst>(User)) {
|
||||||
// TODO: We might be able to handle some cases where the callee is a
|
if (!isCallPromotable(CI))
|
||||||
// constantexpr bitcast of a function.
|
|
||||||
if (!CI->getCalledFunction())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
WorkList.push_back(User);
|
WorkList.push_back(User);
|
||||||
|
@ -429,10 +451,11 @@ static bool collectUsesWithPtrTypes(Value *Val, std::vector<Value*> &WorkList) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
WorkList.push_back(User);
|
WorkList.push_back(User);
|
||||||
|
if (!collectUsesWithPtrTypes(User, WorkList))
|
||||||
Success &= collectUsesWithPtrTypes(User, WorkList);
|
return false;
|
||||||
}
|
}
|
||||||
return Success;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMDGPUPromoteAlloca::visitAlloca(AllocaInst &I) {
|
void AMDGPUPromoteAlloca::visitAlloca(AllocaInst &I) {
|
||||||
|
@ -521,6 +544,11 @@ void AMDGPUPromoteAlloca::visitAlloca(AllocaInst &I) {
|
||||||
|
|
||||||
IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(Call);
|
IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(Call);
|
||||||
if (!Intr) {
|
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<Type*> ArgTypes;
|
std::vector<Type*> ArgTypes;
|
||||||
for (unsigned ArgIdx = 0, ArgEnd = Call->getNumArgOperands();
|
for (unsigned ArgIdx = 0, ArgEnd = Call->getNumArgOperands();
|
||||||
ArgIdx != ArgEnd; ++ArgIdx) {
|
ArgIdx != ArgEnd; ++ArgIdx) {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
; 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 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 }
|
Loading…
Reference in New Issue