RSForEachExpand.cpp revision 25eb586bb055ae07c7e82a2b1bdbd6936641580c
1/*
2 * Copyright 2012, 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
17#include "bcc/Assert.h"
18#include "bcc/Renderscript/RSTransforms.h"
19
20#include <cstdlib>
21
22#include <llvm/IR/DerivedTypes.h>
23#include <llvm/IR/Function.h>
24#include <llvm/IR/Instructions.h>
25#include <llvm/IR/IRBuilder.h>
26#include <llvm/IR/MDBuilder.h>
27#include <llvm/IR/Module.h>
28#include <llvm/Pass.h>
29#include <llvm/Support/raw_ostream.h>
30#include <llvm/IR/DataLayout.h>
31#include <llvm/IR/Function.h>
32#include <llvm/IR/Type.h>
33#include <llvm/Transforms/Utils/BasicBlockUtils.h>
34
35#include "bcc/Config/Config.h"
36#include "bcc/Support/Log.h"
37
38#include "bcinfo/MetadataExtractor.h"
39
40using namespace bcc;
41
42namespace {
43
44static const bool gEnableRsTbaa = true;
45
46/* RSForEachExpandPass - This pass operates on functions that are able to be
47 * called via rsForEach() or "foreach_<NAME>". We create an inner loop for the
48 * ForEach-able function to be invoked over the appropriate data cells of the
49 * input/output allocations (adjusting other relevant parameters as we go). We
50 * support doing this for any ForEach-able compute kernels. The new function
51 * name is the original function name followed by ".expand". Note that we
52 * still generate code for the original function.
53 */
54class RSForEachExpandPass : public llvm::ModulePass {
55private:
56  static char ID;
57
58  llvm::Module *M;
59  llvm::LLVMContext *C;
60
61  uint32_t mExportForEachCount;
62  const char **mExportForEachNameList;
63  const uint32_t *mExportForEachSignatureList;
64
65  // Turns on optimization of allocation stride values.
66  bool mEnableStepOpt;
67
68  uint32_t getRootSignature(llvm::Function *F) {
69    const llvm::NamedMDNode *ExportForEachMetadata =
70        M->getNamedMetadata("#rs_export_foreach");
71
72    if (!ExportForEachMetadata) {
73      llvm::SmallVector<llvm::Type*, 8> RootArgTys;
74      for (llvm::Function::arg_iterator B = F->arg_begin(),
75                                        E = F->arg_end();
76           B != E;
77           ++B) {
78        RootArgTys.push_back(B->getType());
79      }
80
81      // For pre-ICS bitcode, we may not have signature information. In that
82      // case, we use the size of the RootArgTys to select the number of
83      // arguments.
84      return (1 << RootArgTys.size()) - 1;
85    }
86
87    if (ExportForEachMetadata->getNumOperands() == 0) {
88      return 0;
89    }
90
91    bccAssert(ExportForEachMetadata->getNumOperands() > 0);
92
93    // We only handle the case for legacy root() functions here, so this is
94    // hard-coded to look at only the first such function.
95    llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(0);
96    if (SigNode != NULL && SigNode->getNumOperands() == 1) {
97      llvm::Value *SigVal = SigNode->getOperand(0);
98      if (SigVal->getValueID() == llvm::Value::MDStringVal) {
99        llvm::StringRef SigString =
100            static_cast<llvm::MDString*>(SigVal)->getString();
101        uint32_t Signature = 0;
102        if (SigString.getAsInteger(10, Signature)) {
103          ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
104          return 0;
105        }
106        return Signature;
107      }
108    }
109
110    return 0;
111  }
112
113  // Get the actual value we should use to step through an allocation.
114  //
115  // Normally the value we use to step through an allocation is given to us by
116  // the driver. However, for certain primitive data types, we can derive an
117  // integer constant for the step value. We use this integer constant whenever
118  // possible to allow further compiler optimizations to take place.
119  //
120  // DL - Target Data size/layout information.
121  // T - Type of allocation (should be a pointer).
122  // OrigStep - Original step increment (root.expand() input from driver).
123  llvm::Value *getStepValue(llvm::DataLayout *DL, llvm::Type *T,
124                            llvm::Value *OrigStep) {
125    bccAssert(DL);
126    bccAssert(T);
127    bccAssert(OrigStep);
128    llvm::PointerType *PT = llvm::dyn_cast<llvm::PointerType>(T);
129    llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*C);
130    if (mEnableStepOpt && T != VoidPtrTy && PT) {
131      llvm::Type *ET = PT->getElementType();
132      uint64_t ETSize = DL->getTypeAllocSize(ET);
133      llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*C);
134      return llvm::ConstantInt::get(Int32Ty, ETSize);
135    } else {
136      return OrigStep;
137    }
138  }
139
140  /// @brief Returns the type of the ForEach stub parameter structure.
141  ///
142  /// Renderscript uses a single structure in which all parameters are passed
143  /// to keep the signature of the expanded function independent of the
144  /// parameters passed to it.
145  llvm::Type *getForeachStubTy() {
146    llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*C);
147    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*C);
148    llvm::Type *SizeTy = Int32Ty;
149    /* Defined in frameworks/base/libs/rs/rs_hal.h:
150     *
151     * struct RsForEachStubParamStruct {
152     *   const void *in;
153     *   void *out;
154     *   const void *usr;
155     *   size_t usr_len;
156     *   uint32_t x;
157     *   uint32_t y;
158     *   uint32_t z;
159     *   uint32_t lod;
160     *   enum RsAllocationCubemapFace face;
161     *   uint32_t ar[16];
162     * };
163     */
164    llvm::SmallVector<llvm::Type*, 9> StructTys;
165    StructTys.push_back(VoidPtrTy);  // const void *in
166    StructTys.push_back(VoidPtrTy);  // void *out
167    StructTys.push_back(VoidPtrTy);  // const void *usr
168    StructTys.push_back(SizeTy);     // size_t usr_len
169    StructTys.push_back(Int32Ty);    // uint32_t x
170    StructTys.push_back(Int32Ty);    // uint32_t y
171    StructTys.push_back(Int32Ty);    // uint32_t z
172    StructTys.push_back(Int32Ty);    // uint32_t lod
173    StructTys.push_back(Int32Ty);    // enum RsAllocationCubemapFace
174    StructTys.push_back(llvm::ArrayType::get(Int32Ty, 16));  // uint32_t ar[16]
175
176    return llvm::StructType::create(StructTys, "RsForEachStubParamStruct");
177  }
178
179  /// @brief Create skeleton of the expanded function.
180  ///
181  /// This creates a function with the following signature:
182  ///
183  ///   void (const RsForEachStubParamStruct *p, uint32_t x1, uint32_t x2,
184  ///         uint32_t instep, uint32_t outstep)
185  ///
186  llvm::Function *createEmptyExpandedFunction(llvm::StringRef OldName) {
187    llvm::Type *ForEachStubPtrTy = getForeachStubTy()->getPointerTo();
188    llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*C);
189
190    llvm::SmallVector<llvm::Type*, 8> ParamTys;
191    ParamTys.push_back(ForEachStubPtrTy);  // const RsForEachStubParamStruct *p
192    ParamTys.push_back(Int32Ty);           // uint32_t x1
193    ParamTys.push_back(Int32Ty);           // uint32_t x2
194    ParamTys.push_back(Int32Ty);           // uint32_t instep
195    ParamTys.push_back(Int32Ty);           // uint32_t outstep
196
197    llvm::FunctionType *FT =
198        llvm::FunctionType::get(llvm::Type::getVoidTy(*C), ParamTys, false);
199    llvm::Function *F =
200        llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage,
201                               OldName + ".expand", M);
202
203    llvm::Function::arg_iterator AI = F->arg_begin();
204
205    AI->setName("p");
206    AI++;
207    AI->setName("x1");
208    AI++;
209    AI->setName("x2");
210    AI++;
211    AI->setName("arg_instep");
212    AI++;
213    AI->setName("arg_outstep");
214    AI++;
215
216    assert(AI == F->arg_end());
217
218    llvm::BasicBlock *Begin = llvm::BasicBlock::Create(*C, "Begin", F);
219    llvm::IRBuilder<> Builder(Begin);
220    Builder.CreateRetVoid();
221
222    return F;
223  }
224
225  /// @brief Create an empty loop
226  ///
227  /// Create a loop of the form:
228  ///
229  /// for (i = LowerBound; i < UpperBound; i++)
230  ///   ;
231  ///
232  /// After the loop has been created, the builder is set such that
233  /// instructions can be added to the loop body.
234  ///
235  /// @param Builder The builder to use to build this loop. The current
236  ///                position of the builder is the position the loop
237  ///                will be inserted.
238  /// @param LowerBound The first value of the loop iterator
239  /// @param UpperBound The maximal value of the loop iterator
240  /// @param LoopIV A reference that will be set to the loop iterator.
241  /// @return The BasicBlock that will be executed after the loop.
242  llvm::BasicBlock *createLoop(llvm::IRBuilder<> &Builder,
243                               llvm::Value *LowerBound,
244                               llvm::Value *UpperBound,
245                               llvm::PHINode **LoopIV) {
246    assert(LowerBound->getType() == UpperBound->getType());
247
248    llvm::BasicBlock *CondBB, *AfterBB, *HeaderBB;
249    llvm::Value *Cond, *IVNext;
250    llvm::PHINode *IV;
251
252    CondBB = Builder.GetInsertBlock();
253    AfterBB = llvm::SplitBlock(CondBB, Builder.GetInsertPoint(), this);
254    HeaderBB = llvm::BasicBlock::Create(*C, "Loop", CondBB->getParent());
255
256    // if (LowerBound < Upperbound)
257    //   goto LoopHeader
258    // else
259    //   goto AfterBB
260    CondBB->getTerminator()->eraseFromParent();
261    Builder.SetInsertPoint(CondBB);
262    Cond = Builder.CreateICmpULT(LowerBound, UpperBound);
263    Builder.CreateCondBr(Cond, HeaderBB, AfterBB);
264
265    // iv = PHI [CondBB -> LowerBound], [LoopHeader -> NextIV ]
266    // iv.next = iv + 1
267    // if (iv.next < Upperbound)
268    //   goto LoopHeader
269    // else
270    //   goto AfterBB
271    Builder.SetInsertPoint(HeaderBB);
272    IV = Builder.CreatePHI(LowerBound->getType(), 2, "X");
273    IV->addIncoming(LowerBound, CondBB);
274    IVNext = Builder.CreateNUWAdd(IV, Builder.getInt32(1));
275    IV->addIncoming(IVNext, HeaderBB);
276    Cond = Builder.CreateICmpULT(IVNext, UpperBound);
277    Builder.CreateCondBr(Cond, HeaderBB, AfterBB);
278    AfterBB->setName("Exit");
279    Builder.SetInsertPoint(HeaderBB->getFirstNonPHI());
280    *LoopIV = IV;
281    return AfterBB;
282  }
283
284public:
285  RSForEachExpandPass(bool pEnableStepOpt)
286      : ModulePass(ID), M(NULL), C(NULL), mEnableStepOpt(pEnableStepOpt) {
287  }
288
289  /* Performs the actual optimization on a selected function. On success, the
290   * Module will contain a new function of the name "<NAME>.expand" that
291   * invokes <NAME>() in a loop with the appropriate parameters.
292   */
293  bool ExpandFunction(llvm::Function *F, uint32_t Signature) {
294    ALOGV("Expanding ForEach-able Function %s", F->getName().str().c_str());
295
296    if (!Signature) {
297      Signature = getRootSignature(F);
298      if (!Signature) {
299        // We couldn't determine how to expand this function based on its
300        // function signature.
301        return false;
302      }
303    }
304
305    llvm::DataLayout DL(M);
306
307    llvm::Function *ExpandedFunc = createEmptyExpandedFunction(F->getName());
308
309    // Create and name the actual arguments to this expanded function.
310    llvm::SmallVector<llvm::Argument*, 8> ArgVec;
311    for (llvm::Function::arg_iterator B = ExpandedFunc->arg_begin(),
312                                      E = ExpandedFunc->arg_end();
313         B != E;
314         ++B) {
315      ArgVec.push_back(B);
316    }
317
318    if (ArgVec.size() != 5) {
319      ALOGE("Incorrect number of arguments to function: %zu",
320            ArgVec.size());
321      return false;
322    }
323    llvm::Value *Arg_p = ArgVec[0];
324    llvm::Value *Arg_x1 = ArgVec[1];
325    llvm::Value *Arg_x2 = ArgVec[2];
326    llvm::Value *Arg_instep = ArgVec[3];
327    llvm::Value *Arg_outstep = ArgVec[4];
328
329    llvm::Value *InStep = NULL;
330    llvm::Value *OutStep = NULL;
331
332    // Construct the actual function body.
333    llvm::IRBuilder<> Builder(ExpandedFunc->getEntryBlock().begin());
334
335    // Collect and construct the arguments for the kernel().
336    // Note that we load any loop-invariant arguments before entering the Loop.
337    llvm::Function::arg_iterator Args = F->arg_begin();
338
339    llvm::Type *InTy = NULL;
340    llvm::Value *InBasePtr = NULL;
341    if (bcinfo::MetadataExtractor::hasForEachSignatureIn(Signature)) {
342      InTy = Args->getType();
343      InStep = getStepValue(&DL, InTy, Arg_instep);
344      InStep->setName("instep");
345      InBasePtr = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 0));
346      Args++;
347    }
348
349    llvm::Type *OutTy = NULL;
350    llvm::Value *OutBasePtr = NULL;
351    if (bcinfo::MetadataExtractor::hasForEachSignatureOut(Signature)) {
352      OutTy = Args->getType();
353      OutStep = getStepValue(&DL, OutTy, Arg_outstep);
354      OutStep->setName("outstep");
355      OutBasePtr = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 1));
356      Args++;
357    }
358
359    llvm::Value *UsrData = NULL;
360    if (bcinfo::MetadataExtractor::hasForEachSignatureUsrData(Signature)) {
361      llvm::Type *UsrDataTy = Args->getType();
362      UsrData = Builder.CreatePointerCast(Builder.CreateLoad(
363          Builder.CreateStructGEP(Arg_p, 2)), UsrDataTy);
364      UsrData->setName("UsrData");
365      Args++;
366    }
367
368    if (bcinfo::MetadataExtractor::hasForEachSignatureX(Signature)) {
369      Args++;
370    }
371
372    llvm::Value *Y = NULL;
373    if (bcinfo::MetadataExtractor::hasForEachSignatureY(Signature)) {
374      Y = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 5), "Y");
375      Args++;
376    }
377
378    bccAssert(Args == F->arg_end());
379
380    llvm::PHINode *IV;
381    createLoop(Builder, Arg_x1, Arg_x2, &IV);
382
383    // Populate the actual call to kernel().
384    llvm::SmallVector<llvm::Value*, 8> RootArgs;
385
386    llvm::Value *InPtr = NULL;
387    llvm::Value *OutPtr = NULL;
388
389    // Calculate the current input and output pointers
390    //
391    // We always calculate the input/output pointers with a GEP operating on i8
392    // values and only cast at the very end to OutTy. This is because the step
393    // between two values is given in bytes.
394    //
395    // TODO: We could further optimize the output by using a GEP operation of
396    // type 'OutTy' in cases where the element type of the allocation allows.
397    if (OutBasePtr) {
398      llvm::Value *OutOffset = Builder.CreateSub(IV, Arg_x1);
399      OutOffset = Builder.CreateMul(OutOffset, OutStep);
400      OutPtr = Builder.CreateGEP(OutBasePtr, OutOffset);
401      OutPtr = Builder.CreatePointerCast(OutPtr, OutTy);
402    }
403    if (InBasePtr) {
404      llvm::Value *InOffset = Builder.CreateSub(IV, Arg_x1);
405      InOffset = Builder.CreateMul(InOffset, InStep);
406      InPtr = Builder.CreateGEP(InBasePtr, InOffset);
407      InPtr = Builder.CreatePointerCast(InPtr, InTy);
408    }
409
410    if (InPtr) {
411      RootArgs.push_back(InPtr);
412    }
413
414    if (OutPtr) {
415      RootArgs.push_back(OutPtr);
416    }
417
418    if (UsrData) {
419      RootArgs.push_back(UsrData);
420    }
421
422    llvm::Value *X = IV;
423    if (bcinfo::MetadataExtractor::hasForEachSignatureX(Signature)) {
424      RootArgs.push_back(X);
425    }
426
427    if (Y) {
428      RootArgs.push_back(Y);
429    }
430
431    Builder.CreateCall(F, RootArgs);
432
433    return true;
434  }
435
436  /* Expand a pass-by-value kernel.
437   */
438  bool ExpandKernel(llvm::Function *F, uint32_t Signature) {
439    bccAssert(bcinfo::MetadataExtractor::hasForEachSignatureKernel(Signature));
440    ALOGV("Expanding kernel Function %s", F->getName().str().c_str());
441
442    // TODO: Refactor this to share functionality with ExpandFunction.
443    llvm::DataLayout DL(M);
444
445    llvm::Function *ExpandedFunc = createEmptyExpandedFunction(F->getName());
446
447    // Create and name the actual arguments to this expanded function.
448    llvm::SmallVector<llvm::Argument*, 8> ArgVec;
449    for (llvm::Function::arg_iterator B = ExpandedFunc->arg_begin(),
450                                      E = ExpandedFunc->arg_end();
451         B != E;
452         ++B) {
453      ArgVec.push_back(B);
454    }
455
456    if (ArgVec.size() != 5) {
457      ALOGE("Incorrect number of arguments to function: %zu",
458            ArgVec.size());
459      return false;
460    }
461    llvm::Value *Arg_p = ArgVec[0];
462    llvm::Value *Arg_x1 = ArgVec[1];
463    llvm::Value *Arg_x2 = ArgVec[2];
464    llvm::Value *Arg_instep = ArgVec[3];
465    llvm::Value *Arg_outstep = ArgVec[4];
466
467    llvm::Value *InStep = NULL;
468    llvm::Value *OutStep = NULL;
469
470    // Construct the actual function body.
471    llvm::IRBuilder<> Builder(ExpandedFunc->getEntryBlock().begin());
472
473    // Create TBAA meta-data.
474    llvm::MDNode *TBAARenderScript, *TBAAAllocation, *TBAAPointer;
475    llvm::MDBuilder MDHelper(*C);
476
477    TBAARenderScript = MDHelper.createTBAARoot("RenderScript TBAA");
478    TBAAAllocation = MDHelper.createTBAAScalarTypeNode("allocation", TBAARenderScript);
479    TBAAAllocation = MDHelper.createTBAAStructTagNode(TBAAAllocation, TBAAAllocation, 0);
480    TBAAPointer = MDHelper.createTBAAScalarTypeNode("pointer", TBAARenderScript);
481    TBAAPointer = MDHelper.createTBAAStructTagNode(TBAAPointer, TBAAPointer, 0);
482
483    // Collect and construct the arguments for the kernel().
484    // Note that we load any loop-invariant arguments before entering the Loop.
485    llvm::Function::arg_iterator Args = F->arg_begin();
486
487    llvm::Type *OutTy = NULL;
488    bool PassOutByReference = false;
489    llvm::LoadInst *OutBasePtr = NULL;
490    if (bcinfo::MetadataExtractor::hasForEachSignatureOut(Signature)) {
491      llvm::Type *OutBaseTy = F->getReturnType();
492      if (OutBaseTy->isVoidTy()) {
493        PassOutByReference = true;
494        OutTy = Args->getType();
495        Args++;
496      } else {
497        OutTy = OutBaseTy->getPointerTo();
498        // We don't increment Args, since we are using the actual return type.
499      }
500      OutStep = getStepValue(&DL, OutTy, Arg_outstep);
501      OutStep->setName("outstep");
502      OutBasePtr = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 1));
503      if (gEnableRsTbaa) {
504        OutBasePtr->setMetadata("tbaa", TBAAPointer);
505      }
506    }
507
508    llvm::Type *InBaseTy = NULL;
509    llvm::Type *InTy = NULL;
510    llvm::LoadInst *InBasePtr = NULL;
511    if (bcinfo::MetadataExtractor::hasForEachSignatureIn(Signature)) {
512      InBaseTy = Args->getType();
513      InTy =InBaseTy->getPointerTo();
514      InStep = getStepValue(&DL, InTy, Arg_instep);
515      InStep->setName("instep");
516      InBasePtr = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 0));
517      if (gEnableRsTbaa) {
518        InBasePtr->setMetadata("tbaa", TBAAPointer);
519      }
520      Args++;
521    }
522
523    // No usrData parameter on kernels.
524    bccAssert(
525        !bcinfo::MetadataExtractor::hasForEachSignatureUsrData(Signature));
526
527    if (bcinfo::MetadataExtractor::hasForEachSignatureX(Signature)) {
528      Args++;
529    }
530
531    llvm::Value *Y = NULL;
532    if (bcinfo::MetadataExtractor::hasForEachSignatureY(Signature)) {
533      Y = Builder.CreateLoad(Builder.CreateStructGEP(Arg_p, 5), "Y");
534      Args++;
535    }
536
537    bccAssert(Args == F->arg_end());
538
539    llvm::PHINode *IV;
540    createLoop(Builder, Arg_x1, Arg_x2, &IV);
541
542    // Populate the actual call to kernel().
543    llvm::SmallVector<llvm::Value*, 8> RootArgs;
544
545    llvm::Value *InPtr = NULL;
546    llvm::Value *OutPtr = NULL;
547
548    // Calculate the current input and output pointers
549    //
550    // We always calculate the input/output pointers with a GEP operating on i8
551    // values and only cast at the very end to OutTy. This is because the step
552    // between two values is given in bytes.
553    //
554    // TODO: We could further optimize the output by using a GEP operation of
555    // type 'OutTy' in cases where the element type of the allocation allows.
556    if (OutBasePtr) {
557      llvm::Value *OutOffset = Builder.CreateSub(IV, Arg_x1);
558      OutOffset = Builder.CreateMul(OutOffset, OutStep);
559      OutPtr = Builder.CreateGEP(OutBasePtr, OutOffset);
560      OutPtr = Builder.CreatePointerCast(OutPtr, OutTy);
561    }
562    if (InBasePtr) {
563      llvm::Value *InOffset = Builder.CreateSub(IV, Arg_x1);
564      InOffset = Builder.CreateMul(InOffset, InStep);
565      InPtr = Builder.CreateGEP(InBasePtr, InOffset);
566      InPtr = Builder.CreatePointerCast(InPtr, InTy);
567    }
568
569    if (PassOutByReference) {
570      RootArgs.push_back(OutPtr);
571    }
572
573    if (InPtr) {
574      llvm::LoadInst *In = Builder.CreateLoad(InPtr, "In");
575      if (gEnableRsTbaa) {
576        In->setMetadata("tbaa", TBAAAllocation);
577      }
578      RootArgs.push_back(In);
579    }
580
581    llvm::Value *X = IV;
582    if (bcinfo::MetadataExtractor::hasForEachSignatureX(Signature)) {
583      RootArgs.push_back(X);
584    }
585
586    if (Y) {
587      RootArgs.push_back(Y);
588    }
589
590    llvm::Value *RetVal = Builder.CreateCall(F, RootArgs);
591
592    if (OutPtr && !PassOutByReference) {
593      llvm::StoreInst *Store = Builder.CreateStore(RetVal, OutPtr);
594      if (gEnableRsTbaa) {
595        Store->setMetadata("tbaa", TBAAAllocation);
596      }
597    }
598
599    return true;
600  }
601
602  /// @brief Checks if pointers to allocation internals are exposed
603  ///
604  /// This function verifies if through the parameters passed to the kernel
605  /// or through calls to the runtime library the script gains access to
606  /// pointers pointing to data within a RenderScript Allocation.
607  /// If we know we control all loads from and stores to data within
608  /// RenderScript allocations and if we know the run-time internal accesses
609  /// are all annotated with RenderScript TBAA metadata, only then we
610  /// can safely use TBAA to distinguish between generic and from-allocation
611  /// pointers.
612  bool allocPointersExposed(llvm::Module &M) {
613    // Old style kernel function can expose pointers to elements within
614    // allocations.
615    // TODO: Extend analysis to allow simple cases of old-style kernels.
616    for (size_t i = 0; i < mExportForEachCount; ++i) {
617      const char *Name = mExportForEachNameList[i];
618      uint32_t Signature = mExportForEachSignatureList[i];
619      if (M.getFunction(Name) &&
620          !bcinfo::MetadataExtractor::hasForEachSignatureKernel(Signature)) {
621        return true;
622      }
623    }
624
625    // Check for library functions that expose a pointer to an Allocation or
626    // that are not yet annotated with RenderScript-specific tbaa information.
627    static std::vector<std::string> Funcs;
628
629    // rsGetElementAt(...)
630    Funcs.push_back("_Z14rsGetElementAt13rs_allocationj");
631    Funcs.push_back("_Z14rsGetElementAt13rs_allocationjj");
632    Funcs.push_back("_Z14rsGetElementAt13rs_allocationjjj");
633    // rsSetElementAt()
634    Funcs.push_back("_Z14rsSetElementAt13rs_allocationPvj");
635    Funcs.push_back("_Z14rsSetElementAt13rs_allocationPvjj");
636    Funcs.push_back("_Z14rsSetElementAt13rs_allocationPvjjj");
637    // rsGetElementAtYuv_uchar_Y()
638    Funcs.push_back("_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj");
639    // rsGetElementAtYuv_uchar_U()
640    Funcs.push_back("_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj");
641    // rsGetElementAtYuv_uchar_V()
642    Funcs.push_back("_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj");
643
644    for (std::vector<std::string>::iterator FI = Funcs.begin(),
645                                            FE = Funcs.end();
646         FI != FE; ++FI) {
647      llvm::Function *F = M.getFunction(*FI);
648
649      if (!F) {
650        ALOGE("Missing run-time function '%s'", FI->c_str());
651        return true;
652      }
653
654      if (F->getNumUses() > 0) {
655        return true;
656      }
657    }
658
659    return false;
660  }
661
662  /// @brief Connect RenderScript TBAA metadata to C/C++ metadata
663  ///
664  /// The TBAA metadata used to annotate loads/stores from RenderScript
665  /// Allocations is generated in a separate TBAA tree with a "RenderScript TBAA"
666  /// root node. LLVM does assume may-alias for all nodes in unrelated alias
667  /// analysis trees. This function makes the RenderScript TBAA a subtree of the
668  /// normal C/C++ TBAA tree aside of normal C/C++ types. With the connected trees
669  /// every access to an Allocation is resolved to must-alias if compared to
670  /// a normal C/C++ access.
671  void connectRenderScriptTBAAMetadata(llvm::Module &M) {
672    llvm::MDBuilder MDHelper(*C);
673    llvm::MDNode *TBAARenderScript = MDHelper.createTBAARoot("RenderScript TBAA");
674
675    llvm::MDNode *TBAARoot = MDHelper.createTBAARoot("Simple C/C++ TBAA");
676    llvm::MDNode *TBAAMergedRS = MDHelper.createTBAANode("RenderScript", TBAARoot);
677
678    TBAARenderScript->replaceAllUsesWith(TBAAMergedRS);
679  }
680
681  virtual bool runOnModule(llvm::Module &M) {
682    bool Changed = false;
683    this->M = &M;
684    C = &M.getContext();
685    bcinfo::MetadataExtractor me(&M);
686    if (!me.extract()) {
687      ALOGE("Could not extract metadata from module!");
688      return false;
689    }
690    mExportForEachCount = me.getExportForEachSignatureCount();
691    mExportForEachNameList = me.getExportForEachNameList();
692    mExportForEachSignatureList = me.getExportForEachSignatureList();
693
694    bool AllocsExposed = allocPointersExposed(M);
695
696    for (size_t i = 0; i < mExportForEachCount; ++i) {
697      const char *name = mExportForEachNameList[i];
698      uint32_t signature = mExportForEachSignatureList[i];
699      llvm::Function *kernel = M.getFunction(name);
700      if (kernel) {
701        if (bcinfo::MetadataExtractor::hasForEachSignatureKernel(signature)) {
702          Changed |= ExpandKernel(kernel, signature);
703          kernel->setLinkage(llvm::GlobalValue::InternalLinkage);
704        } else if (kernel->getReturnType()->isVoidTy()) {
705          Changed |= ExpandFunction(kernel, signature);
706          kernel->setLinkage(llvm::GlobalValue::InternalLinkage);
707        } else {
708          // There are some graphics root functions that are not
709          // expanded, but that will be called directly. For those
710          // functions, we can not set the linkage to internal.
711        }
712      }
713    }
714
715    if (gEnableRsTbaa && !AllocsExposed) {
716      connectRenderScriptTBAAMetadata(M);
717    }
718
719    return Changed;
720  }
721
722  virtual const char *getPassName() const {
723    return "ForEach-able Function Expansion";
724  }
725
726}; // end RSForEachExpandPass
727
728} // end anonymous namespace
729
730char RSForEachExpandPass::ID = 0;
731
732namespace bcc {
733
734llvm::ModulePass *
735createRSForEachExpandPass(bool pEnableStepOpt){
736  return new RSForEachExpandPass(pEnableStepOpt);
737}
738
739} // end namespace bcc
740