blob: 985589f4886cf42b2c5b16c3b07395ef956b4707 [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 "PushConstant.h"
16
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/Function.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/Metadata.h"
21#include "llvm/IR/Module.h"
22#include "llvm/IR/Type.h"
23#include "llvm/Support/ErrorHandling.h"
24
alan-bakerc4579bb2020-04-29 14:15:50 -040025#include "clspv/Option.h"
26
Kévin Petitbbbda972020-03-03 19:16:31 +000027#include "Constants.h"
28
29using namespace llvm;
30
31namespace clspv {
32
33const char *GetPushConstantName(PushConstant pc) {
34 switch (pc) {
35 case PushConstant::Dimensions:
36 return "dimensions";
37 case PushConstant::GlobalOffset:
38 return "global_offset";
Kévin Petit1af73be2020-03-11 17:53:44 +000039 case PushConstant::EnqueuedLocalSize:
40 return "enqueued_local_size";
Kévin Petit21c23c62020-04-29 01:38:28 +010041 case PushConstant::GlobalSize:
42 return "global_size";
43 case PushConstant::RegionOffset:
44 return "region_offset";
45 case PushConstant::NumWorkgroups:
46 return "num_workgroups";
47 case PushConstant::RegionGroupOffset:
48 return "region_group_offset";
alan-baker6a3930b2020-05-21 10:09:11 -040049 case PushConstant::KernelArgument:
50 return "kernel_argument";
Kévin Petitbbbda972020-03-03 19:16:31 +000051 }
52 llvm_unreachable("Unknown PushConstant in GetPushConstantName");
53 return "";
54}
55
56Type *GetPushConstantType(Module &M, PushConstant pc) {
57 auto &C = M.getContext();
58 switch (pc) {
59 case PushConstant::Dimensions:
60 return IntegerType::get(C, 32);
61 case PushConstant::GlobalOffset:
alan-bakerb3e2b6d2020-06-24 23:59:57 -040062 return FixedVectorType::get(IntegerType::get(C, 32), 3);
Kévin Petit1af73be2020-03-11 17:53:44 +000063 case PushConstant::EnqueuedLocalSize:
alan-bakerb3e2b6d2020-06-24 23:59:57 -040064 return FixedVectorType::get(IntegerType::get(C, 32), 3);
Kévin Petit21c23c62020-04-29 01:38:28 +010065 case PushConstant::GlobalSize:
alan-bakerb3e2b6d2020-06-24 23:59:57 -040066 return FixedVectorType::get(IntegerType::get(C, 32), 3);
Kévin Petit21c23c62020-04-29 01:38:28 +010067 case PushConstant::RegionOffset:
alan-bakerb3e2b6d2020-06-24 23:59:57 -040068 return FixedVectorType::get(IntegerType::get(C, 32), 3);
Kévin Petit21c23c62020-04-29 01:38:28 +010069 case PushConstant::NumWorkgroups:
alan-bakerb3e2b6d2020-06-24 23:59:57 -040070 return FixedVectorType::get(IntegerType::get(C, 32), 3);
Kévin Petit21c23c62020-04-29 01:38:28 +010071 case PushConstant::RegionGroupOffset:
alan-bakerb3e2b6d2020-06-24 23:59:57 -040072 return FixedVectorType::get(IntegerType::get(C, 32), 3);
alan-baker6a3930b2020-05-21 10:09:11 -040073 default:
74 break;
Kévin Petitbbbda972020-03-03 19:16:31 +000075 }
76 llvm_unreachable("Unknown PushConstant in GetPushConstantType");
77 return nullptr;
78}
79
alan-baker6a3930b2020-05-21 10:09:11 -040080Value *GetPushConstantPointer(BasicBlock *BB, PushConstant pc,
81 const ArrayRef<Value *> &extra_indices) {
Kévin Petitbbbda972020-03-03 19:16:31 +000082 auto M = BB->getParent()->getParent();
83
84 // Get variable
85 auto GV = M->getGlobalVariable(clspv::PushConstantsVariableName());
86 assert(GV && "Push constants requested but none are declared.");
87
88 // Find requested pc in metadata
89 auto MD = GV->getMetadata(clspv::PushConstantsMetadataName());
Marco Antognini7e338402021-03-15 12:48:37 +000090#ifndef NDEBUG
Kévin Petitbbbda972020-03-03 19:16:31 +000091 bool found = false;
Marco Antognini7e338402021-03-15 12:48:37 +000092#endif
Kévin Petitbbbda972020-03-03 19:16:31 +000093 uint32_t idx = 0;
94 for (auto &PCMD : MD->operands()) {
95 auto mpc = static_cast<PushConstant>(
96 mdconst::extract<ConstantInt>(PCMD)->getZExtValue());
97 if (mpc == pc) {
Marco Antognini7e338402021-03-15 12:48:37 +000098#ifndef NDEBUG
Kévin Petitbbbda972020-03-03 19:16:31 +000099 found = true;
Marco Antognini7e338402021-03-15 12:48:37 +0000100#endif
Kévin Petitbbbda972020-03-03 19:16:31 +0000101 break;
102 }
103 idx++;
104 }
105
106 // Assert that it exists
107 assert(found && "Push constant wasn't declared.");
108
109 // Construct pointer
110 IRBuilder<> Builder(BB);
alan-baker6a3930b2020-05-21 10:09:11 -0400111 SmallVector<Value *, 4> Indices(2);
112 Indices[0] = Builder.getInt32(0);
113 Indices[1] = Builder.getInt32(idx);
114 for (auto idx : extra_indices)
115 Indices.push_back(idx);
Kévin Petitbbbda972020-03-03 19:16:31 +0000116 return Builder.CreateInBoundsGEP(GV, Indices);
117}
118
alan-bakerc4579bb2020-04-29 14:15:50 -0400119bool UsesGlobalPushConstants(Module &M) {
alan-baker6a3930b2020-05-21 10:09:11 -0400120 return ShouldDeclareGlobalOffsetPushConstant(M) ||
121 ShouldDeclareEnqueuedLocalSizePushConstant(M) ||
122 ShouldDeclareGlobalSizePushConstant(M) ||
123 ShouldDeclareRegionOffsetPushConstant(M) ||
124 ShouldDeclareNumWorkgroupsPushConstant(M) ||
125 ShouldDeclareRegionGroupOffsetPushConstant(M);
alan-bakerc4579bb2020-04-29 14:15:50 -0400126}
127
alan-bakere1996972020-05-04 08:38:12 -0400128bool ShouldDeclareGlobalOffsetPushConstant(Module &M) {
129 bool isEnabled = (clspv::Option::GlobalOffset() &&
130 clspv::Option::NonUniformNDRangeSupported()) ||
131 clspv::Option::GlobalOffsetPushConstant();
alan-bakerc4579bb2020-04-29 14:15:50 -0400132 bool isUsed = (M.getFunction("_Z17get_global_offsetj") != nullptr) ||
133 (M.getFunction("_Z13get_global_idj") != nullptr);
134 return isEnabled && isUsed;
135}
136
alan-baker6a3930b2020-05-21 10:09:11 -0400137bool ShouldDeclareEnqueuedLocalSizePushConstant(Module &M) {
138 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
139 bool isUsed = M.getFunction("_Z23get_enqueued_local_sizej") != nullptr;
140 return isEnabled && isUsed;
141}
142
143bool ShouldDeclareGlobalSizePushConstant(Module &M) {
144 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
145 bool isUsed = M.getFunction("_Z15get_global_sizej") != nullptr;
146 return isEnabled && isUsed;
147}
148
149bool ShouldDeclareRegionOffsetPushConstant(Module &M) {
150 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
151 bool isUsed = M.getFunction("_Z13get_global_idj") != nullptr;
152 return isEnabled && isUsed;
153}
154
155bool ShouldDeclareNumWorkgroupsPushConstant(Module &M) {
156 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
157 bool isUsed = M.getFunction("_Z14get_num_groupsj") != nullptr;
158 return isEnabled && isUsed;
159}
160
161bool ShouldDeclareRegionGroupOffsetPushConstant(Module &M) {
162 bool isEnabled = clspv::Option::NonUniformNDRangeSupported();
163 bool isUsed = M.getFunction("_Z12get_group_idj") != nullptr;
164 return isEnabled && isUsed;
165}
166
167uint64_t GlobalPushConstantsSize(Module &M) {
168 const auto &DL = M.getDataLayout();
169 if (auto GV = M.getGlobalVariable(clspv::PushConstantsVariableName())) {
170 auto ptr_ty = GV->getType();
171 auto block_ty = ptr_ty->getPointerElementType();
172 return DL.getTypeStoreSize(block_ty).getKnownMinSize();
173 } else {
174 SmallVector<Type *, 8> types;
175 if (ShouldDeclareGlobalOffsetPushConstant(M)) {
176 auto type = GetPushConstantType(M, PushConstant::GlobalOffset);
177 types.push_back(type);
178 }
179 if (ShouldDeclareEnqueuedLocalSizePushConstant(M)) {
180 auto type = GetPushConstantType(M, PushConstant::EnqueuedLocalSize);
181 types.push_back(type);
182 }
183 if (ShouldDeclareGlobalSizePushConstant(M)) {
184 auto type = GetPushConstantType(M, PushConstant::GlobalSize);
185 types.push_back(type);
186 }
187 if (ShouldDeclareRegionOffsetPushConstant(M)) {
188 auto type = GetPushConstantType(M, PushConstant::RegionOffset);
189 types.push_back(type);
190 }
191 if (ShouldDeclareNumWorkgroupsPushConstant(M)) {
192 auto type = GetPushConstantType(M, PushConstant::NumWorkgroups);
193 types.push_back(type);
194 }
195 if (ShouldDeclareRegionGroupOffsetPushConstant(M)) {
196 auto type = GetPushConstantType(M, PushConstant::RegionGroupOffset);
197 types.push_back(type);
198 }
199
200 auto block_ty = StructType::get(M.getContext(), types, false);
201 return DL.getTypeStoreSize(block_ty).getKnownMinSize();
202 }
203}
204
Kévin Petitbbbda972020-03-03 19:16:31 +0000205} // namespace clspv