[llvm] [SPIRV] Fix indirect calls for function pointers (PR #111159)
Vyacheslav Levytskyy via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 4 11:46:37 PDT 2024
https://github.com/VyacheslavLevytskyy updated https://github.com/llvm/llvm-project/pull/111159
>From e0c003b1986dd61a97b09f7d2801dbca01619e80 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 4 Oct 2024 06:54:34 -0700
Subject: [PATCH 1/3] fix indirect calls for function pointers
---
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 10 +++
llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 8 +++
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 53 +++++++++++++++-
llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 14 +++++
llvm/lib/Target/SPIRV/SPIRVUtils.h | 3 +
.../fp-simple-hierarchy.ll | 63 +++++++++++++++++++
6 files changed, 149 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index 55b41627802096..b078b22c7057ef 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -600,6 +600,16 @@ void SPIRVAsmPrinter::outputModuleSections() {
}
bool SPIRVAsmPrinter::doInitialization(Module &M) {
+ // Discard the internal service function
+ for (Function &F : M) {
+ if (!F.getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
+ continue;
+ getAnalysis<MachineModuleInfoWrapperPass>()
+ .getMMI()
+ .deleteMachineFunctionFor(F);
+ break;
+ }
+
ModuleSectionsEmitted = false;
// We need to call the parent's one explicitly.
return AsmPrinter::doInitialization(M);
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index 27a9cb0ba9b8c0..59256e81951d73 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -36,6 +36,10 @@ bool SPIRVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const {
+ // Discard the internal service function
+ if (FLI.Fn && FLI.Fn->getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
+ return true;
+
// Maybe run postponed production of types for function pointers
if (IndirectCalls.size() > 0) {
produceIndirectPtrTypes(MIRBuilder);
@@ -280,6 +284,10 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
const Function &F,
ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {
+ // Discard the internal service function
+ if (F.getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
+ return true;
+
assert(GR && "Must initialize the SPIRV type registry before lowering args.");
GR->setCurrentFunc(MIRBuilder.getMF());
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 370df24bc7af9e..43e70ae2032dfe 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -147,6 +147,10 @@ class SPIRVEmitIntrinsics
void replaceWithPtrcasted(Instruction *CI, Type *NewElemTy, Type *KnownElemTy,
CallInst *AssignCI);
+ bool runOnFunction(Function &F);
+ bool postprocessTypes();
+ bool processFunctionPointers(Module &M);
+
public:
static char ID;
SPIRVEmitIntrinsics() : ModulePass(ID) {
@@ -173,8 +177,6 @@ class SPIRVEmitIntrinsics
StringRef getPassName() const override { return "SPIRV emit intrinsics"; }
bool runOnModule(Module &M) override;
- bool runOnFunction(Function &F);
- bool postprocessTypes();
void getAnalysisUsage(AnalysisUsage &AU) const override {
ModulePass::getAnalysisUsage(AU);
@@ -1825,10 +1827,57 @@ bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
}
Changed |= postprocessTypes();
+ Changed |= processFunctionPointers(M);
return Changed;
}
+bool SPIRVEmitIntrinsics::processFunctionPointers(Module &M) {
+ bool IsExt = false;
+ SmallVector<Function*> Worklist;
+ for (auto &F : M) {
+ if (!IsExt) {
+ if (!TM->getSubtarget<SPIRVSubtarget>(F).canUseExtension(
+ SPIRV::Extension::SPV_INTEL_function_pointers))
+ return false;
+ IsExt = true;
+ }
+ if (!F.isDeclaration() || F.isIntrinsic())
+ continue;
+ for (User *U : F.users()) {
+ CallInst *CI = dyn_cast<CallInst>(U);
+ if (!CI || CI->getCalledFunction() != &F) {
+ Worklist.push_back(&F);
+ break;
+ }
+ }
+ }
+ if (Worklist.empty())
+ return false;
+
+ std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
+ if (!getVacantFunctionName(M, ServiceFunName))
+ report_fatal_error(
+ "cannot allocate a name for the internal service function");
+ LLVMContext &Ctx = M.getContext();
+ Function *SF =
+ Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {}, false),
+ GlobalValue::PrivateLinkage, ServiceFunName, M);
+ SF->addFnAttr(SPIRV_BACKEND_SERVICE_FUN_NAME, "");
+ BasicBlock *BB = BasicBlock::Create(Ctx, "entry", SF);
+ IRBuilder<> IRB(BB);
+
+ for (Function *F : Worklist) {
+ SmallVector<Value *> Args;
+ for (const auto &Arg : F->args())
+ Args.push_back(PoisonValue::get(Arg.getType()));
+ IRB.CreateCall(F, Args);
+ }
+ IRB.CreateRetVoid();
+
+ return true;
+}
+
ModulePass *llvm::createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM) {
return new SPIRVEmitIntrinsics(TM);
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index d204a8ac7975d8..dff33b16b9cfcf 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -598,4 +598,18 @@ MachineInstr *getVRegDef(MachineRegisterInfo &MRI, Register Reg) {
return MaybeDef;
}
+bool getVacantFunctionName(Module &M, std::string &Name) {
+ // It's a bit of paranoia, but still we don't want to have even a chance that
+ // the loop will work for too long.
+ constexpr unsigned MaxIters = 1024;
+ for (unsigned I = 0; I < MaxIters; ++I) {
+ std::string OrdName = Name + Twine(I).str();
+ if (!M.getFunction(OrdName)) {
+ Name = OrdName;
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index f7e8a827c2767f..83e717e6ea58fd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -341,5 +341,8 @@ inline const Type *unifyPtrType(const Type *Ty) {
MachineInstr *getVRegDef(MachineRegisterInfo &MRI, Register Reg);
+#define SPIRV_BACKEND_SERVICE_FUN_NAME "__spirv_backend_service_fun"
+bool getVacantFunctionName(Module &M, std::string &Name);
+
} // namespace llvm
#endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll
new file mode 100644
index 00000000000000..5141259f63bdd7
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll
@@ -0,0 +1,63 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpFunction
+
+%classid = type { %arrayid }
+%arrayid = type { [1 x i64] }
+%struct.obj_storage_t = type { %storage }
+%storage = type { [8 x i8] }
+
+ at _ZTV12IncrementBy8 = linkonce_odr dso_local unnamed_addr addrspace(1) constant { [3 x ptr addrspace(4)] } { [3 x ptr addrspace(4)] [ptr addrspace(4) null, ptr addrspace(4) null, ptr addrspace(4) addrspacecast (ptr @_ZN12IncrementBy89incrementEPi to ptr addrspace(4))] }, align 8
+ at _ZTV13BaseIncrement = linkonce_odr dso_local unnamed_addr addrspace(1) constant { [3 x ptr addrspace(4)] } { [3 x ptr addrspace(4)] [ptr addrspace(4) null, ptr addrspace(4) null, ptr addrspace(4) addrspacecast (ptr @_ZN13BaseIncrement9incrementEPi to ptr addrspace(4))] }, align 8
+ at _ZTV12IncrementBy4 = linkonce_odr dso_local unnamed_addr addrspace(1) constant { [3 x ptr addrspace(4)] } { [3 x ptr addrspace(4)] [ptr addrspace(4) null, ptr addrspace(4) null, ptr addrspace(4) addrspacecast (ptr @_ZN12IncrementBy49incrementEPi to ptr addrspace(4))] }, align 8
+ at _ZTV12IncrementBy2 = linkonce_odr dso_local unnamed_addr addrspace(1) constant { [3 x ptr addrspace(4)] } { [3 x ptr addrspace(4)] [ptr addrspace(4) null, ptr addrspace(4) null, ptr addrspace(4) addrspacecast (ptr @_ZN12IncrementBy29incrementEPi to ptr addrspace(4))] }, align 8
+
+define weak_odr dso_local spir_kernel void @foo(ptr addrspace(1) noundef align 8 %_arg_StorageAcc, ptr noundef byval(%classid) align 8 %_arg_StorageAcc3, i32 noundef %_arg_TestCase, ptr addrspace(1) noundef align 4 %_arg_DataAcc) {
+entry:
+ %0 = load i64, ptr %_arg_StorageAcc3, align 8
+ %add.ptr.i = getelementptr inbounds %struct.obj_storage_t, ptr addrspace(1) %_arg_StorageAcc, i64 %0
+ %arrayidx.ascast.i = addrspacecast ptr addrspace(1) %add.ptr.i to ptr addrspace(4)
+ %cmp.i = icmp ugt i32 %_arg_TestCase, 3
+ br i1 %cmp.i, label %entry.critedge, label %if.end.1
+
+entry.critedge: ; preds = %entry
+ %vtable.i.pre = load ptr addrspace(4), ptr addrspace(4) null, align 8
+ br label %exit
+
+if.end.1: ; preds = %entry
+ switch i32 %_arg_TestCase, label %if.end.5 [
+ i32 0, label %if.end.2
+ i32 1, label %if.end.3
+ i32 2, label %if.end.4
+ ]
+
+if.end.5: ; preds = %if.end.1
+ store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV12IncrementBy8, i64 16), ptr addrspace(1) %add.ptr.i, align 8
+ br label %exit
+
+if.end.4: ; preds = %if.end.1
+ store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV12IncrementBy4, i64 16), ptr addrspace(1) %add.ptr.i, align 8
+ br label %exit
+
+if.end.3: ; preds = %if.end.1
+ store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV12IncrementBy2, i64 16), ptr addrspace(1) %add.ptr.i, align 8
+ br label %exit
+
+if.end.2: ; preds = %if.end.1
+ store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV13BaseIncrement, i64 16), ptr addrspace(1) %add.ptr.i, align 8
+ br label %exit
+
+exit: ; preds = %if.end.2, %if.end.3, %if.end.4, %if.end.5, %entry.critedge
+ %vtable.i = phi ptr addrspace(4) [ %vtable.i.pre, %entry.critedge ], [ inttoptr (i64 ptrtoint (ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV12IncrementBy8, i64 16) to i64) to ptr addrspace(4)), %if.end.5 ], [ inttoptr (i64 ptrtoint (ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV12IncrementBy4, i64 16) to i64) to ptr addrspace(4)), %if.end.4 ], [ inttoptr (i64 ptrtoint (ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV12IncrementBy2, i64 16) to i64) to ptr addrspace(4)), %if.end.3 ], [ inttoptr (i64 ptrtoint (ptr addrspace(1) getelementptr inbounds inrange(-16, 8) (i8, ptr addrspace(1) @_ZTV13BaseIncrement, i64 16) to i64) to ptr addrspace(4)), %if.end.2 ]
+ %retval.0.i = phi ptr addrspace(4) [ null, %entry.critedge ], [ %arrayidx.ascast.i, %if.end.5 ], [ %arrayidx.ascast.i, %if.end.4 ], [ %arrayidx.ascast.i, %if.end.3 ], [ %arrayidx.ascast.i, %if.end.2 ]
+ %1 = addrspacecast ptr addrspace(1) %_arg_DataAcc to ptr addrspace(4)
+ %2 = load ptr addrspace(4), ptr addrspace(4) %vtable.i, align 8
+ tail call spir_func addrspace(4) void %2(ptr addrspace(4) noundef align 8 dereferenceable_or_null(8) %retval.0.i, ptr addrspace(4) noundef %1)
+ ret void
+}
+
+declare dso_local spir_func void @_ZN13BaseIncrement9incrementEPi(ptr addrspace(4) noundef align 8 dereferenceable_or_null(8), ptr addrspace(4) noundef)
+declare dso_local spir_func void @_ZN12IncrementBy29incrementEPi(ptr addrspace(4) noundef align 8 dereferenceable_or_null(8), ptr addrspace(4) noundef)
+declare dso_local spir_func void @_ZN12IncrementBy49incrementEPi(ptr addrspace(4) noundef align 8 dereferenceable_or_null(8), ptr addrspace(4) noundef)
+declare dso_local spir_func void @_ZN12IncrementBy89incrementEPi(ptr addrspace(4) noundef align 8 dereferenceable_or_null(8), ptr addrspace(4) noundef)
>From 5c611cc8de60f4583610d0734623af3cfb44d1e4 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 4 Oct 2024 11:21:08 -0700
Subject: [PATCH 2/3] do not emit anything if it's an internal service function
---
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 18 +++++++-----------
llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 17 +++++++++++++++--
.../fp-simple-hierarchy.ll | 2 +-
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index b078b22c7057ef..c0795146e9b923 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -149,6 +149,10 @@ void SPIRVAsmPrinter::outputOpFunctionEnd() {
// Emit OpFunctionEnd at the end of MF and clear BBNumToRegMap.
void SPIRVAsmPrinter::emitFunctionBodyEnd() {
+ // Do not emit anything if it's an internal service function.
+ if (MF->getFunction().getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
+ return;
+
outputOpFunctionEnd();
MAI->BBNumToRegMap.clear();
}
@@ -162,7 +166,9 @@ void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
}
void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
- assert(!MBB.empty() && "MBB is empty!");
+ // Do not emit anything if it's an internal service function.
+ if (MBB.empty())
+ return;
// If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
// OpLabel should be output after them.
@@ -600,16 +606,6 @@ void SPIRVAsmPrinter::outputModuleSections() {
}
bool SPIRVAsmPrinter::doInitialization(Module &M) {
- // Discard the internal service function
- for (Function &F : M) {
- if (!F.getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
- continue;
- getAnalysis<MachineModuleInfoWrapperPass>()
- .getMMI()
- .deleteMachineFunctionFor(F);
- break;
- }
-
ModuleSectionsEmitted = false;
// We need to call the parent's one explicitly.
return AsmPrinter::doInitialization(M);
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index 59256e81951d73..f10de1d2104125 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -36,8 +36,11 @@ bool SPIRVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
const Value *Val, ArrayRef<Register> VRegs,
FunctionLoweringInfo &FLI,
Register SwiftErrorVReg) const {
- // Discard the internal service function
- if (FLI.Fn && FLI.Fn->getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
+ // Ignore if called from the internal service function
+ if (MIRBuilder.getMF()
+ .getFunction()
+ .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
+ .isValid())
return true;
// Maybe run postponed production of types for function pointers
@@ -497,6 +500,16 @@ void SPIRVCallLowering::produceIndirectPtrTypes(
bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
CallLoweringInfo &Info) const {
+ // Ignore if called from the internal service function
+ if (MIRBuilder.getMF()
+ .getFunction()
+ .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
+ .isValid()) {
+ // insert a no-op
+ MIRBuilder.buildTrap();
+ return true;
+ }
+
// Currently call returns should have single vregs.
// TODO: handle the case of multiple registers.
if (Info.OrigRet.Regs.size() > 1)
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll
index 5141259f63bdd7..0178e1192d7ea7 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll
@@ -1,4 +1,4 @@
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; CHECK: OpFunction
>From 4c4524677393b8c594d1ca14d5490bc1908ea1aa Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 4 Oct 2024 11:46:24 -0700
Subject: [PATCH 3/3] code format
---
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 4 +-
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 92 +++++++++----------
2 files changed, 49 insertions(+), 47 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index c0795146e9b923..1b85b72bc690ed 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -150,7 +150,9 @@ void SPIRVAsmPrinter::outputOpFunctionEnd() {
// Emit OpFunctionEnd at the end of MF and clear BBNumToRegMap.
void SPIRVAsmPrinter::emitFunctionBodyEnd() {
// Do not emit anything if it's an internal service function.
- if (MF->getFunction().getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME).isValid())
+ if (MF->getFunction()
+ .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
+ .isValid())
return;
outputOpFunctionEnd();
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 43e70ae2032dfe..e9dfdde24ff3ba 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1673,6 +1673,52 @@ void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) {
}
}
+bool SPIRVEmitIntrinsics::processFunctionPointers(Module &M) {
+ bool IsExt = false;
+ SmallVector<Function *> Worklist;
+ for (auto &F : M) {
+ if (!IsExt) {
+ if (!TM->getSubtarget<SPIRVSubtarget>(F).canUseExtension(
+ SPIRV::Extension::SPV_INTEL_function_pointers))
+ return false;
+ IsExt = true;
+ }
+ if (!F.isDeclaration() || F.isIntrinsic())
+ continue;
+ for (User *U : F.users()) {
+ CallInst *CI = dyn_cast<CallInst>(U);
+ if (!CI || CI->getCalledFunction() != &F) {
+ Worklist.push_back(&F);
+ break;
+ }
+ }
+ }
+ if (Worklist.empty())
+ return false;
+
+ std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
+ if (!getVacantFunctionName(M, ServiceFunName))
+ report_fatal_error(
+ "cannot allocate a name for the internal service function");
+ LLVMContext &Ctx = M.getContext();
+ Function *SF =
+ Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {}, false),
+ GlobalValue::PrivateLinkage, ServiceFunName, M);
+ SF->addFnAttr(SPIRV_BACKEND_SERVICE_FUN_NAME, "");
+ BasicBlock *BB = BasicBlock::Create(Ctx, "entry", SF);
+ IRBuilder<> IRB(BB);
+
+ for (Function *F : Worklist) {
+ SmallVector<Value *> Args;
+ for (const auto &Arg : F->args())
+ Args.push_back(PoisonValue::get(Arg.getType()));
+ IRB.CreateCall(F, Args);
+ }
+ IRB.CreateRetVoid();
+
+ return true;
+}
+
bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
if (Func.isDeclaration())
return false;
@@ -1832,52 +1878,6 @@ bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
return Changed;
}
-bool SPIRVEmitIntrinsics::processFunctionPointers(Module &M) {
- bool IsExt = false;
- SmallVector<Function*> Worklist;
- for (auto &F : M) {
- if (!IsExt) {
- if (!TM->getSubtarget<SPIRVSubtarget>(F).canUseExtension(
- SPIRV::Extension::SPV_INTEL_function_pointers))
- return false;
- IsExt = true;
- }
- if (!F.isDeclaration() || F.isIntrinsic())
- continue;
- for (User *U : F.users()) {
- CallInst *CI = dyn_cast<CallInst>(U);
- if (!CI || CI->getCalledFunction() != &F) {
- Worklist.push_back(&F);
- break;
- }
- }
- }
- if (Worklist.empty())
- return false;
-
- std::string ServiceFunName = SPIRV_BACKEND_SERVICE_FUN_NAME;
- if (!getVacantFunctionName(M, ServiceFunName))
- report_fatal_error(
- "cannot allocate a name for the internal service function");
- LLVMContext &Ctx = M.getContext();
- Function *SF =
- Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {}, false),
- GlobalValue::PrivateLinkage, ServiceFunName, M);
- SF->addFnAttr(SPIRV_BACKEND_SERVICE_FUN_NAME, "");
- BasicBlock *BB = BasicBlock::Create(Ctx, "entry", SF);
- IRBuilder<> IRB(BB);
-
- for (Function *F : Worklist) {
- SmallVector<Value *> Args;
- for (const auto &Arg : F->args())
- Args.push_back(PoisonValue::get(Arg.getType()));
- IRB.CreateCall(F, Args);
- }
- IRB.CreateRetVoid();
-
- return true;
-}
-
ModulePass *llvm::createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM) {
return new SPIRVEmitIntrinsics(TM);
}
More information about the llvm-commits
mailing list