blob: e163bfbd7ab6494f246e8c77b22d7e4d3224e9dd [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);
40 bool shouldDeclareGlobalOffset(Module &M);
Kévin Petit21c23c62020-04-29 01:38:28 +010041 bool shouldDeclareGlobalSize(Module &M);
42 bool shouldDeclareRegionOffset(Module &M);
43 bool shouldDeclareNumWorkgroups(Module &M);
44 bool shouldDeclareRegionGroupOffset(Module &M);
Kévin Petit0936e292020-03-16 15:10:37 +000045
Kévin Petitbbbda972020-03-03 19:16:31 +000046 bool runOnModule(Module &M) override;
47};
48} // namespace
49
50char DeclarePushConstantsPass::ID = 0;
51INITIALIZE_PASS(DeclarePushConstantsPass, "DeclarePushConstants",
52 "Declare push constants", false, false)
53
54namespace clspv {
55ModulePass *createDeclarePushConstantsPass() {
56 return new DeclarePushConstantsPass();
57}
58} // namespace clspv
59
Kévin Petit0936e292020-03-16 15:10:37 +000060bool DeclarePushConstantsPass::shouldDeclareEnqueuedLocalSize(Module &M) {
61 bool isEnabled = ((clspv::Option::Language() ==
62 clspv::Option::SourceLanguage::OpenCL_C_20) ||
63 (clspv::Option::Language() ==
64 clspv::Option::SourceLanguage::OpenCL_CPP));
65 bool isUsed = M.getFunction("_Z23get_enqueued_local_sizej") != nullptr;
66 return isEnabled && isUsed;
67}
68
69bool DeclarePushConstantsPass::shouldDeclareGlobalOffset(Module &M) {
70 bool isEnabled = clspv::Option::GlobalOffset();
71 bool isUsed = (M.getFunction("_Z17get_global_offsetj") != nullptr) ||
72 (M.getFunction("_Z13get_global_idj") != nullptr);
73 return isEnabled && isUsed;
74}
75
Kévin Petit21c23c62020-04-29 01:38:28 +010076bool DeclarePushConstantsPass::shouldDeclareGlobalSize(Module &M) {
77 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
78 bool isUsed = M.getFunction("_Z15get_global_sizej") != nullptr;
79 return isEnabled && isUsed;
80}
81
82bool DeclarePushConstantsPass::shouldDeclareRegionOffset(Module &M) {
83 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
84 bool isUsed = M.getFunction("_Z13get_global_idj") != nullptr;
85 return isEnabled && isUsed;
86}
87
88bool DeclarePushConstantsPass::shouldDeclareNumWorkgroups(Module &M) {
89 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
90 bool isUsed = M.getFunction("_Z14get_num_groupsj") != nullptr;
91 return isEnabled && isUsed;
92}
93
94bool DeclarePushConstantsPass::shouldDeclareRegionGroupOffset(Module &M) {
95 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
96 bool isUsed = M.getFunction("_Z12get_group_idj") != nullptr;
97 return isEnabled && isUsed;
98}
99
Kévin Petitbbbda972020-03-03 19:16:31 +0000100bool DeclarePushConstantsPass::runOnModule(Module &M) {
101
102 bool changed = false;
103
104 std::vector<clspv::PushConstant> PushConstants;
105
106 auto &C = M.getContext();
107
Kévin Petit0936e292020-03-16 15:10:37 +0000108 if (shouldDeclareGlobalOffset(M)) {
Kévin Petitbbbda972020-03-03 19:16:31 +0000109 PushConstants.emplace_back(clspv::PushConstant::GlobalOffset);
110 }
111
Kévin Petit0936e292020-03-16 15:10:37 +0000112 if (shouldDeclareEnqueuedLocalSize(M)) {
Kévin Petit1af73be2020-03-11 17:53:44 +0000113 PushConstants.push_back(clspv::PushConstant::EnqueuedLocalSize);
114 }
115
Kévin Petit21c23c62020-04-29 01:38:28 +0100116 if (shouldDeclareGlobalSize(M)) {
117 PushConstants.push_back(clspv::PushConstant::GlobalSize);
118 }
119
120 if (shouldDeclareRegionOffset(M)) {
121 PushConstants.push_back(clspv::PushConstant::RegionOffset);
122 }
123
124 if (shouldDeclareNumWorkgroups(M)) {
125 PushConstants.push_back(clspv::PushConstant::NumWorkgroups);
126 }
127
128 if (shouldDeclareRegionGroupOffset(M)) {
129 PushConstants.push_back(clspv::PushConstant::RegionGroupOffset);
130 }
131
Kévin Petitbbbda972020-03-03 19:16:31 +0000132 if (PushConstants.size() > 0) {
133 changed = true;
134
135 std::vector<Type *> Members;
136
137 for (auto &pc : PushConstants) {
138 Members.push_back(GetPushConstantType(M, pc));
139 }
140
141 auto STy = StructType::create(C, Members);
142
143 auto GV =
144 new GlobalVariable(M, STy, false, GlobalValue::ExternalLinkage, nullptr,
145 clspv::PushConstantsVariableName(), nullptr,
146 GlobalValue::ThreadLocalMode::NotThreadLocal,
147 clspv::AddressSpace::PushConstant);
148
149 GV->setInitializer(Constant::getNullValue(STy));
150
151 std::vector<llvm::Metadata *> MDArgs;
152 for (auto &pc : PushConstants) {
153 auto Cst =
154 ConstantInt::get(IntegerType::get(C, 32), static_cast<int>(pc));
155 MDArgs.push_back(llvm::ConstantAsMetadata::get(Cst));
156 };
157
158 GV->setMetadata(clspv::PushConstantsMetadataName(),
159 llvm::MDNode::get(C, MDArgs));
160 }
161
162 return changed;
163}