[llvm] 9920324 - [SPIR-V] Map IR function pointers to registers in ModuleAnalysis

Michal Paszkowski via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 7 06:40:20 PST 2023


Author: Michal Paszkowski
Date: 2023-01-07T15:38:01+01:00
New Revision: 99203241df4d73e569e9219105fec76919f07c19

URL: https://github.com/llvm/llvm-project/commit/99203241df4d73e569e9219105fec76919f07c19
DIFF: https://github.com/llvm/llvm-project/commit/99203241df4d73e569e9219105fec76919f07c19.diff

LOG: [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

Added: 
    llvm/test/CodeGen/SPIRV/function/multiple-anonymous-functions.ll

Modified: 
    llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
    llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
    llvm/lib/Target/SPIRV/SPIRVUtils.cpp
    llvm/lib/Target/SPIRV/SPIRVUtils.h

Removed: 
    llvm/test/CodeGen/SPIRV/function/internal-anonymous-function.ll


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index d7f620516df6b..af48d51a056f9 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<unsigned>(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 
diff erent 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 c99fdeb5ae364..a8b659ce3957f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
@@ -131,8 +131,8 @@ struct ModuleAnalysisInfo {
   DenseMap<unsigned, Register> ExtInstSetMap;
   // Contains the list of all global OpVariables in the module.
   SmallVector<MachineInstr *, 4> GlobalVarList;
-  // Maps function names to coresponding function ID registers.
-  StringMap<Register> FuncNameMap;
+  // Maps functions to corresponding function ID registers.
+  DenseMap<const Function *, Register> FuncMap;
   // The set contains machine instructions which are necessary
   // for correct MIR but will not be emitted in function bodies.
   DenseSet<MachineInstr *> 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 @@ struct SPIRVModuleAnalysis : public ModulePass {
       std::function<bool(const SPIRV::DTSortableEntry *)> 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 0f024efdc329d..9dcddf5f5e34e 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 09e14a0f84a3a..7c193611a8574 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 761091924d56b..0000000000000
--- 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 0000000000000..93bdbe3c1c211
--- /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
+}


        


More information about the llvm-commits mailing list