blob: acace025f09339ede3576604dcd75e15f8ceb00c [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 shouldDeclareDimensions(Module &M);
40 bool shouldDeclareEnqueuedLocalSize(Module &M);
41 bool shouldDeclareGlobalOffset(Module &M);
42
Kévin Petitbbbda972020-03-03 19:16:31 +000043 bool runOnModule(Module &M) override;
44};
45} // namespace
46
47char DeclarePushConstantsPass::ID = 0;
48INITIALIZE_PASS(DeclarePushConstantsPass, "DeclarePushConstants",
49 "Declare push constants", false, false)
50
51namespace clspv {
52ModulePass *createDeclarePushConstantsPass() {
53 return new DeclarePushConstantsPass();
54}
55} // namespace clspv
56
Kévin Petit0936e292020-03-16 15:10:37 +000057bool DeclarePushConstantsPass::shouldDeclareDimensions(Module &M) {
58 bool isEnabled = clspv::Option::WorkDim();
59 bool isUsed = M.getFunction("_Z12get_work_dimv") != nullptr;
60 return isEnabled && isUsed;
61}
62
63bool DeclarePushConstantsPass::shouldDeclareEnqueuedLocalSize(Module &M) {
64 bool isEnabled = ((clspv::Option::Language() ==
65 clspv::Option::SourceLanguage::OpenCL_C_20) ||
66 (clspv::Option::Language() ==
67 clspv::Option::SourceLanguage::OpenCL_CPP));
68 bool isUsed = M.getFunction("_Z23get_enqueued_local_sizej") != nullptr;
69 return isEnabled && isUsed;
70}
71
72bool DeclarePushConstantsPass::shouldDeclareGlobalOffset(Module &M) {
73 bool isEnabled = clspv::Option::GlobalOffset();
74 bool isUsed = (M.getFunction("_Z17get_global_offsetj") != nullptr) ||
75 (M.getFunction("_Z13get_global_idj") != nullptr);
76 return isEnabled && isUsed;
77}
78
Kévin Petitbbbda972020-03-03 19:16:31 +000079bool DeclarePushConstantsPass::runOnModule(Module &M) {
80
81 bool changed = false;
82
83 std::vector<clspv::PushConstant> PushConstants;
84
85 auto &C = M.getContext();
86
Kévin Petit0936e292020-03-16 15:10:37 +000087 if (shouldDeclareGlobalOffset(M)) {
Kévin Petitbbbda972020-03-03 19:16:31 +000088 PushConstants.emplace_back(clspv::PushConstant::GlobalOffset);
89 }
90
Kévin Petit0936e292020-03-16 15:10:37 +000091 if (shouldDeclareEnqueuedLocalSize(M)) {
Kévin Petit1af73be2020-03-11 17:53:44 +000092 PushConstants.push_back(clspv::PushConstant::EnqueuedLocalSize);
93 }
94
Kévin Petit0936e292020-03-16 15:10:37 +000095 if (shouldDeclareDimensions(M)) {
Kévin Petitbbbda972020-03-03 19:16:31 +000096 PushConstants.push_back(clspv::PushConstant::Dimensions);
97 }
98
99 if (PushConstants.size() > 0) {
100 changed = true;
101
102 std::vector<Type *> Members;
103
104 for (auto &pc : PushConstants) {
105 Members.push_back(GetPushConstantType(M, pc));
106 }
107
108 auto STy = StructType::create(C, Members);
109
110 auto GV =
111 new GlobalVariable(M, STy, false, GlobalValue::ExternalLinkage, nullptr,
112 clspv::PushConstantsVariableName(), nullptr,
113 GlobalValue::ThreadLocalMode::NotThreadLocal,
114 clspv::AddressSpace::PushConstant);
115
116 GV->setInitializer(Constant::getNullValue(STy));
117
118 std::vector<llvm::Metadata *> MDArgs;
119 for (auto &pc : PushConstants) {
120 auto Cst =
121 ConstantInt::get(IntegerType::get(C, 32), static_cast<int>(pc));
122 MDArgs.push_back(llvm::ConstantAsMetadata::get(Cst));
123 };
124
125 GV->setMetadata(clspv::PushConstantsMetadataName(),
126 llvm::MDNode::get(C, MDArgs));
127 }
128
129 return changed;
130}