From 99203241df4d73e569e9219105fec76919f07c19 Mon Sep 17 00:00:00 2001 From: Michal Paszkowski Date: Sat, 7 Jan 2023 15:25:53 +0100 Subject: [PATCH] [SPIR-V] Map IR function pointers to registers in ModuleAnalysis SPIRVModuleAnalysis collects module and external function registers (usually result of OpFunction) for use when emitting OpFunctionCall. This patch makes the mapping between the functions and registers using pointers (instead of name strings) to ensure anonymous functions and calls can be resolved properly. Differential Revision: https://reviews.llvm.org/D140548 --- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 19 ++++++------ llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h | 12 ++++---- llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 7 ----- llvm/lib/Target/SPIRV/SPIRVUtils.h | 2 -- .../SPIRV/function/internal-anonymous-function.ll | 20 ------------ .../SPIRV/function/multiple-anonymous-functions.ll | 36 ++++++++++++++++++++++ 6 files changed, 51 insertions(+), 45 deletions(-) delete mode 100644 llvm/test/CodeGen/SPIRV/function/internal-anonymous-function.ll create mode 100644 llvm/test/CodeGen/SPIRV/function/multiple-anonymous-functions.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index d7f6205..af48d51 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -92,7 +92,7 @@ void SPIRVModuleAnalysis::setBaseInfo(const Module &M) { MAI.MS[i].clear(); MAI.RegisterAliasTable.clear(); MAI.InstrsToDelete.clear(); - MAI.FuncNameMap.clear(); + MAI.FuncMap.clear(); MAI.GlobalVarList.clear(); MAI.ExtInstSetMap.clear(); MAI.Reqs.clear(); @@ -279,12 +279,12 @@ static bool findSameInstrInMS(const MachineInstr &A, return false; } -// Look for IDs declared with Import linkage, and map the imported name string +// Look for IDs declared with Import linkage, and map the corresponding function // to the register defining that variable (which will usually be the result of // an OpFunction). This lets us call externally imported functions using // the correct ID registers. void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI, - const Function &F) { + const Function *F) { if (MI.getOpcode() == SPIRV::OpDecorate) { // If it's got Import linkage. auto Dec = MI.getOperand(1).getImm(); @@ -292,10 +292,10 @@ void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI, auto Lnk = MI.getOperand(MI.getNumOperands() - 1).getImm(); if (Lnk == static_cast(SPIRV::LinkageType::Import)) { // Map imported function name to function ID register. - std::string Name = getStringImm(MI, 2); + const Function *ImportedFunc = + F->getParent()->getFunction(getStringImm(MI, 2)); Register Target = MI.getOperand(0).getReg(); - // TODO: check defs from different MFs. - MAI.FuncNameMap[Name] = MAI.getRegisterAlias(MI.getMF(), Target); + MAI.FuncMap[ImportedFunc] = MAI.getRegisterAlias(MI.getMF(), Target); } } } else if (MI.getOpcode() == SPIRV::OpFunction) { @@ -303,8 +303,7 @@ void SPIRVModuleAnalysis::collectFuncNames(MachineInstr &MI, Register Reg = MI.defs().begin()->getReg(); Register GlobalReg = MAI.getRegisterAlias(MI.getMF(), Reg); assert(GlobalReg.isValid()); - // TODO: check that it does not conflict with existing entries. - MAI.FuncNameMap[getFunctionGlobalIdentifier(&F)] = GlobalReg; + MAI.FuncMap[F] = GlobalReg; } } @@ -343,13 +342,13 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) { collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints); } else if (TII->isDecorationInstr(MI)) { collectOtherInstr(MI, MAI, SPIRV::MB_Annotations); - collectFuncNames(MI, *F); + collectFuncNames(MI, &*F); } else if (TII->isConstantInstr(MI)) { // Now OpSpecConstant*s are not in DT, // but they need to be collected anyway. collectOtherInstr(MI, MAI, SPIRV::MB_TypeConstVars); } else if (OpCode == SPIRV::OpFunction) { - collectFuncNames(MI, *F); + collectFuncNames(MI, &*F); } else if (OpCode == SPIRV::OpTypeForwardPointer) { collectOtherInstr(MI, MAI, SPIRV::MB_TypeConstVars, false); } diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h index c99fdeb..a8b659c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h @@ -131,8 +131,8 @@ struct ModuleAnalysisInfo { DenseMap ExtInstSetMap; // Contains the list of all global OpVariables in the module. SmallVector GlobalVarList; - // Maps function names to coresponding function ID registers. - StringMap FuncNameMap; + // Maps functions to corresponding function ID registers. + DenseMap FuncMap; // The set contains machine instructions which are necessary // for correct MIR but will not be emitted in function bodies. DenseSet InstrsToDelete; @@ -152,9 +152,9 @@ struct ModuleAnalysisInfo { Register getFuncReg(const Function *F) { assert(F && "Function is null"); - auto FuncReg = FuncNameMap.find(getFunctionGlobalIdentifier(F)); - assert(FuncReg != FuncNameMap.end() && "Cannot find function Id"); - return FuncReg->second; + auto FuncPtrRegPair = FuncMap.find(F); + assert(FuncPtrRegPair != FuncMap.end() && "Cannot find function ID"); + return FuncPtrRegPair->second; } Register getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; } InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; } @@ -211,7 +211,7 @@ private: std::function Pred, bool UsePreOrder); void processDefInstrs(const Module &M); - void collectFuncNames(MachineInstr &MI, const Function &F); + void collectFuncNames(MachineInstr &MI, const Function *F); void processOtherInstrs(const Module &M); void numberRegistersGlobally(const Module &M); diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index 0f024ef..9dcddf5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -354,11 +354,4 @@ bool isSpecialOpaqueType(const Type *Ty) { return isOpenCLBuiltinType(SType) || isSPIRVBuiltinType(SType); return false; } - -std::string getFunctionGlobalIdentifier(const Function *F) { - StringRef Name = F->hasName() ? F->getName() : ".anonymous"; - GlobalValue::LinkageTypes Linkage = F->getLinkage(); - StringRef ModuleFileName = F->getParent()->getSourceFileName(); - return GlobalValue::getGlobalIdentifier(Name, Linkage, ModuleFileName); -} } // namespace llvm diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index 09e14a0..7c19361 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -94,7 +94,5 @@ const Type *getTypedPtrEltType(const Type *Type); // Check if given LLVM type is a special opaque builtin type. bool isSpecialOpaqueType(const Type *Ty); - -std::string getFunctionGlobalIdentifier(const Function *F); } // namespace llvm #endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H diff --git a/llvm/test/CodeGen/SPIRV/function/internal-anonymous-function.ll b/llvm/test/CodeGen/SPIRV/function/internal-anonymous-function.ll deleted file mode 100644 index 7610919..0000000 --- a/llvm/test/CodeGen/SPIRV/function/internal-anonymous-function.ll +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s - -;; Types: -; CHECK-DAG: %[[#F32:]] = OpTypeFloat 32 -; CHECK-DAG: %[[#FNF32:]] = OpTypeFunction %[[#F32]] %[[#F32]] -;; Function decl: -; CHECK: %[[#ANON:]] = OpFunction %[[#F32]] None %[[#FNF32]] -; CHECK-NEXT: OpFunctionParameter %[[#F32]] -; CHECK-NEXT: OpLabel -; CHECK-NEXT: OpReturnValue -; CHECK-NEXT: OpFunctionEnd -define internal spir_func float @0(float %a) { - ret float %a -} - -; CHECK: OpFunctionCall %[[#F32]] %[[#ANON]] -define spir_kernel void @foo(float %a) { - %1 = call spir_func float @0(float %a) - ret void -} diff --git a/llvm/test/CodeGen/SPIRV/function/multiple-anonymous-functions.ll b/llvm/test/CodeGen/SPIRV/function/multiple-anonymous-functions.ll new file mode 100644 index 0000000..93bdbe3 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/function/multiple-anonymous-functions.ll @@ -0,0 +1,36 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s + +;; Types: +; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 +; CHECK-DAG: %[[#F32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#FNI32:]] = OpTypeFunction %[[#I32]] %[[#I32]] +; CHECK-DAG: %[[#FNF32:]] = OpTypeFunction %[[#F32]] %[[#F32]] + +;; Function declarations: +; CHECK: %[[#ANON0:]] = OpFunction %[[#I32]] None %[[#FNI32]] +; CHECK-NEXT: OpFunctionParameter %[[#I32]] +; CHECK-NEXT: OpLabel +; CHECK-NEXT: OpReturnValue +; CHECK-NEXT: OpFunctionEnd +define internal spir_func i32 @0(i32 %a) { + ret i32 %a +} + +; CHECK: %[[#ANON1:]] = OpFunction %[[#F32]] None %[[#FNF32]] +; CHECK-NEXT: OpFunctionParameter %[[#F32]] +; CHECK-NEXT: OpLabel +; CHECK-NEXT: OpReturnValue +; CHECK-NEXT: OpFunctionEnd +define internal spir_func float @1(float %a) { + ret float %a +} + +;; Calls: +; CHECK: OpFunctionCall %[[#I32]] %[[#ANON0]] +; CHECK: OpFunctionCall %[[#F32]] %[[#ANON1]] +define spir_kernel void @foo(i32 %a) { + %call1 = call spir_func i32 @0(i32 %a) + %b = sitofp i32 %a to float + %call2 = call spir_func float @1(float %b) + ret void +} -- 2.7.4