1//===-- SPIRVPrepareGlobals.cpp - Prepare IR SPIRV globals ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The pass transforms IR globals that cannot be trivially mapped to SPIRV
10// into something that is trival to lower.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRV.h"
15#include "SPIRVUtils.h"
16
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/IR/Module.h"
19#include "llvm/Support/Debug.h"
20
21#define DEBUG_TYPE "spirv-prepare-globals"
22
23using namespace llvm;
24
25namespace {
26
27struct SPIRVPrepareGlobals : public ModulePass {
28 static char ID;
29 SPIRVPrepareGlobals() : ModulePass(ID) {}
30
31 StringRef getPassName() const override {
32 return "SPIRV prepare global variables";
33 }
34
35 bool runOnModule(Module &M) override;
36};
37
38// The backend does not support GlobalAlias. Replace aliases with their aliasees
39// when possible and remove them from the module.
40bool tryReplaceAliasWithAliasee(GlobalAlias &GA) {
41 // According to the lang ref, aliases cannot be replaced if either the alias
42 // or the aliasee are interposable. We only replace in the case that both
43 // are not interposable.
44 if (GA.isInterposable()) {
45 LLVM_DEBUG(dbgs() << "Skipping interposable alias: " << GA.getName()
46 << "\n");
47 return false;
48 }
49
50 auto *AO = dyn_cast<GlobalObject>(Val: GA.getAliasee());
51 if (!AO) {
52 LLVM_DEBUG(dbgs() << "Skipping alias whose aliasee is not a GlobalObject: "
53 << GA.getName() << "\n");
54 return false;
55 }
56
57 if (AO->isInterposable()) {
58 LLVM_DEBUG(dbgs() << "Skipping interposable aliasee: " << AO->getName()
59 << "\n");
60 return false;
61 }
62
63 LLVM_DEBUG(dbgs() << "Replacing alias " << GA.getName()
64 << " with aliasee: " << AO->getName() << "\n");
65
66 GA.replaceAllUsesWith(V: AO);
67 if (GA.isDiscardableIfUnused()) {
68 GA.eraseFromParent();
69 }
70
71 return true;
72}
73
74bool SPIRVPrepareGlobals::runOnModule(Module &M) {
75 bool Changed = false;
76
77 for (GlobalAlias &GA : make_early_inc_range(Range: M.aliases())) {
78 Changed |= tryReplaceAliasWithAliasee(GA);
79 }
80
81 return Changed;
82}
83char SPIRVPrepareGlobals::ID = 0;
84
85} // namespace
86
87INITIALIZE_PASS(SPIRVPrepareGlobals, "prepare-globals",
88 "SPIRV prepare global variables", false, false)
89
90namespace llvm {
91ModulePass *createSPIRVPrepareGlobalsPass() {
92 return new SPIRVPrepareGlobals();
93}
94} // namespace llvm
95