RSKernelExpand.cpp revision db169187dea4602e4ad32058762d23d474753fd0
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 17db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "Config.h" 18db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "bcc/bcc_assert.h" 19db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 20db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "DebugHelper.h" 21db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 22db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/DerivedTypes.h" 23db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/Function.h" 24db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/Instructions.h" 25db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/Module.h" 26db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/Pass.h" 27db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/Type.h" 28db169187dea4602e4ad32058762d23d474753fd0Stephen Hines#include "llvm/Support/IRBuilder.h" 29db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 30db169187dea4602e4ad32058762d23d474753fd0Stephen Hinesnamespace { 31db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* ForEachExpandPass - This pass operates on functions that are able to be 32db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * called via rsForEach() or "foreach_<NAME>". We create an inner loop for 33db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * the ForEach-able function to be invoked over the appropriate data cells 34db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * of the input/output allocations (adjusting other relevant parameters as 35db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * we go). We currently only support doing this for compute "root" functions. 36db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * The new function name is the original function name followed by 37db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * ".expanded". Note that we still generate code for the original function. 38db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 39db169187dea4602e4ad32058762d23d474753fd0Stephen Hines class ForEachExpandPass : public llvm::ModulePass { 40db169187dea4602e4ad32058762d23d474753fd0Stephen Hines private: 41db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static char ID; 42db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 43db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Module *M; 44db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::LLVMContext *C; 45db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 46db169187dea4602e4ad32058762d23d474753fd0Stephen Hines uint32_t getSignature(llvm::Function *F) { 47db169187dea4602e4ad32058762d23d474753fd0Stephen Hines const llvm::NamedMDNode *ExportForEachMetadata = 48db169187dea4602e4ad32058762d23d474753fd0Stephen Hines M->getNamedMetadata("#rs_export_foreach"); 49db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 50db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (!ExportForEachMetadata) { 51db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Type*, 8> RootArgTys; 52db169187dea4602e4ad32058762d23d474753fd0Stephen Hines for (llvm::Function::arg_iterator B = F->arg_begin(), 53db169187dea4602e4ad32058762d23d474753fd0Stephen Hines E = F->arg_end(); 54db169187dea4602e4ad32058762d23d474753fd0Stephen Hines B != E; 55db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ++B) { 56db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgTys.push_back(B->getType()); 57db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 58db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 59db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // For pre-ICS bitcode, we may not have signature information. In that 60db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // case, we use the size of the RootArgTys to select the number of 61db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // arguments. 62db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return (1 << RootArgTys.size()) - 1; 63db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 64db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 65db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // We only handle the case for root() functions today, so this is 66db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // hard-coded to look at only the first such function. 67db169187dea4602e4ad32058762d23d474753fd0Stephen Hines bccAssert(ExportForEachMetadata->getNumOperands() > 0); 68db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 69db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(0); 70db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (SigNode != NULL && SigNode->getNumOperands() == 1) { 71db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *SigVal = SigNode->getOperand(0); 72db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (SigVal->getValueID() == llvm::Value::MDStringVal) { 73db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::StringRef SigString = 74db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static_cast<llvm::MDString*>(SigVal)->getString(); 75db169187dea4602e4ad32058762d23d474753fd0Stephen Hines uint32_t Signature = 0; 76db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (SigString.getAsInteger(10, Signature)) { 77db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ALOGE("Non-integer signature value '%s'", SigString.str().c_str()); 78db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return 0; 79db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 80db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature; 81db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 82db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 83db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 84db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return 0; 85db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 86db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 87db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasIn(uint32_t Signature) { 88db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 1; 89db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 90db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 91db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasOut(uint32_t Signature) { 92db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 2; 93db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 94db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 95db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasUsrData(uint32_t Signature) { 96db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 4; 97db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 98db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 99db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasX(uint32_t Signature) { 100db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 8; 101db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 102db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 103db169187dea4602e4ad32058762d23d474753fd0Stephen Hines static bool hasY(uint32_t Signature) { 104db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return Signature & 16; 105db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 106db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 107db169187dea4602e4ad32058762d23d474753fd0Stephen Hines public: 108db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ForEachExpandPass() 109db169187dea4602e4ad32058762d23d474753fd0Stephen Hines : ModulePass(ID), M(NULL), C(NULL) { 110db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 111db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 112db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* Performs the actual optimization on a selected function. On success, the 113db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * Module will contain a new function of the name "<NAME>.expand" that 114db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * invokes <NAME>() in a loop with the appropriate parameters. 115db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 116db169187dea4602e4ad32058762d23d474753fd0Stephen Hines bool ExpandFunction(llvm::Function *F) { 117db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ALOGV("Expanding a ForEach-able Function"); 118db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 119db169187dea4602e4ad32058762d23d474753fd0Stephen Hines uint32_t Signature = getSignature(F); 120db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (!Signature) { 121db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // We couldn't determine how to expand this function based on its 122db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // function signature. 123db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return false; 124db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 125db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 126db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*C); 127db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*C); 128db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *SizeTy = Int32Ty; 129db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 130db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* Defined in frameworks/base/libs/rs/rs_hal.h: 131db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * 132db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * struct RsForEachStubParamStruct { 133db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * const void *in; 134db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * void *out; 135db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * const void *usr; 136db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * size_t usr_len; 137db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t x; 138db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t y; 139db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t z; 140db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t lod; 141db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * enum RsAllocationCubemapFace face; 142db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t ar[16]; 143db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * }; 144db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 145db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Type*, 9> StructTys; 146db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(VoidPtrTy); // const void *in 147db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(VoidPtrTy); // void *out 148db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(VoidPtrTy); // const void *usr 149db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(SizeTy); // size_t usr_len 150db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t x 151db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t y 152db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t z 153db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // uint32_t lod 154db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(Int32Ty); // enum RsAllocationCubemapFace 155db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys.push_back(llvm::ArrayType::get(Int32Ty, 16)); // uint32_t ar[16] 156db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 157db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *ForEachStubPtrTy = llvm::StructType::create( 158db169187dea4602e4ad32058762d23d474753fd0Stephen Hines StructTys, "RsForEachStubParamStruct")->getPointerTo(); 159db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 160db169187dea4602e4ad32058762d23d474753fd0Stephen Hines /* Create the function signature for our expanded function. 161db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * void (const RsForEachStubParamStruct *p, uint32_t x1, uint32_t x2, 162db169187dea4602e4ad32058762d23d474753fd0Stephen Hines * uint32_t instep, uint32_t outstep) 163db169187dea4602e4ad32058762d23d474753fd0Stephen Hines */ 164db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Type*, 8> ParamTys; 165db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(ForEachStubPtrTy); // const RsForEachStubParamStruct *p 166db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t x1 167db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t x2 168db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t instep 169db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ParamTys.push_back(Int32Ty); // uint32_t outstep 170db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 171db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::FunctionType *FT = 172db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::FunctionType::get(llvm::Type::getVoidTy(*C), ParamTys, false); 173db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function *ExpandedFunc = 174db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function::Create(FT, 175db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::GlobalValue::ExternalLinkage, 176db169187dea4602e4ad32058762d23d474753fd0Stephen Hines F->getName() + ".expand", M); 177db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 178db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Create and name the actual arguments to this expanded function. 179db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Argument*, 8> ArgVec; 180db169187dea4602e4ad32058762d23d474753fd0Stephen Hines for (llvm::Function::arg_iterator B = ExpandedFunc->arg_begin(), 181db169187dea4602e4ad32058762d23d474753fd0Stephen Hines E = ExpandedFunc->arg_end(); 182db169187dea4602e4ad32058762d23d474753fd0Stephen Hines B != E; 183db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ++B) { 184db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ArgVec.push_back(B); 185db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 186db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 187db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (ArgVec.size() != 5) { 188db169187dea4602e4ad32058762d23d474753fd0Stephen Hines ALOGE("Incorrect number of arguments to function: %d", ArgVec.size()); 189db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return false; 190db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 191db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_p = ArgVec[0]; 192db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_x1 = ArgVec[1]; 193db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_x2 = ArgVec[2]; 194db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_instep = ArgVec[3]; 195db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Arg_outstep = ArgVec[4]; 196db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 197db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_p->setName("p"); 198db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_x1->setName("x1"); 199db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_x2->setName("x2"); 200db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_instep->setName("instep"); 201db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Arg_outstep->setName("outstep"); 202db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 203db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Construct the actual function body. 204db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock *Begin = 205db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock::Create(*C, "Begin", ExpandedFunc); 206db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::IRBuilder<> Builder(Begin); 207db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 208db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // uint32_t X = x1; 209db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::AllocaInst *AX = Builder.CreateAlloca(Int32Ty, 0, "AX"); 210db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(Arg_x1, AX); 211db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 212db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Collect and construct the arguments for root(). 213db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Note that we load any loop-invariant arguments before entering the Loop. 214db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function::arg_iterator Args = F->arg_begin(); 215db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 216db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *InTy = NULL; 217db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::AllocaInst *AIn = NULL; 218db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasIn(Signature)) { 219db169187dea4602e4ad32058762d23d474753fd0Stephen Hines InTy = Args->getType(); 220db169187dea4602e4ad32058762d23d474753fd0Stephen Hines AIn = Builder.CreateAlloca(InTy, 0, "AIn"); 221db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(Builder.CreatePointerCast(Builder.CreateLoad( 222db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStructGEP(Arg_p, 0)), InTy), AIn); 223db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 224db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 225db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 226db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *OutTy = NULL; 227db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::AllocaInst *AOut = NULL; 228db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasOut(Signature)) { 229db169187dea4602e4ad32058762d23d474753fd0Stephen Hines OutTy = Args->getType(); 230db169187dea4602e4ad32058762d23d474753fd0Stephen Hines AOut = Builder.CreateAlloca(OutTy, 0, "AOut"); 231db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(Builder.CreatePointerCast(Builder.CreateLoad( 232db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStructGEP(Arg_p, 1)), OutTy), AOut); 233db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 234db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 235db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 236db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *UsrData = NULL; 237db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasUsrData(Signature)) { 238db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Type *UsrDataTy = Args->getType(); 239db169187dea4602e4ad32058762d23d474753fd0Stephen Hines UsrData = Builder.CreatePointerCast(Builder.CreateLoad( 240db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStructGEP(Arg_p, 2)), UsrDataTy); 241db169187dea4602e4ad32058762d23d474753fd0Stephen Hines UsrData->setName("UsrData"); 242db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 243db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 244db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 245db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasX(Signature)) { 246db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 247db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 248db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 249db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Y = NULL; 250db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasY(Signature)) { 251db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Y = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 5), "Y"); 252db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Args++; 253db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 254db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 255db169187dea4602e4ad32058762d23d474753fd0Stephen Hines bccAssert(Args == F->arg_end()); 256db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 257db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock *Loop = llvm::BasicBlock::Create(*C, "Loop", ExpandedFunc); 258db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::BasicBlock *Exit = llvm::BasicBlock::Create(*C, "Exit", ExpandedFunc); 259db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 260db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // if (x1 < x2) goto Loop; else goto Exit; 261db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Cond = Builder.CreateICmpSLT(Arg_x1, Arg_x2); 262db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateCondBr(Cond, Loop, Exit); 263db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 264db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Loop: 265db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.SetInsertPoint(Loop); 266db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 267db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Populate the actual call to root(). 268db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::SmallVector<llvm::Value*, 8> RootArgs; 269db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 270db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *In = NULL; 271db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *Out = NULL; 272db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 273db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (AIn) { 274db169187dea4602e4ad32058762d23d474753fd0Stephen Hines In = Builder.CreateLoad(AIn, "In"); 275db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(In); 276db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 277db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 278db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (AOut) { 279db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Out = Builder.CreateLoad(AOut, "Out"); 280db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(Out); 281db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 282db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 283db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (UsrData) { 284db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(UsrData); 285db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 286db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 287db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // We always have to load X, since it is used to iterate through the loop. 288db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *X = Builder.CreateLoad(AX, "X"); 289db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (hasX(Signature)) { 290db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(X); 291db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 292db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 293db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (Y) { 294db169187dea4602e4ad32058762d23d474753fd0Stephen Hines RootArgs.push_back(Y); 295db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 296db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 297db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateCall(F, RootArgs); 298db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 299db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (In) { 300db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // In += instep 301db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *NewIn = Builder.CreateIntToPtr(Builder.CreateNUWAdd( 302db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreatePtrToInt(In, Int32Ty), Arg_instep), InTy); 303db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(NewIn, AIn); 304db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 305db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 306db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (Out) { 307db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Out += outstep 308db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *NewOut = Builder.CreateIntToPtr(Builder.CreateNUWAdd( 309db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreatePtrToInt(Out, Int32Ty), Arg_outstep), OutTy); 310db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(NewOut, AOut); 311db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 312db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 313db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // X++; 314db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Value *XPlusOne = 315db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateNUWAdd(X, llvm::ConstantInt::get(Int32Ty, 1)); 316db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateStore(XPlusOne, AX); 317db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 318db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // If (X < x2) goto Loop; else goto Exit; 319db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Cond = Builder.CreateICmpSLT(XPlusOne, Arg_x2); 320db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateCondBr(Cond, Loop, Exit); 321db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 322db169187dea4602e4ad32058762d23d474753fd0Stephen Hines // Exit: 323db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.SetInsertPoint(Exit); 324db169187dea4602e4ad32058762d23d474753fd0Stephen Hines Builder.CreateRetVoid(); 325db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 326db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return true; 327db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 328db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 329db169187dea4602e4ad32058762d23d474753fd0Stephen Hines virtual bool runOnModule(llvm::Module &M) { 330db169187dea4602e4ad32058762d23d474753fd0Stephen Hines this->M = &M; 331db169187dea4602e4ad32058762d23d474753fd0Stephen Hines C = &M.getContext(); 332db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 333db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::Function *root = M.getFunction("root"); 334db169187dea4602e4ad32058762d23d474753fd0Stephen Hines if (root && root->getReturnType()->isVoidTy()) { 335db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return ExpandFunction(root); 336db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 337db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 338db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return false; 339db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 340db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 341db169187dea4602e4ad32058762d23d474753fd0Stephen Hines virtual const char *getPassName() const { 342db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return "ForEach-able Function Expansion"; 343db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 344db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 345db169187dea4602e4ad32058762d23d474753fd0Stephen Hines }; 346db169187dea4602e4ad32058762d23d474753fd0Stephen Hines} // end anonymous namespace 347db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 348db169187dea4602e4ad32058762d23d474753fd0Stephen Hineschar ForEachExpandPass::ID = 0; 349db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 350db169187dea4602e4ad32058762d23d474753fd0Stephen Hinesnamespace bcc { 351db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 352db169187dea4602e4ad32058762d23d474753fd0Stephen Hines llvm::ModulePass *createForEachExpandPass() { 353db169187dea4602e4ad32058762d23d474753fd0Stephen Hines return new ForEachExpandPass(); 354db169187dea4602e4ad32058762d23d474753fd0Stephen Hines } 355db169187dea4602e4ad32058762d23d474753fd0Stephen Hines 356db169187dea4602e4ad32058762d23d474753fd0Stephen Hines} // namespace bcc 357