RSKernelExpand.cpp revision 7a66e6cbb1ae32cd56b19822c4e66560deb857db
1db169187dea4602e4ad32058762d23d474753fd0Stephen Hines/* 2db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * Copyright 2012, The Android Open Source Project 3db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * 4db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 5db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * you may not use this file except in compliance with the License. 6db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * You may obtain a copy of the License at 7db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * 8db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * http://www.apache.org/licenses/LICENSE-2.0 9db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * 10db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * Unless required by applicable law or agreed to in writing, software 11db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 12db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * See the License for the specific language governing permissions and 14db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * limitations under the License. 15db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 16db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 177a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao//#define RS_FOREACH_EXPAND_PASS_NDEBUG 0 187a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#include "RSTransforms.h" 197a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao 207a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#include <cstdlib> 217a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao 222f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "Config.h" 232f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines 242f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "DebugHelper.h" 257a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#include "RSInfo.h" 262f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines 272f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/DerivedTypes.h" 282f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/Function.h" 292f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/Instructions.h" 302f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/Module.h" 312f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/Pass.h" 322f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/Type.h" 332f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines#include "llvm/Support/IRBuilder.h" 34db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 357a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liaousing namespace bcc; 367a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao 37db169187dea4602e4ad32058762d23d474753fd0Stephen Hinesnamespace { 387a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao 397a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao/* RSForEachExpandPass - This pass operates on functions that are able to be 407a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao * called via rsForEach() or "foreach_<NAME>". We create an inner loop for the 417a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao * ForEach-able function to be invoked over the appropriate data cells of the 427a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao * input/output allocations (adjusting other relevant parameters as we go). We 437a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao * support doing this for any ForEach-able compute kernels. The new function 447a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao * name is the original function name followed by ".expand". Note that we 457a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao * still generate code for the original function. 467a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao */ 477a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liaoclass RSForEachExpandPass : public llvm::ModulePass { 487a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liaoprivate: 49db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static char ID; 50db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 51db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Module *M; 52db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::LLVMContext *C; 53db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 547a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao const RSInfo::ExportForeachFuncListTy &mFuncs; 55cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines 56cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines uint32_t getRootSignature(llvm::Function *F) { 57db169187dea4602e4ad32058762d23d474753fd0Stephen Hines const llvm::NamedMDNode *ExportForEachMetadata = 58db169187dea4602e4ad32058762d23d474753fd0Stephen Hines M->getNamedMetadata("#rs_export_foreach"); 59db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 60db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (!ExportForEachMetadata) { 61db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Type*, 8> RootArgTys; 62db169187dea4602e4ad32058762d23d474753fd0Stephen Hines for (llvm::Function::arg_iterator B = F->arg_begin(), 63db169187dea4602e4ad32058762d23d474753fd0Stephen Hines E = F->arg_end(); 64db169187dea4602e4ad32058762d23d474753fd0Stephen Hines B != E; 65db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ++B) { 66db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgTys.push_back(B->getType()); 67db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 68db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 69db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // For pre-ICS bitcode, we may not have signature information. In that 70db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // case, we use the size of the RootArgTys to select the number of 71db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // arguments. 72db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return (1 << RootArgTys.size()) - 1; 73db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 74db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 757a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#if !RS_FOREACH_EXPAND_PASS_NDEBUG 767a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao if (ExportForEachMetadata->getNumOperands() <= 0) { 777a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao ALOGE("Assert failed at %s:%d: Invalid #rs_export_foreach metadata in " 787a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao " '%s'!", __FILE__, __LINE__, M->getModuleIdentifier().c_str()); 797a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao ::abort(); 807a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao } 817a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#endif 82db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 83cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines // We only handle the case for legacy root() functions here, so this is 84cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines // hard-coded to look at only the first such function. 85db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(0); 86db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (SigNode != NULL && SigNode->getNumOperands() == 1) { 87db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *SigVal = SigNode->getOperand(0); 88db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (SigVal->getValueID() == llvm::Value::MDStringVal) { 89db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::StringRef SigString = 90db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static_cast<llvm::MDString*>(SigVal)->getString(); 91db169187dea4602e4ad32058762d23d474753fd0Stephen Hines uint32_t Signature = 0; 92db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (SigString.getAsInteger(10, Signature)) { 93db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ALOGE("Non-integer signature value '%s'", SigString.str().c_str()); 94db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return 0; 95db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 96db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature; 97db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 98db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 99db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 100db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return 0; 101db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 102db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 103db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasIn(uint32_t Signature) { 104db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 1; 105db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 106db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 107db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasOut(uint32_t Signature) { 108db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 2; 109db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 110db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 111db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasUsrData(uint32_t Signature) { 112db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 4; 113db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 114db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 115db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasX(uint32_t Signature) { 116db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 8; 117db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 118db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 119db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasY(uint32_t Signature) { 120db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 16; 121db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 122db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 1237a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liaopublic: 1247a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao RSForEachExpandPass(const RSInfo::ExportForeachFuncListTy &pForeachFuncs) 1257a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao : ModulePass(ID), M(NULL), C(NULL), mFuncs(pForeachFuncs) { 126db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 127db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 128db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* Performs the actual optimization on a selected function. On success, the 129db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * Module will contain a new function of the name "<NAME>.expand" that 130db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * invokes <NAME>() in a loop with the appropriate parameters. 131db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 132cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines bool ExpandFunction(llvm::Function *F, uint32_t Signature) { 133cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines ALOGV("Expanding ForEach-able Function %s", F->getName().str().c_str()); 134db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 135db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (!Signature) { 136cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines Signature = getRootSignature(F); 137cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines if (!Signature) { 138cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines // We couldn't determine how to expand this function based on its 139cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines // function signature. 140cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines return false; 141cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines } 142db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 143db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 144db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*C); 145db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*C); 146db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *SizeTy = Int32Ty; 147db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 148db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* Defined in frameworks/base/libs/rs/rs_hal.h: 149db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * 150db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * struct RsForEachStubParamStruct { 151db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * const void *in; 152db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * void *out; 153db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * const void *usr; 154db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * size_t usr_len; 155db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t x; 156db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t y; 157db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t z; 158db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t lod; 159db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * enum RsAllocationCubemapFace face; 160db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t ar[16]; 161db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * }; 162db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 163db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Type*, 9> StructTys; 164db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(VoidPtrTy); // const void *in 165db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(VoidPtrTy); // void *out 166db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(VoidPtrTy); // const void *usr 167db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(SizeTy); // size_t usr_len 168db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t x 169db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t y 170db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t z 171db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t lod 172db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // enum RsAllocationCubemapFace 173db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(llvm::ArrayType::get(Int32Ty, 16)); // uint32_t ar[16] 174db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 175db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *ForEachStubPtrTy = llvm::StructType::create( 176db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys, "RsForEachStubParamStruct")->getPointerTo(); 177db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 178db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* Create the function signature for our expanded function. 179db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * void (const RsForEachStubParamStruct *p, uint32_t x1, uint32_t x2, 180db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t instep, uint32_t outstep) 181db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 182db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Type*, 8> ParamTys; 183db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(ForEachStubPtrTy); // const RsForEachStubParamStruct *p 184db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t x1 185db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t x2 186db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t instep 187db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t outstep 188db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 189db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::FunctionType *FT = 190db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::FunctionType::get(llvm::Type::getVoidTy(*C), ParamTys, false); 191db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function *ExpandedFunc = 192db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function::Create(FT, 193db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::GlobalValue::ExternalLinkage, 194db169187dea4602e4ad32058762d23d474753fd0Stephen Hines F->getName() + ".expand", M); 195db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 196db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Create and name the actual arguments to this expanded function. 197db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Argument*, 8> ArgVec; 198db169187dea4602e4ad32058762d23d474753fd0Stephen Hines for (llvm::Function::arg_iterator B = ExpandedFunc->arg_begin(), 199db169187dea4602e4ad32058762d23d474753fd0Stephen Hines E = ExpandedFunc->arg_end(); 200db169187dea4602e4ad32058762d23d474753fd0Stephen Hines B != E; 201db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ++B) { 202db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ArgVec.push_back(B); 203db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 204db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 205db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (ArgVec.size() != 5) { 20689e8490c80505468f2b816ca9d12fefa53f05959Shih-wei Liao ALOGE("Incorrect number of arguments to function: %zu", 20789e8490c80505468f2b816ca9d12fefa53f05959Shih-wei Liao ArgVec.size()); 208db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return false; 209db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 210db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_p = ArgVec[0]; 211db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_x1 = ArgVec[1]; 212db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_x2 = ArgVec[2]; 213db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_instep = ArgVec[3]; 214db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_outstep = ArgVec[4]; 215db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 216db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_p->setName("p"); 217db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_x1->setName("x1"); 218db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_x2->setName("x2"); 219db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_instep->setName("instep"); 220db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_outstep->setName("outstep"); 221db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 222db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Construct the actual function body. 223db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock *Begin = 224db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock::Create(*C, "Begin", ExpandedFunc); 225db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::IRBuilder<> Builder(Begin); 226db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 227db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // uint32_t X = x1; 228db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::AllocaInst *AX = Builder.CreateAlloca(Int32Ty, 0, "AX"); 229db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(Arg_x1, AX); 230db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 231cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines // Collect and construct the arguments for the kernel(). 232db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Note that we load any loop-invariant arguments before entering the Loop. 233db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function::arg_iterator Args = F->arg_begin(); 234db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 235db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *InTy = NULL; 236db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::AllocaInst *AIn = NULL; 237db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasIn(Signature)) { 238db169187dea4602e4ad32058762d23d474753fd0Stephen Hines InTy = Args->getType(); 239db169187dea4602e4ad32058762d23d474753fd0Stephen Hines AIn = Builder.CreateAlloca(InTy, 0, "AIn"); 240db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(Builder.CreatePointerCast(Builder.CreateLoad( 241db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStructGEP(Arg_p, 0)), InTy), AIn); 242db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 243db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 244db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 245db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *OutTy = NULL; 246db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::AllocaInst *AOut = NULL; 247db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasOut(Signature)) { 248db169187dea4602e4ad32058762d23d474753fd0Stephen Hines OutTy = Args->getType(); 249db169187dea4602e4ad32058762d23d474753fd0Stephen Hines AOut = Builder.CreateAlloca(OutTy, 0, "AOut"); 250db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(Builder.CreatePointerCast(Builder.CreateLoad( 251db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStructGEP(Arg_p, 1)), OutTy), AOut); 252db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 253db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 254db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 255db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *UsrData = NULL; 256db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasUsrData(Signature)) { 257db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *UsrDataTy = Args->getType(); 258db169187dea4602e4ad32058762d23d474753fd0Stephen Hines UsrData = Builder.CreatePointerCast(Builder.CreateLoad( 259db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStructGEP(Arg_p, 2)), UsrDataTy); 260db169187dea4602e4ad32058762d23d474753fd0Stephen Hines UsrData->setName("UsrData"); 261db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 262db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 263db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 264db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasX(Signature)) { 265db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 266db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 267db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 268db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Y = NULL; 269db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasY(Signature)) { 270db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Y = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 5), "Y"); 271db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 272db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 273db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 2747a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#if !RS_FOREACH_EXPAND_PASS_NDEBUG 2757a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao if (Args != F->arg_end()) { 2767a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao ALOGE("Assert failed at %s:%d: Invalid signature to the foreach function " 2777a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao "'%s'!", __FILE__, __LINE__, F->getName().str().c_str()); 2787a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao ::abort(); 2797a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao } 2807a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao#endif 281db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 282db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock *Loop = llvm::BasicBlock::Create(*C, "Loop", ExpandedFunc); 283db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock *Exit = llvm::BasicBlock::Create(*C, "Exit", ExpandedFunc); 284db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 285db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // if (x1 < x2) goto Loop; else goto Exit; 286db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Cond = Builder.CreateICmpSLT(Arg_x1, Arg_x2); 287db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateCondBr(Cond, Loop, Exit); 288db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 289db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Loop: 290db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.SetInsertPoint(Loop); 291db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 292cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines // Populate the actual call to kernel(). 293db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Value*, 8> RootArgs; 294db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 295db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *In = NULL; 296db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Out = NULL; 297db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 298db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (AIn) { 299db169187dea4602e4ad32058762d23d474753fd0Stephen Hines In = Builder.CreateLoad(AIn, "In"); 300db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(In); 301db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 302db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 303db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (AOut) { 304db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Out = Builder.CreateLoad(AOut, "Out"); 305db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(Out); 306db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 307db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 308db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (UsrData) { 309db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(UsrData); 310db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 311db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 312db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // We always have to load X, since it is used to iterate through the loop. 313db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *X = Builder.CreateLoad(AX, "X"); 314db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasX(Signature)) { 315db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(X); 316db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 317db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 318db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (Y) { 319db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(Y); 320db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 321db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 322db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateCall(F, RootArgs); 323db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 324db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (In) { 325db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // In += instep 326db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *NewIn = Builder.CreateIntToPtr(Builder.CreateNUWAdd( 327db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreatePtrToInt(In, Int32Ty), Arg_instep), InTy); 328db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(NewIn, AIn); 329db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 330db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 331db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (Out) { 332db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Out += outstep 333db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *NewOut = Builder.CreateIntToPtr(Builder.CreateNUWAdd( 334db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreatePtrToInt(Out, Int32Ty), Arg_outstep), OutTy); 335db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(NewOut, AOut); 336db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 337db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 338db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // X++; 339db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *XPlusOne = 340db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateNUWAdd(X, llvm::ConstantInt::get(Int32Ty, 1)); 341db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(XPlusOne, AX); 342db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 343db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // If (X < x2) goto Loop; else goto Exit; 344db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Cond = Builder.CreateICmpSLT(XPlusOne, Arg_x2); 345db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateCondBr(Cond, Loop, Exit); 346db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 347db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Exit: 348db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.SetInsertPoint(Exit); 349db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateRetVoid(); 350db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 351db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return true; 352db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 353db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 354db169187dea4602e4ad32058762d23d474753fd0Stephen Hines virtual bool runOnModule(llvm::Module &M) { 355cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines bool Changed = false; 356db169187dea4602e4ad32058762d23d474753fd0Stephen Hines this->M = &M; 357db169187dea4602e4ad32058762d23d474753fd0Stephen Hines C = &M.getContext(); 358db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 3597a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao for (RSInfo::ExportForeachFuncListTy::const_iterator 3607a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao func_iter = mFuncs.begin(), func_end = mFuncs.end(); 3617a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao func_iter != func_end; func_iter++) { 3627a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao const char *name = func_iter->first; 3637a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao uint32_t signature = func_iter->second; 3647a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao llvm::Function *kernel = M.getFunction(name); 365cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines if (kernel && kernel->getReturnType()->isVoidTy()) { 3667a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao Changed |= ExpandFunction(kernel, signature); 367cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines } 368db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 369db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 370cc366e573e31f43a6101fd6e04b90c6afdc3b7a7Stephen Hines return Changed; 371db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 372db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 373db169187dea4602e4ad32058762d23d474753fd0Stephen Hines virtual const char *getPassName() const { 374db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return "ForEach-able Function Expansion"; 375db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 376db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 3777a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao}; // end RSForEachExpandPass 378db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 3797a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao} // end anonymous namespace 3807a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao 3817a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liaochar RSForEachExpandPass::ID = 0; 382db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 383db169187dea4602e4ad32058762d23d474753fd0Stephen Hinesnamespace bcc { 384db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 3857a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liaollvm::ModulePass * 3867a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei LiaocreateRSForEachExpandPass(const RSInfo::ExportForeachFuncListTy &pForeachFuncs){ 3877a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao return new RSForEachExpandPass(pForeachFuncs); 3887a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao} 389db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 3907a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao} // end namespace bcc 391