[llvm-branch-commits] [llvm] Reapply "[SPIRV] Emit intrinsics for globals only in function that references them (#178143 (#179268)) (PR #182552)
Konrad Kleine via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Feb 23 05:57:58 PST 2026
================
@@ -62,6 +62,94 @@ namespace llvm::SPIRV {
} // namespace llvm::SPIRV
namespace {
+// This class keeps track of which functions reference which global variables.
+class GlobalVariableUsers {
+ template <typename T1, typename T2>
+ using OneToManyMapTy = DenseMap<T1, SmallPtrSet<T2, 4>>;
+
+ OneToManyMapTy<const GlobalVariable *, const Function *> GlobalIsUsedByFun;
+
+ void collectGlobalUsers(
+ const GlobalVariable *GV,
+ OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
+ &GlobalIsUsedByGlobal) {
+ SmallVector<const Value *> Stack = {GV->user_begin(), GV->user_end()};
+ while (!Stack.empty()) {
+ const Value *V = Stack.pop_back_val();
+
+ if (const Instruction *I = dyn_cast<Instruction>(V)) {
+ GlobalIsUsedByFun[GV].insert(I->getFunction());
+ continue;
+ }
+
+ if (const GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
+ GlobalIsUsedByGlobal[GV].insert(UserGV);
+ continue;
+ }
+
+ if (const Constant *C = dyn_cast<Constant>(V))
+ Stack.append(C->user_begin(), C->user_end());
+ }
+ }
+
+ bool propagateGlobalToGlobalUsers(
+ OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
+ &GlobalIsUsedByGlobal) {
+ SmallVector<const GlobalVariable *> OldUsersGlobals;
+ bool Changed = false;
+ for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
+ OldUsersGlobals.assign(UserGlobals.begin(), UserGlobals.end());
+ for (const GlobalVariable *UserGV : OldUsersGlobals) {
+ auto It = GlobalIsUsedByGlobal.find(UserGV);
+ if (It == GlobalIsUsedByGlobal.end())
+ continue;
+ Changed |= set_union(UserGlobals, It->second);
+ }
+ }
+ return Changed;
+ }
+
+ void propagateGlobalToFunctionReferences(
+ OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
+ &GlobalIsUsedByGlobal) {
+ for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
+ auto &UserFunctions = GlobalIsUsedByFun[GV];
+ for (const GlobalVariable *UserGV : UserGlobals) {
+ auto It = GlobalIsUsedByFun.find(UserGV);
+ if (It == GlobalIsUsedByFun.end())
+ continue;
+ set_union(UserFunctions, It->second);
+ }
+ }
+ }
+
+public:
+ void init(Module &M) {
+ // Collect which global variables are referenced by which global variables
+ // and which functions reference each global variables.
+ OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
+ GlobalIsUsedByGlobal;
+ GlobalIsUsedByFun.clear();
+ for (GlobalVariable &GV : M.globals())
+ collectGlobalUsers(&GV, GlobalIsUsedByGlobal);
+
+ // Compute indirect references by iterating until a fixed point is reached.
+ while (propagateGlobalToGlobalUsers(GlobalIsUsedByGlobal))
+ (void)0;
+
+ propagateGlobalToFunctionReferences(GlobalIsUsedByGlobal);
+ }
+
+ const auto &getTransitiveUserFunctions(const GlobalVariable &GV) const {
+ auto It = GlobalIsUsedByFun.find(&GV);
+ if (It != GlobalIsUsedByFun.end())
+ return It->second;
+
+ using FunctionSetType = typename decltype(GlobalIsUsedByFun)::mapped_type;
+ const static FunctionSetType Empty;
+ return Empty;
+ }
----------------
kwk wrote:
Hey, this turned out to be a more constructive outcome than I anticipated. Thank you.
https://github.com/llvm/llvm-project/pull/182552
More information about the llvm-branch-commits
mailing list