blob: d520d54a6a4e897a00363c8d43b208c3044253ca [file] [log] [blame]
Kévin Petitbbbda972020-03-03 19:16:31 +00001// Copyright 2020 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/Module.h"
19#include "llvm/Pass.h"
20#include "llvm/Transforms/Utils/Cloning.h"
21
22#include "clspv/AddressSpace.h"
23#include "clspv/Option.h"
24#include "clspv/PushConstant.h"
25
26#include "Constants.h"
27#include "Passes.h"
28#include "PushConstant.h"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "declarepushconstants"
33
34namespace {
35struct DeclarePushConstantsPass : public ModulePass {
36 static char ID;
37 DeclarePushConstantsPass() : ModulePass(ID) {}
38
Kévin Petit0936e292020-03-16 15:10:37 +000039 bool shouldDeclareEnqueuedLocalSize(Module &M);
Kévin Petit21c23c62020-04-29 01:38:28 +010040 bool shouldDeclareGlobalSize(Module &M);
41 bool shouldDeclareRegionOffset(Module &M);
42 bool shouldDeclareNumWorkgroups(Module &M);
43 bool shouldDeclareRegionGroupOffset(Module &M);
Kévin Petit0936e292020-03-16 15:10:37 +000044
Kévin Petitbbbda972020-03-03 19:16:31 +000045 bool runOnModule(Module &M) override;
46};
47} // namespace
48
49char DeclarePushConstantsPass::ID = 0;
50INITIALIZE_PASS(DeclarePushConstantsPass, "DeclarePushConstants",
51 "Declare push constants", false, false)
52
53namespace clspv {
54ModulePass *createDeclarePushConstantsPass() {
55 return new DeclarePushConstantsPass();
56}
57} // namespace clspv
58
Kévin Petit0936e292020-03-16 15:10:37 +000059bool DeclarePushConstantsPass::shouldDeclareEnqueuedLocalSize(Module &M) {
alan-bakerc4579bb2020-04-29 14:15:50 -040060 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
Kévin Petit0936e292020-03-16 15:10:37 +000061 bool isUsed = M.getFunction("_Z23get_enqueued_local_sizej") != nullptr;
62 return isEnabled && isUsed;
63}
64
Kévin Petit21c23c62020-04-29 01:38:28 +010065bool DeclarePushConstantsPass::shouldDeclareGlobalSize(Module &M) {
66 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
67 bool isUsed = M.getFunction("_Z15get_global_sizej") != nullptr;
68 return isEnabled && isUsed;
69}
70
71bool DeclarePushConstantsPass::shouldDeclareRegionOffset(Module &M) {
72 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
73 bool isUsed = M.getFunction("_Z13get_global_idj") != nullptr;
74 return isEnabled && isUsed;
75}
76
77bool DeclarePushConstantsPass::shouldDeclareNumWorkgroups(Module &M) {
78 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
79 bool isUsed = M.getFunction("_Z14get_num_groupsj") != nullptr;
80 return isEnabled && isUsed;
81}
82
83bool DeclarePushConstantsPass::shouldDeclareRegionGroupOffset(Module &M) {
84 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
85 bool isUsed = M.getFunction("_Z12get_group_idj") != nullptr;
86 return isEnabled && isUsed;
87}
88
Kévin Petitbbbda972020-03-03 19:16:31 +000089bool DeclarePushConstantsPass::runOnModule(Module &M) {
90
91 bool changed = false;
92
93 std::vector<clspv::PushConstant> PushConstants;
94
95 auto &C = M.getContext();
96
alan-bakere1996972020-05-04 08:38:12 -040097 if (clspv::ShouldDeclareGlobalOffsetPushConstant(M)) {
Kévin Petitbbbda972020-03-03 19:16:31 +000098 PushConstants.emplace_back(clspv::PushConstant::GlobalOffset);
99 }
100
Kévin Petit0936e292020-03-16 15:10:37 +0000101 if (shouldDeclareEnqueuedLocalSize(M)) {
Kévin Petit1af73be2020-03-11 17:53:44 +0000102 PushConstants.push_back(clspv::PushConstant::EnqueuedLocalSize);
103 }
104
Kévin Petit21c23c62020-04-29 01:38:28 +0100105 if (shouldDeclareGlobalSize(M)) {
106 PushConstants.push_back(clspv::PushConstant::GlobalSize);
107 }
108
109 if (shouldDeclareRegionOffset(M)) {
110 PushConstants.push_back(clspv::PushConstant::RegionOffset);
111 }
112
113 if (shouldDeclareNumWorkgroups(M)) {
114 PushConstants.push_back(clspv::PushConstant::NumWorkgroups);
115 }
116
117 if (shouldDeclareRegionGroupOffset(M)) {
118 PushConstants.push_back(clspv::PushConstant::RegionGroupOffset);
119 }
120
Kévin Petitbbbda972020-03-03 19:16:31 +0000121 if (PushConstants.size() > 0) {
122 changed = true;
123
124 std::vector<Type *> Members;
125
126 for (auto &pc : PushConstants) {
127 Members.push_back(GetPushConstantType(M, pc));
128 }
129
130 auto STy = StructType::create(C, Members);
131
132 auto GV =
133 new GlobalVariable(M, STy, false, GlobalValue::ExternalLinkage, nullptr,
134 clspv::PushConstantsVariableName(), nullptr,
135 GlobalValue::ThreadLocalMode::NotThreadLocal,
136 clspv::AddressSpace::PushConstant);
137
138 GV->setInitializer(Constant::getNullValue(STy));
139
140 std::vector<llvm::Metadata *> MDArgs;
141 for (auto &pc : PushConstants) {
142 auto Cst =
143 ConstantInt::get(IntegerType::get(C, 32), static_cast<int>(pc));
144 MDArgs.push_back(llvm::ConstantAsMetadata::get(Cst));
145 };
146
147 GV->setMetadata(clspv::PushConstantsMetadataName(),
148 llvm::MDNode::get(C, MDArgs));
149 }
150
151 return changed;
152}