Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015, The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Jean-Luc Brouillet | a2dd52f | 2017-02-16 20:57:26 -0800 | [diff] [blame] | 17 | #include "RSScriptGroupFusion.h" |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 18 | |
Jean-Luc Brouillet | a2dd52f | 2017-02-16 20:57:26 -0800 | [diff] [blame] | 19 | #include "Assert.h" |
| 20 | #include "Log.h" |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 21 | #include "bcc/BCCContext.h" |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 22 | #include "bcc/Source.h" |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 23 | #include "bcinfo/MetadataExtractor.h" |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 24 | #include "llvm/ADT/StringExtras.h" |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 25 | #include "llvm/IR/DataLayout.h" |
| 26 | #include "llvm/IR/IRBuilder.h" |
| 27 | #include "llvm/IR/Module.h" |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 28 | #include "llvm/Support/raw_ostream.h" |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 29 | |
| 30 | using llvm::Function; |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 31 | using llvm::Module; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 32 | |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 33 | using std::string; |
| 34 | |
| 35 | namespace bcc { |
| 36 | |
| 37 | namespace { |
| 38 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 39 | const Function* getInvokeFunction(const Source& source, const int slot, |
| 40 | Module* newModule) { |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 41 | |
| 42 | bcinfo::MetadataExtractor &metadata = *source.getMetadata(); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 43 | const char* functionName = metadata.getExportFuncNameList()[slot]; |
| 44 | Function* func = newModule->getFunction(functionName); |
| 45 | // Materialize the function so that later the caller can inspect its argument |
| 46 | // and return types. |
| 47 | newModule->materialize(func); |
| 48 | return func; |
| 49 | } |
| 50 | |
| 51 | const Function* |
| 52 | getFunction(Module* mergedModule, const Source* source, const int slot, |
| 53 | uint32_t* signature) { |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 54 | |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 55 | bcinfo::MetadataExtractor &metadata = *source->getMetadata(); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 56 | const char* functionName = metadata.getExportForEachNameList()[slot]; |
Stephen Hines | a108bc5 | 2015-04-15 13:20:00 -0700 | [diff] [blame] | 57 | if (functionName == nullptr || !functionName[0]) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 58 | ALOGE("Kernel fusion (module %s slot %d): failed to find kernel function", |
| 59 | source->getName().c_str(), slot); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 60 | return nullptr; |
| 61 | } |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 62 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 63 | if (metadata.getExportForEachInputCountList()[slot] > 1) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 64 | ALOGE("Kernel fusion (module %s function %s): cannot handle multiple inputs", |
| 65 | source->getName().c_str(), functionName); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 66 | return nullptr; |
| 67 | } |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 68 | |
| 69 | if (signature != nullptr) { |
| 70 | *signature = metadata.getExportForEachSignatureList()[slot]; |
| 71 | } |
| 72 | |
| 73 | const Function* function = mergedModule->getFunction(functionName); |
| 74 | |
| 75 | return function; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 76 | } |
| 77 | |
Stephen Hines | 4dc1d8e | 2020-07-24 16:18:16 -0700 | [diff] [blame] | 78 | // The collection of supported signature bits. Context or user data arguments are |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 79 | // not currently supported in kernel fusion. To support them or any new kinds of |
| 80 | // arguments in the future, it requires not only listing the signature bits here, |
| 81 | // but also implementing additional necessary fusion logic in the getFusedFuncSig(), |
| 82 | // getFusedFuncType(), and fuseKernels() functions below. |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 83 | constexpr uint32_t ExpectedSignatureBits = |
| 84 | bcinfo::MD_SIG_In | |
| 85 | bcinfo::MD_SIG_Out | |
| 86 | bcinfo::MD_SIG_X | |
| 87 | bcinfo::MD_SIG_Y | |
| 88 | bcinfo::MD_SIG_Z | |
| 89 | bcinfo::MD_SIG_Kernel; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 90 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 91 | int getFusedFuncSig(const std::vector<Source*>& sources, |
| 92 | const std::vector<int>& slots, |
| 93 | uint32_t* retSig) { |
| 94 | *retSig = 0; |
| 95 | uint32_t firstSignature = 0; |
| 96 | uint32_t signature = 0; |
| 97 | auto slotIter = slots.begin(); |
| 98 | for (const Source* source : sources) { |
| 99 | const int slot = *slotIter++; |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 100 | bcinfo::MetadataExtractor &metadata = *source->getMetadata(); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 101 | |
| 102 | if (metadata.getExportForEachInputCountList()[slot] > 1) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 103 | ALOGE("Kernel fusion (module %s slot %d): cannot handle multiple inputs", |
| 104 | source->getName().c_str(), slot); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 105 | return -1; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 106 | } |
| 107 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 108 | signature = metadata.getExportForEachSignatureList()[slot]; |
| 109 | if (signature & ~ExpectedSignatureBits) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 110 | ALOGE("Kernel fusion (module %s slot %d): Unexpected signature %x", |
| 111 | source->getName().c_str(), slot, signature); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 112 | return -1; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 113 | } |
| 114 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 115 | if (firstSignature == 0) { |
| 116 | firstSignature = signature; |
| 117 | } |
| 118 | |
| 119 | *retSig |= signature; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 120 | } |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 121 | |
| 122 | if (!bcinfo::MetadataExtractor::hasForEachSignatureIn(firstSignature)) { |
| 123 | *retSig &= ~bcinfo::MD_SIG_In; |
| 124 | } |
| 125 | |
| 126 | if (!bcinfo::MetadataExtractor::hasForEachSignatureOut(signature)) { |
| 127 | *retSig &= ~bcinfo::MD_SIG_Out; |
| 128 | } |
| 129 | |
| 130 | return 0; |
| 131 | } |
| 132 | |
| 133 | llvm::FunctionType* getFusedFuncType(bcc::BCCContext& Context, |
| 134 | const std::vector<Source*>& sources, |
| 135 | const std::vector<int>& slots, |
| 136 | Module* M, |
| 137 | uint32_t* signature) { |
| 138 | int error = getFusedFuncSig(sources, slots, signature); |
| 139 | |
| 140 | if (error < 0) { |
| 141 | return nullptr; |
| 142 | } |
| 143 | |
| 144 | const Function* firstF = getFunction(M, sources.front(), slots.front(), nullptr); |
| 145 | |
| 146 | bccAssert (firstF != nullptr); |
| 147 | |
| 148 | llvm::SmallVector<llvm::Type*, 8> ArgTys; |
| 149 | |
| 150 | if (bcinfo::MetadataExtractor::hasForEachSignatureIn(*signature)) { |
| 151 | ArgTys.push_back(firstF->arg_begin()->getType()); |
| 152 | } |
| 153 | |
| 154 | llvm::Type* I32Ty = llvm::IntegerType::get(Context.getLLVMContext(), 32); |
| 155 | if (bcinfo::MetadataExtractor::hasForEachSignatureX(*signature)) { |
| 156 | ArgTys.push_back(I32Ty); |
| 157 | } |
| 158 | if (bcinfo::MetadataExtractor::hasForEachSignatureY(*signature)) { |
| 159 | ArgTys.push_back(I32Ty); |
| 160 | } |
| 161 | if (bcinfo::MetadataExtractor::hasForEachSignatureZ(*signature)) { |
| 162 | ArgTys.push_back(I32Ty); |
| 163 | } |
| 164 | |
| 165 | const Function* lastF = getFunction(M, sources.back(), slots.back(), nullptr); |
| 166 | |
| 167 | bccAssert (lastF != nullptr); |
| 168 | |
| 169 | llvm::Type* retTy = lastF->getReturnType(); |
| 170 | |
| 171 | return llvm::FunctionType::get(retTy, ArgTys, false); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 172 | } |
| 173 | |
| 174 | } // anonymous namespace |
| 175 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 176 | bool fuseKernels(bcc::BCCContext& Context, |
| 177 | const std::vector<Source *>& sources, |
| 178 | const std::vector<int>& slots, |
| 179 | const std::string& fusedName, |
| 180 | Module* mergedModule) { |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 181 | bccAssert(sources.size() == slots.size() && "sources and slots differ in size"); |
| 182 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 183 | uint32_t fusedFunctionSignature; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 184 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 185 | llvm::FunctionType* fusedType = |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 186 | getFusedFuncType(Context, sources, slots, mergedModule, &fusedFunctionSignature); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 187 | |
| 188 | if (fusedType == nullptr) { |
| 189 | return false; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 190 | } |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 191 | |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 192 | Function* fusedKernel = |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 193 | (Function*)(mergedModule->getOrInsertFunction(fusedName, fusedType)); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 194 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 195 | llvm::LLVMContext& ctxt = Context.getLLVMContext(); |
| 196 | |
| 197 | llvm::BasicBlock* block = llvm::BasicBlock::Create(ctxt, "entry", fusedKernel); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 198 | llvm::IRBuilder<> builder(block); |
| 199 | |
| 200 | Function::arg_iterator argIter = fusedKernel->arg_begin(); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 201 | |
| 202 | llvm::Value* dataElement = nullptr; |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 203 | if (bcinfo::MetadataExtractor::hasForEachSignatureIn(fusedFunctionSignature)) { |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 204 | dataElement = &*(argIter++); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 205 | dataElement->setName("DataIn"); |
| 206 | } |
| 207 | |
| 208 | llvm::Value* X = nullptr; |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 209 | if (bcinfo::MetadataExtractor::hasForEachSignatureX(fusedFunctionSignature)) { |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 210 | X = &*(argIter++); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 211 | X->setName("x"); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 212 | } |
| 213 | |
| 214 | llvm::Value* Y = nullptr; |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 215 | if (bcinfo::MetadataExtractor::hasForEachSignatureY(fusedFunctionSignature)) { |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 216 | Y = &*(argIter++); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 217 | Y->setName("y"); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 218 | } |
| 219 | |
| 220 | llvm::Value* Z = nullptr; |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 221 | if (bcinfo::MetadataExtractor::hasForEachSignatureZ(fusedFunctionSignature)) { |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 222 | Z = &*(argIter++); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 223 | Z->setName("z"); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 224 | } |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 225 | |
| 226 | auto slotIter = slots.begin(); |
| 227 | for (const Source* source : sources) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 228 | int slot = *slotIter; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 229 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 230 | uint32_t inputFunctionSignature; |
| 231 | const Function* inputFunction = |
| 232 | getFunction(mergedModule, source, slot, &inputFunctionSignature); |
| 233 | if (inputFunction == nullptr) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 234 | // Either failed to find the kernel function, or the function has multiple inputs. |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 235 | return false; |
| 236 | } |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 237 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 238 | // Don't try to fuse a non-kernel |
| 239 | if (!bcinfo::MetadataExtractor::hasForEachSignatureKernel(inputFunctionSignature)) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 240 | ALOGE("Kernel fusion (module %s function %s): not a kernel", |
| 241 | source->getName().c_str(), inputFunction->getName().str().c_str()); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 242 | return false; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 243 | } |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 244 | |
| 245 | std::vector<llvm::Value*> args; |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 246 | |
| 247 | if (bcinfo::MetadataExtractor::hasForEachSignatureIn(inputFunctionSignature)) { |
| 248 | if (dataElement == nullptr) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 249 | ALOGE("Kernel fusion (module %s function %s): expected input, but got null", |
| 250 | source->getName().c_str(), inputFunction->getName().str().c_str()); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 251 | return false; |
| 252 | } |
| 253 | |
| 254 | const llvm::FunctionType* funcTy = inputFunction->getFunctionType(); |
| 255 | llvm::Type* firstArgType = funcTy->getParamType(0); |
| 256 | |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 257 | if (dataElement->getType() != firstArgType) { |
| 258 | std::string msg; |
| 259 | llvm::raw_string_ostream rso(msg); |
| 260 | rso << "Mismatching argument type, expected "; |
| 261 | firstArgType->print(rso); |
| 262 | rso << ", received "; |
| 263 | dataElement->getType()->print(rso); |
| 264 | ALOGE("Kernel fusion (module %s function %s): %s", source->getName().c_str(), |
| 265 | inputFunction->getName().str().c_str(), rso.str().c_str()); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 266 | return false; |
| 267 | } |
| 268 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 269 | args.push_back(dataElement); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 270 | } else { |
| 271 | // Only the first kernel in a batch is allowed to have no input |
| 272 | if (slotIter != slots.begin()) { |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 273 | ALOGE("Kernel fusion (module %s function %s): function not first in batch takes no input", |
| 274 | source->getName().c_str(), inputFunction->getName().str().c_str()); |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 275 | return false; |
| 276 | } |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 277 | } |
| 278 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 279 | if (bcinfo::MetadataExtractor::hasForEachSignatureX(inputFunctionSignature)) { |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 280 | args.push_back(X); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 281 | } |
| 282 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 283 | if (bcinfo::MetadataExtractor::hasForEachSignatureY(inputFunctionSignature)) { |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 284 | args.push_back(Y); |
| 285 | } |
| 286 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 287 | if (bcinfo::MetadataExtractor::hasForEachSignatureZ(inputFunctionSignature)) { |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 288 | args.push_back(Z); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 289 | } |
| 290 | |
Yang Ni | 8c12d61 | 2015-06-19 16:02:38 -0700 | [diff] [blame] | 291 | dataElement = builder.CreateCall((llvm::Value*)inputFunction, args); |
Yang Ni | 531d08c | 2015-06-29 11:05:51 -0700 | [diff] [blame] | 292 | |
| 293 | slotIter++; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 294 | } |
| 295 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 296 | if (fusedKernel->getReturnType()->isVoidTy()) { |
| 297 | builder.CreateRetVoid(); |
| 298 | } else { |
| 299 | builder.CreateRet(dataElement); |
| 300 | } |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 301 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 302 | llvm::NamedMDNode* ExportForEachNameMD = |
| 303 | mergedModule->getOrInsertNamedMetadata("#rs_export_foreach_name"); |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 304 | |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 305 | llvm::MDString* nameMDStr = llvm::MDString::get(ctxt, fusedName); |
| 306 | llvm::MDNode* nameMDNode = llvm::MDNode::get(ctxt, nameMDStr); |
| 307 | ExportForEachNameMD->addOperand(nameMDNode); |
| 308 | |
| 309 | llvm::NamedMDNode* ExportForEachMD = |
| 310 | mergedModule->getOrInsertNamedMetadata("#rs_export_foreach"); |
| 311 | llvm::MDString* sigMDStr = llvm::MDString::get(ctxt, |
Pirama Arumuga Nainar | f5b49a0 | 2016-09-15 23:04:25 -0700 | [diff] [blame] | 312 | llvm::utostr(fusedFunctionSignature)); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 313 | llvm::MDNode* sigMDNode = llvm::MDNode::get(ctxt, sigMDStr); |
| 314 | ExportForEachMD->addOperand(sigMDNode); |
| 315 | |
| 316 | return true; |
| 317 | } |
| 318 | |
| 319 | bool renameInvoke(BCCContext& Context, const Source* source, const int slot, |
| 320 | const std::string& newName, Module* module) { |
| 321 | const llvm::Function* F = getInvokeFunction(*source, slot, module); |
| 322 | std::vector<llvm::Type*> params; |
| 323 | for (auto I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { |
| 324 | params.push_back(I->getType()); |
| 325 | } |
| 326 | llvm::Type* returnTy = F->getReturnType(); |
| 327 | |
| 328 | llvm::FunctionType* batchFuncTy = |
| 329 | llvm::FunctionType::get(returnTy, params, false); |
| 330 | |
| 331 | llvm::Function* newF = |
| 332 | llvm::Function::Create(batchFuncTy, |
| 333 | llvm::GlobalValue::ExternalLinkage, newName, |
| 334 | module); |
| 335 | |
| 336 | llvm::BasicBlock* block = llvm::BasicBlock::Create(Context.getLLVMContext(), |
| 337 | "entry", newF); |
| 338 | llvm::IRBuilder<> builder(block); |
| 339 | |
| 340 | llvm::Function::arg_iterator argIter = newF->arg_begin(); |
Pirama Arumuga Nainar | f229c40 | 2016-03-06 23:05:45 -0800 | [diff] [blame] | 341 | llvm::Value* arg1 = &*(argIter++); |
Yang Ni | 0ab50b8 | 2015-02-16 12:31:56 -0800 | [diff] [blame] | 342 | builder.CreateCall((llvm::Value*)F, arg1); |
| 343 | |
| 344 | builder.CreateRetVoid(); |
| 345 | |
| 346 | llvm::NamedMDNode* ExportFuncNameMD = |
| 347 | module->getOrInsertNamedMetadata("#rs_export_func"); |
| 348 | llvm::MDString* strMD = llvm::MDString::get(module->getContext(), newName); |
| 349 | llvm::MDNode* nodeMD = llvm::MDNode::get(module->getContext(), strMD); |
| 350 | ExportFuncNameMD->addOperand(nodeMD); |
| 351 | |
| 352 | return true; |
Yang Ni | a4ded13 | 2014-11-17 17:44:08 -0800 | [diff] [blame] | 353 | } |
| 354 | |
| 355 | } // namespace bcc |